Skip to content

feat(stage5): label-strip retry for package overview diagrams#60

Merged
RichardHightower merged 1 commit into
mainfrom
feat/stage5-strip-labels-retry
May 12, 2026
Merged

feat(stage5): label-strip retry for package overview diagrams#60
RichardHightower merged 1 commit into
mainfrom
feat/stage5-strip-labels-retry

Conversation

@RichardHightower
Copy link
Copy Markdown
Contributor

Summary

When Stage 5's merged per-package overview diagram fails mmdc validation, retry once with every arrow label stripped. If the stripped diagram passes, write it; otherwise stay fail-soft.

Why

PR #58 brought per-package overview diagrams to package READMEs. The agent-brain dogfood reached 22/24 packages — the config package missed out because one of its arrow labels contained ; and (), which mermaid's parser rejects:

Settings ..> ValidationError : calls get_api_key(); raises ValidationError

Mermaid's relationship-label grammar is fiddlier than its node grammar — ; is rejected, () is sometimes rejected, and quoting rules are undocumented. The per-class diagrams pass mmdc individually because each has only a few simple arrows; merging 11 of them stacks enough exotic labels that one breaks the whole parse.

Aggressive label stripping is the universal escape hatch: the retry's "boxes + bare arrows" output is less informative than a labelled diagram, but it ships rather than getting dropped, and on the agent-brain run this turns 22/24 into 24/24.

Closes #59.

Changes

  • src/designdoc/stages/s5_mermaid.py
    • New _strip_arrow_labels(diagram_text) helper: drops everything after : on lines containing a mermaid classDiagram arrow op (and not starting with class ). Class-body : is preserved.
    • _emit_package_diagrams: after validate(merged) fails, retry once with stripped labels. Write the stripped form if it passes; otherwise unchanged fail-soft continue.
  • tests/unit/test_stage5_package_diagrams.py
    • 5 new tests covering the helper (3 cases) and the retry wiring (2 cases — success path + retry-also-fails fail-soft path). Validation is mocked via monkeypatch so the retry control flow is pinned independently of mmdc version quirks.

Invariants

  • MAX_ATTEMPTS=3 preserved (loop.py unchanged)
  • Checker isolation preserved (no doer/checker context bridging)
  • Schema-validated verdicts / fail-loud preserved
  • Mermaid two-checker (mmdc + LLM) preserved — mmdc still gates every write; the retry just gives mmdc a second, weaker candidate to validate before falling back to fail-soft
  • HIL fallback preserved

Verification

  • task ci green locally (107 passed in 53.95s — lint + unit + integration including test_stage5_appends_package_overview_diagram_to_readme)
  • New tests cover the change (helper + retry wiring + fail-soft-still-works)
  • TWRC discipline followed (RED with ImportError: _strip_arrow_labels → implementation → GREEN)

Related

…d — closes #59

Stage 5 emits a per-package overview diagram by merging each package's
per-class classDiagrams. On the agent-brain dogfood, one package (`config`)
ended up diagram-less because a single relationship label contained `;` and
`()`, which mermaid's parser rejected.

When validate() rejects the first merge, retry once with every arrow
label stripped (everything after `:` on relationship lines). If the
stripped form passes mmdc, write it. If it also fails, fall back to the
existing fail-soft path (leave the README untouched).

The retry result is "boxes + bare arrows" — less informative than a
labelled diagram, but it ships rather than getting dropped. mmdc's label
grammar has enough fragile edge cases (semicolons, parens, quoting) that
aggressive stripping is the right universal escape hatch.

Unit coverage:
  * _strip_arrow_labels helper: strips arrow labels, leaves unlabelled
    arrows alone, preserves class-body `:` (e.g. `+bar: str`).
  * _emit_package_diagrams: retries with stripped labels when first
    validate fails; stays fail-soft when retry also fails.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@RichardHightower RichardHightower merged commit 9200d74 into main May 12, 2026
2 checks passed
@RichardHightower RichardHightower deleted the feat/stage5-strip-labels-retry branch May 12, 2026 13:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Stage 5: label-strip retry for package-overview diagrams that fail mmdc

1 participant