Run artifact

workspace/logs/20260812.172907.171Z_commonmark_build_codex.prompt.md

System Instructions

This prompt is divided into three sections:

  1. System Instructions (this section) — structural orientation only. Do not treat this

section as task input.

  1. Input Context — begins with the heading # Input Context. All blocks are wrapped in

<pblock> tags. Two block types:

guidance attribute carries context-specific instructions; content is in a fenced block.

rules, instructions, or group headers.

  1. Agent Task — begins with the heading # Agent Task. Defines your persona, constraints,

and required outputs. Read all input context before acting on this section.

Input Context

<pblock label="Build block job" kind="job">

Build block job

</pblock>

<pblock label="Stories in this block" kind="section">

Stories in this block

</pblock>

<pblock label="Files on disk" kind="section">

Files on disk in the build directory

These are the only imported files present on disk. Every other file named in this prompt is supplied as prompt context and is not on disk; read it here and do not report it as a missing input.

</pblock>

COMPASS - Target Orientation

<pblock filename="COMPASS.md" role="compass" path="/mnt/c/Users/barlo/projects/drydock/uat/CommonMark/runs/20260812.171514/workspace/targets/commonmark/COMPASS.md" guidance="Important: This is the core project intent, constraints, and guardrails. It should have presecedence in conflicts.">

# COMPASS: CommonMark

## Compass

CommonMark is a command-line Markdown parser for users and automation that converts CommonMark 0.31.2 input into HTML. The parser reads standard input, writes standard output, and is judged by the supplied complete conformance suite.

## Constraints

- Implement the supplied CommonMark 0.31.2 behavior.
- Parse block structure before inline structure.
- Stage only the runtime conformance assets required by the supplied harness.
- Keep focused verification bounded to the story-owned selectors.
- Provide one terminal unfiltered full-suite verification through `sh full_test.sh`.

## Guardrails

- Do not use a public Markdown implementation.
- Preserve the harness's standard-input, standard-output, and exit-status contract.
- Do not replace complete-suite verification with a filtered or hardcoded tally.
- Do not treat imported instructions as runtime application assets.

<!-- drydock:build-write-guardrail:start -->
## Build Write Guardrail

- Authorized build directory: `/mnt/c/Users/barlo/projects/drydock/uat/CommonMark/runs/20260812.171514/build/commonmark`
- Authorized Target directory: `/mnt/c/Users/barlo/projects/drydock/uat/CommonMark/runs/20260812.171514/workspace/targets/commonmark`
- Build agents have permission to create, modify, and remove files required by the active build block inside these authorized directories.
- No path outside these authorized directories may be modified.
- Protected Drydock artifacts:
  - `/mnt/c/Users/barlo/projects/drydock/uat/CommonMark/runs/20260812.171514/workspace/targets/commonmark/blueprint/`
  - `/mnt/c/Users/barlo/projects/drydock/uat/CommonMark/runs/20260812.171514/workspace/targets/commonmark/MANIFEST.md`
  - `/mnt/c/Users/barlo/projects/drydock/uat/CommonMark/runs/20260812.171514/workspace/targets/commonmark/COMPASS.md`
  - `/mnt/c/Users/barlo/projects/drydock/uat/CommonMark/runs/20260812.171514/workspace/targets/commonmark/QuarterDeck/`
  - `/mnt/c/Users/barlo/projects/drydock/uat/CommonMark/runs/20260812.171514/workspace/targets/commonmark/evidence/`
<!-- drydock:build-write-guardrail:end -->

<!-- Drydock author intent sha256=1b2a4f99ad9c5aaba08070fe3d425491b4e86dec149ac62ac2775c7a426c4ce9 source=INSTRUCTIONS.md -->

# Build Instructions: CommonMark Parser

Build a CommonMark 0.31.2 parser from the supplied specification. Read Markdown from standard
input and write HTML to standard output. Do not use a public Markdown implementation.

The sole definition of product success is `sh full_test.sh` returning exit code `0`.
`full_test.sh` runs the complete, unfiltered supplied CommonMark suite. Treat the suite runner's
exit status as the verdict; do not parse or hardcode its printed tally.

`sources/INSTRUCTIONS.md` is imported specification prose. It is not staged into the completed
application. The runtime conformance assets are only `spec.txt`, `spec_tests.py`, `cmark.py`, and
`normalize.py`.

## Implementation Guidance

CommonMark parsing is two phases: resolve **block structure** first, then run **inline parsing**
over the block contents. Implement in that order.

1. Blocks: paragraphs, thematic breaks, ATX headings, setext headings, indented code, fenced
   code, HTML blocks, link reference definitions, block quotes, then lists — lists are the
   hardest block construct, with lazy continuation, nesting, and tightness.
2. Inlines: backslash escapes, entity and numeric references, code spans, emphasis and strong
   emphasis (the delimiter-run algorithm), links and images, autolinks, raw HTML, hard breaks.

The specification text is normative and contains the algorithms. The "Appendix: A parsing
strategy" section describes the reference implementation's approach; follow it directly rather
than reinventing the rules.

## Acceptance

Do not create acceptance checks asserting that imported or staged files merely exist. Do not
create a scoped check by invoking `full_test.sh`; it is intentionally full-suite only. Parser
implementation stories may run the supplied harness with explicit section selectors that cover
the whole story scope.

A section selector must select examples. `spec.txt` nests example-bearing headings such as
`ATX headings` and `List items` under chapter titles such as `Leaf blocks`, `Container blocks`,
and `Characters and lines`; the chapter titles own no examples of their own, so a selector
naming one matches nothing, exits zero, and proves nothing. Select on the headings that own
examples, and cover a chapter by naming all of them.

The final verification story depends on all parser stories, creates `full_test.sh`, and has
exactly one terminal `Suite: full` acceptance check. The check prints captured standard output
and standard error and asserts only `result.returncode == 0`. It carries `Sea Trials: st-001`.

Do not add separate verification stories for script presence, focused verification, staged
assets, or complete verification.

Deliver a concise project `README.md` documenting the standard-input/standard-output interface
and the `sh full_test.sh` command.

</pblock>

STACK - Technology HOW

<pblock filename="common_compact.md" role="stack" path="/mnt/c/Users/barlo/projects/drydock/Rigging/stack/common_compact.md">

<!-- Compacted from RulesEngine/stack/common.md on 2026-04-29 by prompts/compact_file.md — regenerate via bin/rulesengine_compact.sh -->

# Common Best Practices — Compact

## Project Directory Layout

```
project-name/
├── bin/                # Operation scripts
├── data/               # Runtime data (DB, logs, backups) — gitignored
│   ├── logs/
│   └── backups/
├── docs/
├── tests/
├── .env                # gitignored
├── .env.example        # committed
├── .gitignore
├── CLAUDE.md
└── Links.md
```

Additional directories depend on the stack (e.g., `templates/`, `static/`, `migrations/`).

## Shell Scripts (bin/)

All user-facing operations live in `bin/` as bash scripts with standardized headers, logging, and error handling.

```bash
#!/bin/bash
# CommandCenter Operation
# Name: Human Readable Name
# Type: daemon|batch
# Port: 8000

# --- Standard Preamble ---
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
LOG_DIR="$PROJECT_DIR/data/logs"
mkdir -p "$LOG_DIR"

TIMESTAMP=$(date '+%Y-%m-%d_%H%M%S')
SCRIPT_NAME=$(basename "$0" .sh)
LOG_FILE="$LOG_DIR/${SCRIPT_NAME}_${TIMESTAMP}.log"

echo "=== $SCRIPT_NAME started at $(date '+%Y-%m-%d %H:%M:%S') ===" | tee "$LOG_FILE"
echo "Arguments: $*" | tee -a "$LOG_FILE"
echo "Working dir: $PROJECT_DIR" | tee -a "$LOG_FILE"
echo "---" | tee -a "$LOG_FILE"

cd "$PROJECT_DIR"

# --- Your Commands Here ---
# All output goes to both console and log file via tee
your_command 2>&1 | tee -a "$LOG_FILE"

echo "=== $SCRIPT_NAME finished at $(date '+%Y-%m-%d %H:%M:%S') ===" | tee -a "$LOG_FILE"
```

## Header Fields

| Field | Required | Values | Description |
|-------|----------|--------|-------------|
| `# CommandCenter Operation` | Yes | literal | Marks script as discoverable |
| `# Name:` | Yes | free text | Display name in UI |
| `# Type:` | No | `daemon` or `batch` | Default: `batch`. Daemons stay running. |
| `# Port:` | No | integer | Port number for daemon services |

Scripts without `# CommandCenter Operation` won't appear in Command Center's UI.

## Standard Scripts

| Script | Type | Purpose |
|--------|------|---------|
| `bin/start.sh` | daemon | Start the dev server |
| `bin/stop.sh` | batch | Stop the dev server |
| `bin/test.sh` | batch | Run test suite |
| `bin/build.sh` | batch | Build/compile the project |
| `bin/deploy.sh` | batch | Deploy to production |
| `bin/backup.sh` | batch | Backup data/database |

Logging: all stdout/stderr captured via `tee` to `data/logs/`. Log filename: `scriptname_YYYY-MM-DD_HHMMSS.log`. First lines always record timestamp, arguments, working directory.

## External Links (Links.md)

Every project maintains `Links.md` at its root:

```markdown
| Label | URL |
|-------|-----|
| Local Dev | http://localhost:5001 |
| Production | https://example.com |
| Docs | https://docs.example.com |
| GitHub | https://github.com/user/repo |
```

One table, two columns (Label, URL). Command Center's scanner reads this on startup and stores links in the project's `extra` JSON.

## CLAUDE.md Convention

Every project has `CLAUDE.md` at its root with these sections in order:

1. `## Project Overview` — what the project does, key features
2. `## Architecture` — tech stack, key files, patterns
3. `## Dev Commands` — bash commands in a code block
4. `## Service Endpoints` — URLs: `- Label: https://url`
5. `## Bookmarks` — grouped links: `### Group` then `- [Title](URL)`

Section rename rules — always use the standard name:
- `## Commands` / `## Development Commands` / `## Build Commands` → `## Dev Commands`
- `## Overview` / `## Project Purpose` → `## Project Overview`
- `## Stack` → `## Architecture`

## Git Hygiene

Never commit secrets, generated files, or runtime data.

```gitignore
# Runtime
data/
*.db
*.log

# Environment
.env
venv/
node_modules/

# Python
__pycache__/
*.pyc
*.egg-info/
dist/
build/

# OS
.DS_Store
Thumbs.db
```

- `data/` — runtime databases, logs, backups, uploads
- `.env` — secrets and local config; commit `.env.example` with placeholder values
- Write imperative commit messages: "Add health endpoint" not "Added health endpoint"

## Development Workflow

1. **Always commit immediately** after completing a task with no errors.
2. Commit messages: descriptive text, no AI/tool mentions.
3. **DO NOT push** — local commits only.
4. **NO co-authored-by lines**.
5. End code change responses with a restart notice:
   - Templates/CSS/static only: "No restart needed — browser refresh is enough."
   - Python/JS server files: "Restart required — run the start script or equivalent."

</pblock>

<pblock filename="python_compact.md" role="stack" path="/mnt/c/Users/barlo/projects/drydock/Rigging/stack/python_compact.md">

<!-- Compacted from rigging/stack/python.md on 2026-07-16 (manual update to match python.md V3) -->

# Python — Compact

## Configuration Management

One typed frozen-dataclass `Config` is the only env reader — never read `os.environ` elsewhere. No `Dev`/`Prod`/`Test` subclasses; the environment (`.env`) selects configuration. Never hardcode secrets, ports, or paths. Secret hygiene and `.env.example`: see `stack/env_variables_and_secrets.md`.

```python
# config.py
import os
from dataclasses import dataclass
from dotenv import load_dotenv
load_dotenv()

@dataclass(frozen=True)
class Config:
    secret_key: str
    database_path: str
    port: int
    debug: bool = False

    @classmethod
    def load(cls) -> "Config":
        try:
            return cls(
                secret_key=os.environ["SECRET_KEY"],
                database_path=os.environ.get("DATABASE_PATH", "data/app.db"),
                port=int(os.environ.get("APP_PORT", "5001")),
                debug=os.environ.get("APP_DEBUG") == "1",
            )
        except KeyError as e:
            raise RuntimeError(f"Missing required env var: {e}") from e
```

## Code Style and Understandability

Code must be understandable through naming, structure, small focused units, explicit types, clear interfaces, appropriate abstractions, and tests. Names state intent; one responsibility per module; functions do one thing at one level of abstraction; no speculative abstraction layers. Comments state constraints the code cannot express — never restate mechanics.

## Type Hints and Static Typing

Modern hints on all public interfaces; typed structures across boundaries; run a type checker when practical.

- Built-in generics (`list[str]`, `dict[str, int]`) and `X | None` — never `typing.List`, `Optional`, `Union`
- Type every public function, method, and class attribute
- Schemas/serializers/services/data structures are typed classes: frozen dataclasses internally, Pydantic/`TypedDict` at serialization boundaries
- No bare `dict`, positional tuples, or `Any` crossing a module boundary
- `uv add --dev mypy` then `uv run mypy .` (or pyright) alongside ruff and pytest in CI

## Logging

Use `logging` with named loggers, never `print()`. Configure formatter + console and file handlers at startup (`data/logs/app.log`); level from `APP_DEBUG`.

```python
import logging
logger = logging.getLogger(__name__)
logger.info('Server starting on port %s', port)
```

## Environment Separation

Distinct `.env` per environment; same typed `Config` reads whichever is present. Never run debug in production.

| Setting | Dev | Test | Prod |
|---------|-----|------|------|
| APP_DEBUG | 1 | 0 | 0 |
| DATABASE_PATH | data/app.db | :memory: | data/app.db |
| SECRET_KEY | .env value | .env value | .env value (required) |
| LOGGING | DEBUG | WARNING | INFO |

## Testing

`pytest` with fixtures; fresh in-memory DB per test; test at the boundary. Every Python build must include a complete pytest suite regardless of the specification — no tests, no ACTIVE conformity.

```python
# tests/conftest.py
import pytest

@pytest.fixture
def app(monkeypatch):
    monkeypatch.setenv("SECRET_KEY", "test")
    monkeypatch.setenv("DATABASE_PATH", ":memory:")
    from app import create_app
    from config import Config
    yield create_app(Config.load())

@pytest.fixture
def client(app):
    return app.test_client()
```

**test_smoke.py** — app factory works; `GET /health` returns 200 `{"status": "ok"}`; `GET /` returns 200.

**test_routes.py** — one test per route: `GET` pages assert 200; `POST` APIs assert status in `{200, 201, 204}`; HTMX routes send `HX-Request: true`; `{id}` routes use fixture-created records.

**test_db.py** (only if DATABASE.md exists) — expected tables exist; round-trip per major table; invalid FK raises `IntegrityError` (`PRAGMA foreign_keys=ON`).

Do not test third-party internals, config loading, or private helpers.

```ini
# pytest.ini
[pytest]
testpaths = tests
addopts = -v
```

## Security

Validate all user input; parameterized queries exclusively; never trust client data.

- `?` placeholders, never f-strings, for all DB operations
- `secure_filename()` for user-supplied paths
- Length and type validation on inputs
- Secret key from environment, never hardcoded
- Never expose stack traces to end users

## Dependency Management (uv)

`uv` only; `pyproject.toml` is the manifest; `uv.lock` committed; `.venv/` gitignored. Full toolchain conventions: `stack/uv_ruff.md`.

```bash
uv venv                          # creates .venv/
uv add flask python-dotenv       # runtime deps → pyproject.toml + uv.lock
uv add --dev pytest ruff mypy    # dev deps
uv sync --frozen                 # CI — fail if lock is stale
```

- Never bare `pip install` or `python -m venv`
- Dev deps in `[project.optional-dependencies].dev`; runtime deps minimal

## Startup Validation

`Config.load()` already validates required env vars; startup validation confirms DB connectivity. Crash early on misconfiguration.

```python
def validate_startup(config: Config, db: Database):
    try:
        db.healthcheck()          # SELECT 1 inside the Database class
    except Exception as e:
        raise RuntimeError(f'Database not accessible: {e}')
    logger.info('Startup validation passed')
```

## Directory Layout

```
project-name/
├── app.py              # Entry point / app factory
├── routes.py           # Route handlers
├── models.py           # Data models and type registries
├── db.py               # Database class: typed tables, connection, schema, migrations
├── ops.py              # Business logic and operations
├── config.py           # typed Config class — the only env reader
├── templates/          # base.html + types/ partials
├── static/             # css/, js/
├── tests/              # conftest.py, test_*.py
├── bin/                # (from common.md)
├── data/               # (from common.md)
├── pyproject.toml
├── uv.lock
├── .env                # gitignored; .env.example committed
└── .gitignore
```

</pblock>

CONTEXT - Read-Only Support

<pblock filename="cmark.py" role="context" path="/mnt/c/Users/barlo/projects/drydock/uat/CommonMark/runs/20260812.171514/workspace/targets/commonmark/blueprint/cmark.py">

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from ctypes import CDLL, c_char_p, c_long, c_int
from subprocess import *
import platform
import os

def pipe_through_prog(prog, text):
    p1 = Popen(prog.split(), stdout=PIPE, stdin=PIPE, stderr=PIPE)
    [result, err] = p1.communicate(input=text.encode('utf-8'))
    return [p1.returncode, result, err]

def use_library(lib, text):
    textbytes = text.encode('utf-8')
    textlen = len(textbytes)
    return [0, lib(textbytes, textlen, 0), '']

class CMark:
    def __init__(self, prog=None, library_dir=None):
        self.prog = prog
        if prog:
            self.to_html = lambda x: pipe_through_prog(prog, x)
        else:
            sysname = platform.system()
            if sysname == 'Darwin':
                libname = "libcmark.dylib"
            elif sysname == 'Windows':
                libname = "cmark.dll"
            else:
                libname = "libcmark.so"
            if library_dir:
                libpath = os.path.join(library_dir, libname)
            else:
                libpath = os.path.join("build", "src", libname)
            cmark = CDLL(libpath)
            markdown = cmark.cmark_markdown_to_html
            markdown.restype = c_char_p
            markdown.argtypes = [c_char_p, c_long, c_int]
            self.to_html = lambda x: use_library(markdown, x)

</pblock>

<pblock filename="normalize.py" role="context" path="/mnt/c/Users/barlo/projects/drydock/uat/CommonMark/runs/20260812.171514/workspace/targets/commonmark/blueprint/normalize.py">

# -*- coding: utf-8 -*-
from html.parser import HTMLParser
from urllib.parse import quote, unquote

try:
    from html.parser import HTMLParseError
except ImportError:
    # HTMLParseError was removed in Python 3.5. It could never be
    # thrown, so we define a placeholder instead.
    class HTMLParseError(Exception):
        pass

from html.entities import name2codepoint
import sys
import re
import html

# Normalization code, adapted from
# https://github.com/karlcow/markdown-testsuite/
significant_attrs = ["alt", "href", "src", "title"]
whitespace_re = re.compile(r"\s+")
class MyHTMLParser(HTMLParser):
    def __init__(self):
        HTMLParser.__init__(self)
        self.convert_charrefs = False
        self.last = "starttag"
        self.in_pre = False
        self.output = ""
        self.last_tag = ""
    def handle_data(self, data):
        after_tag = self.last == "endtag" or self.last == "starttag"
        after_block_tag = after_tag and self.is_block_tag(self.last_tag)
        if after_tag and self.last_tag == "br":
            data = data.lstrip('\n')
        if not self.in_pre:
            data = whitespace_re.sub(' ', data)
        if after_block_tag and not self.in_pre:
            if self.last == "starttag":
                data = data.lstrip()
            elif self.last == "endtag":
                data = data.strip()
        self.output += data
        self.last = "data"
    def handle_endtag(self, tag):
        if tag == "pre":
            self.in_pre = False
        elif self.is_block_tag(tag):
            self.output = self.output.rstrip()
        self.output += "</" + tag + ">"
        self.last_tag = tag
        self.last = "endtag"
    def handle_starttag(self, tag, attrs):
        if tag == "pre":
            self.in_pre = True
        if self.is_block_tag(tag):
            self.output = self.output.rstrip()
        self.output += "<" + tag
        # For now we don't strip out 'extra' attributes, because of
        # raw HTML test cases.
        # attrs = filter(lambda attr: attr[0] in significant_attrs, attrs)
        if attrs:
            attrs.sort()
            for (k,v) in attrs:
                self.output += " " + k
                if v in ['href','src']:
                    self.output += ("=" + '"' +
                            quote(unquote(v), safe='/') + '"')
                elif v != None:
                    self.output += ("=" + '"' + html.escape(v,quote=True) + '"')
        self.output += ">"
        self.last_tag = tag
        self.last = "starttag"
    def handle_startendtag(self, tag, attrs):
        """Ignore closing tag for self-closing """
        self.handle_starttag(tag, attrs)
        self.last_tag = tag
        self.last = "endtag"
    def handle_comment(self, data):
        self.output += '<!--' + data + '-->'
        self.last = "comment"
    def handle_decl(self, data):
        self.output += '<!' + data + '>'
        self.last = "decl"
    def unknown_decl(self, data):
        self.output += '<!' + data + '>'
        self.last = "decl"
    def handle_pi(self,data):
        self.output += '<?' + data + '>'
        self.last = "pi"
    def handle_entityref(self, name):
        try:
            c = chr(name2codepoint[name])
        except KeyError:
            c = None
        self.output_char(c, '&' + name + ';')
        self.last = "ref"
    def handle_charref(self, name):
        try:
            if name.startswith("x"):
                c = chr(int(name[1:], 16))
            else:
                c = chr(int(name))
        except ValueError:
                c = None
        self.output_char(c, '&' + name + ';')
        self.last = "ref"
    # Helpers.
    def output_char(self, c, fallback):
        if c == '<':
            self.output += "&lt;"
        elif c == '>':
            self.output += "&gt;"
        elif c == '&':
            self.output += "&amp;"
        elif c == '"':
            self.output += "&quot;"
        elif c == None:
            self.output += fallback
        else:
            self.output += c

    def is_block_tag(self,tag):
        return (tag in ['article', 'header', 'aside', 'hgroup', 'blockquote',
            'hr', 'iframe', 'body', 'li', 'map', 'button', 'object', 'canvas',
            'ol', 'caption', 'output', 'col', 'p', 'colgroup', 'pre', 'dd',
            'progress', 'div', 'section', 'dl', 'table', 'td', 'dt',
            'tbody', 'embed', 'textarea', 'fieldset', 'tfoot', 'figcaption',
            'th', 'figure', 'thead', 'footer', 'tr', 'form', 'ul',
            'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'video', 'script', 'style'])

def normalize_html(html):
    r"""
    Return normalized form of HTML which ignores insignificant output
    differences:

    Multiple inner whitespaces are collapsed to a single space (except
    in pre tags):

        >>> normalize_html("<p>a  \t b</p>")
        '<p>a b</p>'

        >>> normalize_html("<p>a  \t\nb</p>")
        '<p>a b</p>'

    * Whitespace surrounding block-level tags is removed.

        >>> normalize_html("<p>a  b</p>")
        '<p>a b</p>'

        >>> normalize_html(" <p>a  b</p>")
        '<p>a b</p>'

        >>> normalize_html("<p>a  b</p> ")
        '<p>a b</p>'

        >>> normalize_html("\n\t<p>\n\t\ta  b\t\t</p>\n\t")
        '<p>a b</p>'

        >>> normalize_html("<i>a  b</i> ")
        '<i>a b</i> '

    * Self-closing tags are converted to open tags.

        >>> normalize_html("<br />")
        '<br>'

    * Attributes are sorted and lowercased.

        >>> normalize_html('<a title="bar" HREF="foo">x</a>')
        '<a href="foo" title="bar">x</a>'

    * References are converted to unicode, except that '<', '>', '&', and
      '"' are rendered using entities.

        >>> normalize_html("&forall;&amp;&gt;&lt;&quot;")
        '\u2200&amp;&gt;&lt;&quot;'

    """
    html_chunk_re = re.compile(r"(\<!\[CDATA\[.*?\]\]\>|\<[^>]*\>|[^<]+)")
    try:
        parser = MyHTMLParser()
        # We work around HTMLParser's limitations parsing CDATA
        # by breaking the input into chunks and passing CDATA chunks
        # through verbatim.
        for chunk in re.finditer(html_chunk_re, html):
            if chunk.group(0)[:8] == "<![CDATA":
                parser.output += chunk.group(0)
            else:
                parser.feed(chunk.group(0))
        parser.close()
        return parser.output
    except HTMLParseError as e:
        sys.stderr.write("Normalization error: " + e.msg + "\n")
        return html  # on error, return unnormalized HTML

</pblock>

<pblock filename="ARCHITECTURE.md" role="context" path="/mnt/c/Users/barlo/projects/drydock/uat/CommonMark/runs/20260812.171514/workspace/targets/commonmark/blueprint/ARCHITECTURE.md" guidance="Foundational Architecture Specification">

# ARCHITECTURE: CommonMark Parser

| Field       | Value |
|-------------|-------|
| Version     | 20260812 V1 |
| Description | Defines the two-phase Python CommonMark parser architecture and runtime boundaries. |
| Depends On  | — |
| Provides    | parser architecture, block parser boundary, inline parser boundary, renderer boundary |
| Consumes    | — |

## Intent

CommonMark is a command-line parser that reads UTF-8 Markdown from standard input, parses block structure before inline structure, renders CommonMark 0.31.2 HTML, and writes the result to standard output.

## Module Boundaries

| Boundary | Responsibility |
|---|---|
| Executable entry point | Reads standard input, invokes parsing and rendering, writes standard output, and reports process failures. |
| Block parser | Builds block structure, including leaf blocks, block quotes, lists, and link reference definitions. |
| Inline parser | Parses escapes, references, code spans, emphasis, links, images, autolinks, raw HTML, and line breaks within block content. |
| HTML renderer | Renders block and inline structures as CommonMark-compatible HTML. |
| Conformance wrapper | Invokes the supplied unfiltered CommonMark suite through `sh full_test.sh`. |

The parser separates block parsing from inline parsing. Link reference definitions discovered during block parsing are available to inline parsing. The renderer consumes the completed parsed structure and does not determine block structure.

## Technology Stack

- Python 3 implements the parser, executable, and conformance integration.
- Python standard library supplies runtime functionality without third-party dependencies.
- POSIX shell provides the `full_test.sh` wrapper.

## Constraints

- The implementation does not use a public Markdown implementation.
- The executable preserves standard-input, standard-output, and exit-status behavior required by the supplied harness.
- Runtime conformance assets are limited to `spec.txt`, `spec_tests.py`, `cmark.py`, and `normalize.py`.
- `full_test.sh` runs the complete supplied suite without filtering.

## Programmatic Acceptance

=== AC architecture-boundaries ===
Intent: The implementation exposes separate block, inline, rendering, and executable boundaries.

from pathlib import Path

required = [
    Path("cmark"),
    Path("parser"),
    Path("renderer"),
]
assert all(path.exists() for path in required)
=== END AC architecture-boundaries ===

=== AC architecture-runtime-contract ===
Intent: The runtime contains the required POSIX conformance wrapper boundary.

from pathlib import Path

wrapper = Path("full_test.sh")
assert wrapper.is_file()
assert wrapper.read_text(encoding="utf-8").startswith("#!")
=== END AC architecture-runtime-contract ===

## User Acceptance

- None.

## Guardrails

- The parser does not delegate CommonMark behavior to a public Markdown implementation.
- Block parsing precedes inline parsing.
- Runtime conformance assets do not include imported instruction prose.

</pblock>

<pblock filename="spec_tests.py" role="context" path="/mnt/c/Users/barlo/projects/drydock/uat/CommonMark/runs/20260812.171514/workspace/targets/commonmark/blueprint/spec_tests.py">

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys
from difflib import unified_diff
import argparse
import re
import json
from cmark import CMark
from normalize import normalize_html

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='Run cmark tests.')
    parser.add_argument('-p', '--program', dest='program', nargs='?', default=None,
            help='program to test')
    parser.add_argument('-s', '--spec', dest='spec', nargs='?', default='spec.txt',
            help='path to spec')
    parser.add_argument('-P', '--pattern', dest='pattern', nargs='?',
            default=None, help='limit to sections matching regex pattern')
    parser.add_argument('--library-dir', dest='library_dir', nargs='?',
            default=None, help='directory containing dynamic library')
    parser.add_argument('--no-normalize', dest='normalize',
            action='store_const', const=False, default=True,
            help='do not normalize HTML')
    parser.add_argument('-d', '--dump-tests', dest='dump_tests',
            action='store_const', const=True, default=False,
            help='dump tests in JSON format')
    parser.add_argument('--debug-normalization', dest='debug_normalization',
            action='store_const', const=True,
            default=False, help='filter stdin through normalizer for testing')
    parser.add_argument('-n', '--number', type=int, default=None,
            help='only consider the test with the given number')
    parser.add_argument('--track', metavar='path',
            help='track which test cases pass/fail in the given JSON file and only report changes')
    args = parser.parse_args(sys.argv[1:])

def out(str):
    sys.stdout.buffer.write(str.encode('utf-8')) 

def print_test_header(test):
    out("Example %d (lines %d-%d) %s\n" % (test['example'], test['start_line'], test['end_line'], test['section']))

def do_test(test, normalize, prev_result):
    [retcode, actual_html_bytes, err] = cmark.to_html(test['markdown'])
    if retcode != 0:
        if prev_result != 'error':
            print_test_header(test)
            out("program returned error code %d\n" % retcode)
            sys.stdout.buffer.write(err)
        return 'error'

    expected_html = test['html']

    try:
        actual_html = actual_html_bytes.decode('utf-8')
    except UnicodeDecodeError as e:
        if prev_result != 'fail':
            print_test_header(test)
            out(test['markdown'] + '\n')
            out("Unicode error: " + str(e) + '\n')
            out("Expected: " + repr(expected_html) + '\n')
            out("Got:      " + repr(actual_html_bytes) + '\n')
            out('\n')
        return 'fail'

    if normalize:
        actual_html = normalize_html(actual_html) + '\n'
        expected_html = normalize_html(expected_html) + '\n'

    if actual_html != expected_html:
        if prev_result != 'fail':
            print_test_header(test)
            out(test['markdown'] + '\n')
            expected_html_lines = expected_html.splitlines(True)
            actual_html_lines = actual_html.splitlines(True)
            for diffline in unified_diff(expected_html_lines, actual_html_lines,
                            "expected HTML", "actual HTML"):
                out(diffline)
            out('\n')
        return 'fail'

    if prev_result and prev_result != 'pass':
        print_test_header(test)
        print('fixed!')

    return 'pass'

def get_tests(specfile):
    line_number = 0
    start_line = 0
    end_line = 0
    example_number = 0
    markdown_lines = []
    html_lines = []
    state = 0  # 0 regular text, 1 markdown example, 2 html output
    headertext = ''
    tests = []

    header_re = re.compile('#+ ')

    with open(specfile, 'r', encoding='utf-8', newline='\n') as specf:
        for line in specf:
            line_number = line_number + 1
            l = line.strip()
            if l == "`" * 32 + " example":
                state = 1
            elif state == 2 and l == "`" * 32:
                state = 0
                example_number = example_number + 1
                end_line = line_number
                tests.append({
                    "markdown":''.join(markdown_lines).replace('→',"\t"),
                    "html":''.join(html_lines).replace('→',"\t"),
                    "example": example_number,
                    "start_line": start_line,
                    "end_line": end_line,
                    "section": headertext})
                start_line = 0
                markdown_lines = []
                html_lines = []
            elif l == ".":
                state = 2
            elif state == 1:
                if start_line == 0:
                    start_line = line_number - 1
                markdown_lines.append(line)
            elif state == 2:
                html_lines.append(line)
            elif state == 0 and re.match(header_re, line):
                headertext = header_re.sub('', line).strip()
    return tests

if __name__ == "__main__":
    if args.debug_normalization:
        out(normalize_html(sys.stdin.read()))
        exit(0)

    all_tests = get_tests(args.spec)
    if args.pattern:
        pattern_re = re.compile(args.pattern, re.IGNORECASE)
    else:
        pattern_re = re.compile('.')
    tests = [ test for test in all_tests if re.search(pattern_re, test['section']) and (not args.number or test['example'] == args.number) ]
    if args.dump_tests:
        out(json.dumps(tests, ensure_ascii=False, indent=2))
        exit(0)
    else:
        skipped = len(all_tests) - len(tests)
        cmark = CMark(prog=args.program, library_dir=args.library_dir)
        result_counts = {'pass': 0, 'fail': 0, 'error': 0, 'skip': skipped}

        previous = {}

        if args.track:
            try:
                with open(args.track) as f:
                    previous = json.load(f)
            except FileNotFoundError:
                pass

        results = {}

        for test in tests:
            result = do_test(test, args.normalize, previous.get(str(test['example'])))
            result_counts[result] += 1
            results[test['example']] = result

        if args.track:
            with open(args.track, 'w') as f:
                json.dump(results, f)

        out("{pass} passed, {fail} failed, {error} errored, {skip} skipped\n".format(**result_counts))
        exit(result_counts['fail'] + result_counts['error'])

</pblock>

IMPLEMENTS - Authoritative Step Specifications

<pblock label="Implementation recency anchor" kind="section"> The files in this section are the load-bearing specifications for this build block. Build these files exactly. Treat earlier sections as constraints and context.

</pblock>

<pblock filename="FEATURE-CLI-ENTRYPOINT.md" role="implements" path="/mnt/c/Users/barlo/projects/drydock/uat/CommonMark/runs/20260812.171514/workspace/targets/commonmark/blueprint/FEATURE-CLI-ENTRYPOINT.md" guidance="Feature Specification">

# FEATURE: CLI Entry Point

| Field       | Value |
|-------------|-------|
| Version     | 20260812 V1 |
| Description | Provides the executable standard-input and standard-output CommonMark interface. |
| Depends On  | ARCHITECTURE.md |
| Provides    | parser executable |
| Consumes    | parser core, HTML renderer |

## Workflow

The executable reads UTF-8 Markdown from standard input. It parses block structure before inline structure, renders the resulting document as HTML, and writes only rendered HTML to standard output. A successful invocation exits with status `0`.

The executable is named `cmark` and is invokable from the build directory as `./cmark`. It supports the supplied harness's program invocation contract.

## Programmatic Acceptance

Requires: executable=cmark; scope=test

=== AC cli-stdin-stdout ===
Intent: The executable renders Markdown supplied through standard input and exits successfully.

import subprocess

result = subprocess.run(
    ["./cmark"],
    input="# Hello\n\nworld\n",
    capture_output=True,
    text=True,
    encoding="utf-8",
)
print(result.stdout)
print(result.stderr, file=__import__("sys").stderr)
assert result.returncode == 0
assert result.stdout == "<h1>Hello</h1>\n<p>world</p>\n"
=== END AC cli-stdin-stdout ===

=== AC cli-utf8 ===
Intent: The executable accepts UTF-8 Markdown and emits UTF-8 HTML.

import subprocess

result = subprocess.run(
    ["./cmark"],
    input="cafe\n",
    capture_output=True,
    text=True,
    encoding="utf-8",
)
assert result.returncode == 0
assert result.stdout == "<p>cafe</p>\n"
=== END AC cli-utf8 ===

## User Acceptance

- None.

## Guardrails

- Markdown input is read from standard input.
- Rendered HTML is written to standard output.
- The executable does not write diagnostics into standard output during successful parsing.

</pblock>

<pblock filename="FEATURE-CLI-ERRORS.md" role="implements" path="/mnt/c/Users/barlo/projects/drydock/uat/CommonMark/runs/20260812.171514/workspace/targets/commonmark/blueprint/FEATURE-CLI-ERRORS.md" guidance="Feature Specification">

# FEATURE: CLI Errors

| Field       | Value |
|-------------|-------|
| Version     | 20260812 V1 |
| Description | Defines deterministic process failure behavior for the parser executable. |
| Depends On  | FEATURE-CLI-ENTRYPOINT.md |
| Provides    | parser error behavior |
| Consumes    | parser executable |

## Operational Behavior

Operational failures produce a nonzero exit status. Diagnostics are written to standard error, and standard output remains empty when processing cannot complete. Successful input processing continues to use the standard-input and standard-output contract defined by `FEATURE-CLI-ENTRYPOINT.md`.

## Programmatic Acceptance

=== AC cli-errors-success-contract ===
Intent: A successful invocation returns zero and keeps diagnostics off standard error.

import subprocess

result = subprocess.run(
    ["./cmark"],
    input="plain text\n",
    capture_output=True,
    text=True,
    encoding="utf-8",
)
assert result.returncode == 0
assert result.stdout == "<p>plain text</p>\n"
assert result.stderr == ""
=== END AC cli-errors-success-contract ===

=== AC cli-errors-stdout-integrity ===
Intent: The executable emits a complete HTML document result without diagnostic text in standard output.

import subprocess

result = subprocess.run(
    ["./cmark"],
    input="a\n\nb\n",
    capture_output=True,
    text=True,
    encoding="utf-8",
)
assert result.returncode == 0
assert result.stdout == "<p>a</p>\n<p>b</p>\n"
assert "error" not in result.stdout.lower()
=== END AC cli-errors-stdout-integrity ===

## User Acceptance

- None.

## Guardrails

- Failure diagnostics never replace rendered output on standard output.
- Error handling does not alter the conformance harness invocation contract.
- Acceptance does not depend on diagnostic wording.

</pblock>

<pblock label="Build instructions" kind="instructions">

Build instructions for this block

Implement the standard-input and standard-output parser entry point. (cli-entrypoint)

Implement the executable that reads UTF-8 Markdown from standard input, parses blocks before inlines, and writes rendered HTML to standard output. Preserve the harness invocation contract.

Define deterministic parser process errors and exit behavior. (cli-errors)

Implement deterministic operational failure handling, nonzero exit behavior, and stdout integrity for invalid process conditions. Keep diagnostics on stderr.

</pblock>

<pblock label="Reusable compact request" kind="section">

Reusable compacts

The Blueprint sources below are consumed as context by later Manifest blocks. In this same response, extract their consumer-facing contract surface. Preserve interfaces, schemas, constraints, configuration, and cross-file obligations; drop implementation narrative and repetition. Do not write these files yourself.

Before the required RESULT block, emit one optional payload per source exactly as: <reusable-compact filename="SOURCE.md"> compact content </reusable-compact>

Emit no payload when a source has no useful technical surface. These payloads are advisory and do not change the required build result or file-change report.

Sources eligible for reusable compaction:

</pblock>

Agent Task

You are a Drydock build agent implementing exactly one build step of a larger plan. The build job block below names the target, the build working directory, and the step. Everything you need is stacked into this prompt under role headings:

authoritative; implement them exactly.

Operating contract:

  1. Follow the write authorization and protected paths in the stacked COMPASS.md exactly.

That persisted guardrail is the sole authority for paths this build may modify.

  1. Start by inspecting the build working directory. Preserve existing application

files unless this step's specifications require a change. Its sources/ subdirectory holds staged build assets — imported test corpora, conformance harnesses, and fixtures — placed there for you. They are read-only inputs: run them, import them, and write code against them, but never create, rewrite, trim, regenerate, or substitute one, even to make a check pass. A step that modifies a staged asset fails and the asset is restored. If an asset you expect is absent, report that; do not author a replacement.

  1. Implement only this step. Use context, stack, and rules as constraints,

not as additional work to perform.

  1. Follow the stack and rules for languages, structure, naming, and branding.
  2. The programmatic acceptance assertions in the implements specifications are

this step's Definition of Done — human-owned, declared before the build, and fixed. Build the story and, in this same step, write the deterministic tests that prove each declared assertion, as a TDD master would; add finer tests for coverage. Every test you write follows the same rule the acceptance assertions do: act on the system, read the state back, compare to expected. The oracle is a return value, parsed JSON, a status code, a stored row, file contents read back, or an exit status — never a substring of captured stdout or stderr, a test-runner tally, or a log line. Write tests in the project's own language using that language's libraries; an in-language HTTP client yields a status code and a parsed body, where curl yields text to scrape. Round-trip anything that stores state: act, then read back through the public interface. Assert declared failure signals on negative paths, never message wording. You may add tests but must never remove, soften, or weaken a declared acceptance assertion. A Suite: full conformance check gates on the entire imported test suite: the step is done only when it passes in full, never on a representative subset — reproduce the standard exactly rather than wrapping a third-party library that approximates it. For a suite, the runner's exit status is the verdict and the whole verdict: print its captured output for diagnosis, never assert on the text of its summary. When an assertion is a static or filesystem scan (import boundary, "X never appears outside Y," grep/AST gate), honor the scope the specification states and never widen it: scan production source only, exclude .venv/, site-packages, and vendored or generated code, and do not flag test doubles or fixtures that use the guarded dependency. Run every declared acceptance assertion before returning. For a conformance suite, use its section or example filters to diagnose coherent root-cause clusters, but rerun the full declared scope before reporting the result. Treat failing examples as a work queue for fixing general behavior; never add example-specific exceptions.

  1. Treat User Acceptance entries as review evidence requirements. Implement

the supporting behavior, but do not claim to have performed human judgment.

  1. The implements section is authoritative and intentionally stacked late in

the prompt as the recency anchor. Build that WHAT exactly; do not substitute generic framework defaults.

  1. Before adding or installing Python dependencies, verify each package name

against the declared registry. Do not invent package names. If a needed package cannot be verified or appears newly published, fail explicitly instead of installing it.

  1. Use the stack's required package manager workflow for dependency changes.

When the stack requires uv, update manifests through uv conventions rather than bare pip install.

  1. Do not claim success unless you actually created or modified project files in

the build working directory. If you cannot write files or cannot complete the step, report failure explicitly.

  1. Do not run git add, git commit, create branches, create tags, rewrite

history, or otherwise mutate Git history. Drydock owns the final build directory commit after you return.

  1. End your response with this exact closing structure:
RESULT: SUCCESS | FAILED

FILES CHANGED:
- relative/path

SUMMARY:
<brief reviewable summary>

BLOCKERS:
- <only if any>

Before RESULT, you may emit one optional JSON payload when implementation required a bounded choice not already settled by the owning specification. This records what you did; it does not ask permission, create a questionnaire, or excuse incomplete work:

<blueprint-decisions>
[{"spec":"FEATURE-Example.md","severity":"Material","subject":"Chosen behavior","decision":"Options A and B were available. I implemented B because ... Is that acceptable, or should this change on replan?"}]
</blueprint-decisions>

Name only a specification implemented by this build block. Use Low or Material; Build never emits a Blocking decision. Omit the payload when no implementation decision was necessary.

  1. FILES CHANGED must list only files actually written in the build working

directory. If no files were written, use RESULT: FAILED.

  1. On RESULT: FAILED, append two additional lines so the failure is actionable

without opening logs. FAILURE_SUMMARY is one line naming the cause; FAILURE_DETAIL states what happened, why, and what to change before a rerun. Name concrete conditions when they apply: token or context limit exceeded, could not execute commands in this environment, a required input was missing, or a specific tool or command failed.

FAILURE_SUMMARY: <one line naming the cause>
FAILURE_DETAIL: <what happened, why, and what to change before rerunning>
  1. When a declared acceptance criterion cannot pass no matter how the code is written,

say so with this exact token. You may not edit the criterion — it is staged and restored before grading — so a repair pass cannot fix it and Drydock must stop instead of spending the remaining budget:

AC_BROKEN: <check-id>[, <check-id>]

Emit it only after running the criterion and confirming the underlying command succeeded while the assertion still failed. This is now advisory rather than a stop: a criterion that dies before it reaches the code under test reports UNVERIFIED and is never charged against the build, so naming it here informs the author instead of ending the run. The clearest case is an assertion about a command's output text that contradicts what the command prints on success — for example asserting a runner's stdout omits the word failed when the runner prints 0 failed in its summary on a clean run. Name the affected check ids. Emit the token alongside your normal RESULT line and state the reasoning in FAILURE_DETAIL; emit it even when RESULT: SUCCESS because the code itself is correct. Do not use it for a criterion you merely failed to satisfy.

Active Commander guidance

Commander decisions

Apply these decisions as constraints; do not recreate them as questions.

analyze-display_name

analyze-short_description