Skip to content

feat(init): atomic-agents init wizard PR 2 of 2 — researcher + writer + Add-to-it#323

Merged
dep0we merged 10 commits into
mainfrom
feat-init-wizard-pr2
Jun 2, 2026
Merged

feat(init): atomic-agents init wizard PR 2 of 2 — researcher + writer + Add-to-it#323
dep0we merged 10 commits into
mainfrom
feat-init-wizard-pr2

Conversation

@dep0we
Copy link
Copy Markdown
Owner

@dep0we dep0we commented Jun 2, 2026

Summary

Closes #94 (init-wizard arc closer).

  • Adds two starter templates: researcher (curiosity-first investigator with research integrity layer 1 ON, raw/ source intake) and writer (voice-first content agent with Sonnet primary + Haiku fallback, drafts/ + revisions/ write paths).
  • Wires Add-to-it as a third collision-recovery branch (alongside Overwrite + Cancel). On re-running atomic-agents init against 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_write per file (no staging dir).
  • Lands 8 polish items from PR 1 adversarial deferrals: lazy DEFAULT_AGENTS_ROOT, split _doctor_handoff try/except, _from_template length pre-check, _types(mod, *names) helper, ENOENT translator, iterative _walk_traversable with MAX_TEMPLATE_DEPTH=16, microsecond timestamp tails, URL credential redaction on persona-backend warning.
  • KeyboardInterrupt restructure: all wizard cleanup paths catch BaseException with explicit re-raise so KI runs cleanup; outermost handler in run_init returns exit 130 with "Canceled."; _commit_merges mid-loop KI prints a Wrote/Pending file list before re-raising so operators know exactly what landed.
  • --from-template <name> and --list-templates are 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 setting ANTHROPIC_API_KEY at build time.
  • spec/28 (Judge layer) amended: web search HTTP GETs explicitly classified as read_only so researcher templates use the Cautious preset without paying judge_required overhead on every search query.
  • spec/35 (init wizard) grows from 14 to 15 normative MUSTs: MUST 5 + new MUST 15 codify the section-detection contract + file-level merge contract; MUST 4 + 7 + 11 amended to match the carve-outs and operator surface.

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 ed8208e wired 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 3a481eb added _split_h3_subsections + _join_h3_subsections helpers 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_preview exception 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-template enumeration still cited the now-amended MUST 7 pre-flight) and 3 of 4 LOWs were cosmetic count/regex-citation drifts. Fix commit 1a1eee1 closed all 4 in-scope (MUST 11 amendment, MUST 15 regex citation, CHANGELOG count fixes); L1 (YAML frontmatter not preserved by _split_sections/_join_sections round-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.
  • Em dash check on all changed files (production + spec + tests + CHANGELOG diff): 0 in new prose.
  • --from-template advisor, --from-template researcher, --from-template writer all scaffold cleanly without an API key (per amended MUST 7 carve-out + smoke tests).
  • --list-templates enumerates all 3 templates with one-line descriptions.
  • Re-running init on an existing agent now offers 3 options (overwrite / add_to_it / cancel) via _check_collision.
  • Add-to-it on an unmodified scaffold prints "No changes to apply" and exits 0 without firing Confirm (zero-changes early return).
  • Add-to-it preserves operator-added orphan h2 sections in original position + operator-added h3 subsections under schema h2 sections verbatim (the C1 fix from Round 2).
  • Add-to-it on a file with a duplicate schema h2 fails-closed back to overwrite/cancel.
  • Add-to-it on a file with a Setext-style h2 fails-closed back to overwrite/cancel.
  • Mid-commit KeyboardInterrupt prints Wrote N of M files summary before re-raising; outer handler exits 130.
  • _render_diff_preview exception fallback prints file list when difflib/rich raises.

Follow-ups

🤖 Generated with Claude Code

Dan Powers and others added 10 commits June 2, 2026 13:57
…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>
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.

[deployment] Configuration wizard + deploy assistant for new operators (post-public-flip)

1 participant