Phase D: scaffold-keeper background agent
- scaffold-keeper.ts: dispatchScaffoldKeeperIfNeeded fires async after milestone
completion and on stopAuto cleanup. Detects editing-drift items, writes
<file>.proposed artifacts (template-only stub for now; later wires the
records-keeper skill subagent for code-as-fact merging), emits a structured
approval_request notification with stable dedupe_key so repeated runs don't
spam the user.
- Wired into auto-post-unit.ts and auto.ts:stopAuto via fire-and-forget so
the auto loop is never blocked by scaffold work.
- Failure modes non-fatal: try/catch around the dispatch, errors logged via
logWarning("scaffold").
Phase E: /sf scaffold sync command (escape hatch)
- commands-scaffold-sync.ts: parseScaffoldSyncArgs + handleScaffoldSync.
- Flags:
--dry-run report what would change, no writes
--include-editing run scaffold-keeper synchronously for editing-drift items
--only=<glob> scope to a path glob (suffix/prefix match)
- Wired into the SF command system via commands-bootstrap.ts, commands/catalog.ts,
and commands/handlers/ops.ts following the existing /sf <verb> pattern.
- Reuses ensureAgenticDocsScaffold from Phase C — doesn't reimplement sync logic.
Doctor finding (checkScaffoldFreshness) refined to reference the new command.
Tests: 8 new cases in scaffold-keeper.test.ts. All 49 scaffold tests green.
Together with Phases A-C, this completes ADR-021. Documents are now versioned,
upgrades are automatic for the safe cases, and editing-drift surfaces through
.proposed artifacts and structured notifications. The scaffold-keeper agent
body is currently a template-only stub; replacing it with a real records-keeper
subagent dispatch is a follow-up that the architecture now enables.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>