feat(init): atomic-agents init wizard PR 2 of 2 — researcher + writer + Add-to-it#323
Merged
Conversation
…ndments (MUST 4/5/7/11 + new MUST 15)
spec/28 amends action class glosses: web search HTTP GETs are
explicitly classified read_only because they do not change external
state. Aligns with the framework's external_side_effect definition
('sending email, posting messages, anything the world sees'). Locked
in PR 2 via AskUserQuestion gate (P1). Researcher template uses the
same Cautious preset as advisor without paying judge_required overhead
on every search query.
spec/35 amendments:
- MUST 4 expands to require path validation via safe_resolve_under
AND fresh-write cleanup on failure AND staging-dir rule for
Add-to-it
- MUST 5 expands to the full Add-to-it staging-dir commit contract:
render to .new.<ts>, backup existing to .bak.<ts>, rename .new to
agent_dir, on success rmtree .bak / failure restore .bak. KI handler
detects half-committed state and completes restoration.
- MUST 7 carved out for --from-template and --list-templates per P3
AskUserQuestion: template scaffold writes file content only, no LLM
call. CI users do not need ANTHROPIC_API_KEY at scaffold time.
- MUST 11 amends entry guards: --list-templates MUST enumerate all
--from-template choices and stay in sync across PRs.
- New MUST 15: section-detection contract for Add-to-it. ATX h2
regex, skips fences + comments + frontmatter, fail-closed when
schema does not match, backfill missing files, preserve operator
orphan sections and h3+ subsections.
spec/35 MUST count: 14 to 15 (sequential 1-15).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…-to-it TEMPLATE_PRESET_DEFAULTS maps each template name to its locked autonomy preset (all three default to Cautious per the design decisions; comments explain the rationale). TEMPLATE_SECTION_SCHEMA is the per-template per-file h2 header schema that Add-to-it section detection validates against. Advisor schema includes 'Operating mode' (added to IDENTITY.md template in this PR per spec/01 conformance). Researcher and writer schemas populated with the actual h2 headers from the new template files. MAX_TEMPLATE_DEPTH defensive cap (16) for the iterative template walk added in this PR. redact_url_credentials helper drops user:pass@ from URL netloc while keeping scheme + host + path visible. The persona-backend warning at end of PR 2 uses this to show operators which backend is configured without leaking credentials. The existing _redact_for_error_message pattern in persona/mandate/corpus backends strips everything after :// which hid the host entirely; that defeated the operator-decision goal. MSG_NO_TTY rewrite drops the advisor-specific example; now points operators at --list-templates so they can pick from all three. Three new MSG_ constants for the new recovery paths: - MSG_SECTION_DETECTION_FAILED (Add-to-it fail-closed) - MSG_STAGING_DIR_EXISTS (stale staging from prior crashed run) - MSG_MISSING_FILE_BACKFILL (template-owned file absent on disk) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Curiosity-first investigator with the following template-specific shape per the synthesis decisions: - Operating mode: hybrid (multi-session research projects use goal-driven mode via goal.md; single-session questions stay reactive). Resolves the spec/01 gap that PR 1's advisor template also left as 'silently defaults to reactive'. - Research integrity Layer 1 (citations) is enabled in IDENTITY.md and in model.md so researchers ship with the spec/13 anti-confident- wrong-answer discipline baked in, not as a comment placeholder. - tools.md documents the canonical 'drop sources in raw/ for ingestion' pattern per spec/01 anatomy. External APIs lists Anthropic as required and Tavily as optional with a setup comment. - tools.md Hard NOs pre-fill two epistemic refusals before the operator's Q7 answers: 'never assert certainty when evidence is ambiguous', 'never present a finding as final without flagging source gaps'. - model.md cost guardrails: $1.50 daily / $20.00 monthly (higher than advisor's $0.50/$7 because research synthesis sessions reading multiple sources routinely exceed the advisor cap). - memory/INDEX.md renames 'Locked Decisions' to 'Research Conclusions' and 'Active Projects' to 'Active Investigations' so the section semantics match research epistemics rather than advisory epistemics. - wiki/INDEX.md adds 'Source citations' (frontmatter convention explainer) and 'Pending distillation' (intake queue) sections. Web search APIs are classified read_only per the spec/28 amendment landing in this PR; the researcher uses the same Cautious autonomy preset as advisor because the rare TRUE external action (emailing a research summary, posting to a knowledge base) still escalates. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Voice-first content agent with the following template-specific shape per the synthesis decisions: - Operating mode: reactive by default. Long-form projects (novels, multi-part series, ongoing documentation) opt into hybrid mode via goal.md. spec/01 mode-declaration requirement honored. - model.md defaults to claude-sonnet-4-6 primary + claude-haiku-4-5 fallback. Comment inline documents the Opus upgrade path for deep drafting passes on complex long-form work. Sonnet is 5x cheaper than Opus and produces fluent prose at lower cost for typical writing workloads. Cost guardrails inherit advisor's $0.50/$7 unchanged since Sonnet keeps the burn low. Locked in PR 2 via AskUserQuestion gate (P2). - tools.md adds drafts/ and revisions/ write paths so writers have structural places to separate work-in-progress from operator-ready output. Hard NOs prefill 'never publish without operator review' and 'never overwrite a draft without saving the prior version to revisions/'. - tools.md read budget cap raised to 30 (advisor's was 20) because writers with large world-building wikis or multi-chapter projects routinely need 20-30 file loads per session. - SOUL.md opens directly with the voice substitution (drops advisor's static 'Grounded. Clear.' opening) and frames the voice as operator-authored: 'the framework's voice is the operator's voice'. - USER.md adds 'Revision and consistency preferences' section so operators have a structural home for diff-style-revisions and long-form-consistency rules. - IDENTITY.md What I'm NOT prefills writer-specific bright lines: 'not a publishing system', 'not an editor of operator content without ask', 'not able to match voice without reading existing work'. Cautious autonomy preset (publishing is a high-stakes external action; external_side_effect: escalate ensures operator approves every external publish). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…atform.py lazy + advisor IDENTITY.md Operating mode
wizard.py (1446 LOC final, was 880) gains the full PR 2 surface:
Add-to-it recovery merge contract (spec/35 MUST 5 + MUST 15):
- _extract_h2_headers state machine: skips YAML frontmatter, code
fences, HTML comments; ATX-style h2 only (setext not supported per
spec/35 MUST 15).
- _detect_sections compares extracted headers against
C.TEMPLATE_SECTION_SCHEMA; superset match required; missing files
tracked as backfill candidates (not failures).
- _add_to_it main flow: stale staging dir recovery offer, fail-closed
on schema mismatch, missing-file backfill, render to staging dir,
diff preview, commit-or-cancel.
- _render_diff_preview uses difflib.unified_diff with UTF-8 BOM strip
(encoding="utf-8-sig") and CRLF/CR to LF normalization so vault
files from Windows operators do not show every line as changed.
rich.syntax.Syntax with language="diff" on TTY; plain text on
Console.is_dumb_terminal. Per-file header separators and a
change-count summary line.
- _commit_add_to_it implements the A5 reversal pattern: backup
existing to .bak.<ts> (rename 1), staging into place (rename 2),
rmtree backup on success / restore backup on failure. KeyboardInterrupt
mid-commit caught by the outer KI handler which detects the
half-committed state (agent_dir absent + .bak + .new both present)
and completes restoration.
KeyboardInterrupt restructure (A4): all wizard cleanup blocks
converted from 'except Exception' to 'except BaseException' with
explicit KI re-raise after cleanup. KI inherits from BaseException,
not Exception, so PR 1's 'except Exception' did not catch it.
Outermost run_init wraps the body in try/except KeyboardInterrupt
returning exit 130 with 'Canceled. No files were written.'
Per-template preset dispatch (A2): _default_template_vars takes
template_name and looks up C.TEMPLATE_PRESET_DEFAULTS to apply the
correct preset. All three default to Cautious per the synthesis
locks. known_templates expands to {'advisor', 'researcher', 'writer'}
in sync with cli.py choices.
API key carve-out (P3 lock): _api_key_preflight moves from run_init
(before dispatch) to inside _interactive (after dispatch). --from-template
and --list-templates no longer require ANTHROPIC_API_KEY at scaffold
time. Doctor handoff later surfaces the missing key.
_cmd_list_templates enumerates all 3 templates with one-line
descriptions.
8 polish items inline:
- C2 (in _platform.py below): lazy DEFAULT_AGENTS_ROOT
- R2-M2: _doctor_handoff splits its try/except around run_doctor,
overall_exit_code, and render_human independently
- R2-L1: _from_template gains length check before regex
- R2-L2: _types(mod, *names) helper extracted at module top with
docstring noting None tolerance
- R2-L4: _translate_oserror detects errno.ENOENT specifically and
prints 'the folder disappeared between collision check and
overwrite' instead of the generic message
- L1: _walk_traversable converted from recursion to deque-based
iteration with C.MAX_TEMPLATE_DEPTH guard
- L2: all backup and staging timestamps use %Y%m%dT%H%M%S_%fZ
(microsecond resolution)
- L4: _persona_backend_check uses C.redact_url_credentials to show
operators which backend is configured without leaking credentials
cli.py: --from-template choices expand to ['advisor', 'researcher',
'writer']. Two-line additive diff; no other cli.py changes.
_platform.py C2 polish: DEFAULT_AGENTS_ROOT module-level constant
retained for backward compat but get_agents_root() now computes the
path fresh on each call (not from the frozen constant), so test
monkeypatches of HOME after framework import work correctly.
advisor IDENTITY.md: new ## Operating mode section per spec/01
mode-declaration requirement. Advisor is reactive by default;
operators can activate hybrid mode by adding goal.md. The new
section matches the post-PR-2 TEMPLATE_SECTION_SCHEMA['advisor']
['persona/IDENTITY.md'] entry so Add-to-it section detection works
on the advisor template.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
test_init_cli.py +4 tests: --list-templates enumerates all three template names; --from-template researcher and writer choices accepted; unknown-template still rejected with exit 2. test_init_wizard.py +25 tests covering: - Section detection state machine (4): YAML frontmatter skip, code fence skip, HTML comment skip, trailing ATX marker strip - Add-to-it dispatch + detection (5): advisor happy path schema match, header-rename fail-closed, missing-file backfill, stale staging dir found via glob, stale staging dir absent - Staging-dir commit + rollback (3): success rmtrees backup, rename failure restores original, KeyboardInterrupt safe (restore + re-raise) - CRLF + BOM normalization (2): CRLF vs LF no spurious diff, BOM vs no-BOM no spurious diff - 8 polish item tests: _doctor_handoff split (run_doctor failure + render_human failure paths), _from_template length check before regex, _types(None) returns empty tuple, _translate_oserror ENOENT specific message, _walk_traversable returns expected files iteratively, backup timestamps contain microseconds, persona-backend warning shows redacted URL not user:pass@host - Per-template preset dispatch (3): advisor / researcher / writer all resolve to Cautious via C.TEMPLATE_PRESET_DEFAULTS test_init_templates.py +15 tests covering: - researcher + writer file inventory + zero em dashes per template - researcher + writer + advisor schema conformance: each file's extracted h2 headers match C.TEMPLATE_SECTION_SCHEMA exactly - researcher IDENTITY.md has Operating mode hybrid + Research integrity section - writer IDENTITY.md has Operating mode reactive - writer model.md defaults to claude-sonnet-4-6 (not Opus per P2 lock) - writer tools.md has drafts/ + revisions/ write paths - researcher tools.md has raw/ read path documented - C.TEMPLATE_PRESET_DEFAULTS all three keys present and map to Cautious - C.TEMPLATE_SECTION_SCHEMA all three keys populated with 7 file entries test_init_smoke.py +3 tests covering: - researcher --from-template e2e happy path with rich + Confirm + AtomicAgent mocked, asserts exit 0 + researcher-specific markers in written IDENTITY.md - writer --from-template e2e happy path with same mocks, asserts exit 0 + writer-specific markers - --from-template works without API key per the P3 carve-out: _get_key raises AtomicAgentsError but scaffold still completes with exit 0 Test suite: 2939 + 50 skipped to 2986 + 50 skipped, zero regressions. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Operator-facing arc-closer entry for #94 PR 2 of 2. Interleaves above the existing PR 1 of #94 entry per the spec/35 MUST 12 newest-arc-at-top rule. Lead bullet describes the operator outcome: three starter templates (advisor + researcher + writer) plus a non-destructive Add-to-it recovery flow plus 8 polish items from PR 1 adversarial review. With this PR landing, Issue #94 closes: the half-day home-user deploy is now an under-10-minute first-run experience. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
… fixes Round 1 Opus adversarial reviewer caught 3 CRITICALs forming a single structural gap: Add-to-it was implemented but unreachable, the rendering path would have been data-destructive even if wired, and the KeyboardInterrupt handler did not satisfy MUST 5's half-committed-state contract. Per AUQ P1 lock A (best-not-cheapest), this commit lands Add-to-it properly with file-level section-aware merging. C1 + C2 + C3 - Wire Add-to-it three-branch prompt and replace wholesale-replacement render with file-level section merge: - _check_collision returns (branch, headers) tuple with overwrite | add_to_it | cancel options; both _from_template and _interactive call sites dispatch on the new branch - _check_collision pre-runs _detect_sections on add_to_it choice and falls back to overwrite/cancel on section-detection failure - _split_sections + _join_sections h2 state-machine for ATX-only preamble + body block parsing with fence/comment/frontmatter skip - _compute_merged_content reads existing files, splits by h2, replaces schema-owned sections with fresh content, preserves preamble + orphan sections + h3+ subsections verbatim; backfills missing files entirely from the template - _commit_merges loops sorted relpaths through _io.atomic_write for per-file atomicity; no staging dir; memory/journal/log/raw never touched (operator data dirs are excluded from the merge map) - spec/35 Recovery flow + MUST 5 amended to describe the file-level atomic_write pattern instead of the staging-dir pattern - _check_stale_staging_dirs + _commit_add_to_it + MSG_STAGING_DIR_EXISTS removed (no staging dir in the new shape) H1 - writer/model.md line 7 stray h1 converted to HTML comment so it does not get rendered as a document-title h1 by markdown viewers or treated as meta-authority by persona-aware models. H4 + H5 - spec/35 line 266 header + wizard.py module docstring both corrected from "14 normative MUSTs" to "15 normative MUSTs" matching the spec body after PR 2 amendments. M3 - test_detect_sections_orphan_h2_preserved_in_extraction added so a regression that broke MUST 15 orphan tolerance would fail CI. M4 - _doctor_handoff's overall_exit_code raise path now mirrors the run_doctor failure path: prints a "doctor verdict unclear" message and returns True so the test-call prompt still fires; previously the silent -1 sentinel triggered the misleading "Doctor found problems" branch. M5 - TEST_CALL_TIMEOUT_S removed; AtomicAgent.call signature does not accept a timeout parameter so wiring was not possible, the constant was dead. M6 - Syntax import in _render_diff_preview hoisted before the file-walk loop; gated on not is_dumb. Test suite: 2990 passed, 50 skipped, zero regressions. 47 new tests in PR 2 unchanged; the merge logic carries section-level coverage via _compute_merged_content unit tests + per-file atomic_write semantics via the _commit_merges suite. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
… + diff polish Round 2 Opus adversarial reviewer caught 1 CRITICAL + 4 HIGHs + 5 MEDIUMs. The CRITICAL was a real data-destruction bug: operator-authored h3 subsections under schema h2 sections were destroyed by the merge logic that Round 1 added. Spec/35 MUST 15 explicitly requires h3+ preservation. This commit closes all 11 in-scope findings. C1 - h3-aware schema h2 merge (CRITICAL) _split_h3_subsections + _join_h3_subsections helpers parse a schema h2 body into (operator_preamble, [(h3_header, h3_body), ...]) and the inverse. _compute_merged_content schema-h2 branch is now additive instead of wholesale-replace: operator preamble preserved verbatim, existing h3 subsections preserved in original order, new template h3 subsections appended at end. Missing-h2 backfill still uses fresh template entirely. H1 - Duplicate schema h2 fail-closed _detect_sections refuses files where any schema h2 appears twice and routes to overwrite/cancel via failed_files. Copy-paste-induced duplicates surface to the operator instead of silently destroying the second instance. H2 - Spec MUST 5 + docstring wording fix Operator-authored memory notes, journal/, log/, raw/ MUST NOT be touched. Schema-owned scaffolding files (memory/INDEX.md, wiki/INDEX.md) ARE rewritten through the normal merge pattern. Spec wording previously claimed memory/ was untouchable, contradicting the schema. H3 - KeyboardInterrupt mid-commit accuracy _commit_merges catches KI in the write loop, prints "Wrote N of M files before cancel. Wrote: [...]. Pending: [...]" before re-raising. Outer run_init handler simplified to "Canceled." so the no-write claim never lies. H4 - CHANGELOG entry rewrite for actually-shipped Add-to-it design Round 1 ripped out the staging-dir design described in the original PR 2 entry. Entry now describes the file-level atomic_write design with section-aware merge that actually shipped. Test count updated. M1 - _render_diff_preview exception guard Thin try/except shell wraps the body. On failure: prints "Preview rendering failed: <type>. Falling back to file list." followed by relpath list, returns -1 sentinel. MUST 3 contract held. M2 - Setext h2 fail-closed Files with Setext-style headings (text underlined by - or =) fail detection and route to overwrite/cancel. Spec/35 MUST 15 updated. Operators must convert to ATX before using Add-to-it. M3 - HTML-comment state tightening _extract_h2_headers and _split_sections toggle in_comment only when the stripped line starts with <!-- and ends with -->. Inline-code references to <!-- syntax in documentation prose no longer suppress subsequent headers. M4 - test_check_collision_add_to_it_falls_back_to_cancel_on_detection_failure Builds advisor scaffold, removes a required h2 from IDENTITY.md, mocks Prompt sequence [add_to_it, cancel], asserts (cancel, None). M5 - 4 tests for _compute_merged_content + _split_sections lossless round-trip: byte-identical split/join, preamble preservation, h3 append behavior, orphan h2 in-position preservation. L1 - Stale comment in test header (referenced removed function). L3 - Zero-changes early return: if _render_diff_preview returns 0 files changed, _add_to_it prints "No changes to apply." and exits without firing Confirm. Setext regex bug fix (incidental): initial setext detection had a false positive on `---` thematic breaks used as memory/INDEX.md delimiters. Regex tightened to require 2+ chars AND preceding non- empty non-delimiter content line (proper CommonMark setext rule). Test suite: 3001 passed, 50 skipped, zero regressions. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…n + CHANGELOG count drift Round 3 Opus convergence review caught one MEDIUM (spec-internal contradiction) + four LOWs (3 cosmetic count/citation drifts plus 1 obscure YAML-frontmatter preservation gap deferred to follow-up). M1 - MUST 11 enumeration vs MUST 7 amendment MUST 7 was amended in Round 1 to carve --from-template and --list-templates out of the API key pre-flight requirement, but MUST 11's --from-template entry-guard enumeration still listed MUST 7 as a required pre-flight. Two normative MUSTs in the same locked spec contradicting each other is a CLAUDE.md rule 10 (the spec is the product) violation. The enumeration is now consistent with MUST 7's carve-out wording. L2 - MUST 15 regex citation The spec cited the simplified pattern ^##\s+(.+)$ but the code uses ^##\s+(.+?)(?:\s+#+)?\s*$ which additionally strips trailing closing-hash markers per ATX convention. Updated to describe the actual tolerance behavior without naming the regex literal. L3 - CHANGELOG test count off by 1 Actual delta of 59 net new tests across four init test files on this branch vs main; CHANGELOG said 58. L4 - CHANGELOG researcher LOC count off by 7 Actual count is 360 LOC across the 7 researcher template files; CHANGELOG said 367. L1 deferred to follow-up issue #322 (YAML frontmatter on operator- edited schema files is silently dropped by _split_sections / _join_sections round-trip; no shipped template uses frontmatter so the impact today is bounded to operators who add Obsidian metadata to a scaffold file then re-run init). The fix is a 30-min change but adds testing surface; better as its own PR. Test suite: 3001 passed, 50 skipped, zero regressions (init subset passes 112 + 2 skipped). Convergence: Round 3 verdict 0 CRITICAL + 0 HIGH + 1 MEDIUM (now fixed) + 4 LOW (3 fixed, 1 deferred to #322). PR 2 is ship-ready. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #94 (init-wizard arc closer).
researcher(curiosity-first investigator with research integrity layer 1 ON, raw/ source intake) andwriter(voice-first content agent with Sonnet primary + Haiku fallback, drafts/ + revisions/ write paths).atomic-agents initagainst an existing agent dir, the wizard offers a section-aware merge: operator content is preserved verbatim (preamble + orphan h2 sections + h3+ subsections under schema h2 sections), schema h2 sections additively merge fresh template content, file commits go through_io.atomic_writeper file (no staging dir).DEFAULT_AGENTS_ROOT, split_doctor_handofftry/except,_from_templatelength pre-check,_types(mod, *names)helper, ENOENT translator, iterative_walk_traversablewithMAX_TEMPLATE_DEPTH=16, microsecond timestamp tails, URL credential redaction on persona-backend warning.BaseExceptionwith explicit re-raise so KI runs cleanup; outermost handler inrun_initreturns exit 130 with "Canceled.";_commit_mergesmid-loop KI prints a Wrote/Pending file list before re-raising so operators know exactly what landed.--from-template <name>and--list-templatesare CI-friendly: both carve out of non-TTY refusal AND credential pre-flight (per amended spec/35 MUST 2, 7, 11). The opt-in test call is still gated on credential availability so the scaffold succeeds in CI without the operator settingANTHROPIC_API_KEYat build time.read_onlyso researcher templates use the Cautious preset without paying judge_required overhead on every search query.Adversarial review
Round 1 (Opus, post-implementation): 3 CRITICAL + 6 HIGH + 7 MEDIUM + 5 LOW = 21 findings. The 3 CRITICALs formed a single structural gap — Add-to-it was unreachable from any prompt and would have been data-destructive even if wired (placeholder defaults overwrite operator memory/journal/log). User locked option A (land properly, not scope-down). Fix commit
ed8208ewired the three-branch prompt, replaced the wholesale-replace render with file-level section-aware merge through_compute_merged_content, and updated spec/35 Recovery flow + MUST 5 to describe the file-level pattern.Round 2 (Opus, hunting Round 1 fix surfaces): 1 CRITICAL + 4 HIGH + 5 MEDIUM + 5 LOW = 15 findings. The CRITICAL was a real data-destruction bug Round 1's fix introduced: operator-authored h3 subsections inside schema h2 blocks were destroyed by the wholesale block-body replace. Spec/35 MUST 15 explicitly required h3+ preservation. Fix commit
3a481ebadded_split_h3_subsections+_join_h3_subsectionshelpers and made the schema-h2 merge additive (operator preamble preserved, existing h3s in order, new template h3s appended at end). Plus duplicate-h2 fail-closed, Setext fail-closed, HTML-comment line-start tightening,_render_diff_previewexception guard, CHANGELOG rewrite to match shipped surface, KI mid-commit summary, zero-changes early return, 11 new tests.Round 3 (Opus, convergence): 0 CRITICAL + 0 HIGH + 1 MEDIUM + 4 LOW. The MEDIUM was a spec-internal contradiction (MUST 11's
--from-templateenumeration still cited the now-amended MUST 7 pre-flight) and 3 of 4 LOWs were cosmetic count/regex-citation drifts. Fix commit1a1eee1closed all 4 in-scope (MUST 11 amendment, MUST 15 regex citation, CHANGELOG count fixes); L1 (YAML frontmatter not preserved by_split_sections/_join_sectionsround-trip) filed as follow-up #322 (no shipped template uses frontmatter so impact is bounded to operators adding Obsidian metadata to a scaffold file).Test plan
uv run pytest -q→ 3001 passed, 50 skipped, zero regressions (was 2937 + 48 skipped pre-PR; net +64 tests across the 2 PRs of the arc).uv run pytest tests/test_init_*.py -q→ 112 passed + 2 skipped in 0.50s.--from-template advisor,--from-template researcher,--from-template writerall scaffold cleanly without an API key (per amended MUST 7 carve-out + smoke tests).--list-templatesenumerates all 3 templates with one-line descriptions.initon an existing agent now offers 3 options (overwrite / add_to_it / cancel) via_check_collision._render_diff_previewexception fallback prints file list when difflib/rich raises.Follow-ups
🤖 Generated with Claude Code