Skip to content

feat(cli): cli-3.22.0 — charter close reconciles follow-ups + offers TDE promotion (#135 Tier 3)#236

Merged
montfort merged 1 commit into
mainfrom
feat/tier3-charter-close-followups
Jun 11, 2026
Merged

feat(cli): cli-3.22.0 — charter close reconciles follow-ups + offers TDE promotion (#135 Tier 3)#236
montfort merged 1 commit into
mainfrom
feat/tier3-charter-close-followups

Conversation

@montfort

Copy link
Copy Markdown
Contributor

Summary

Implements RFC #135 Tier 3 — the last open tier of the follow-ups automation roadmap. After an interactive charter close, the CLI reconciles the follow-ups registry against the just-closed work and offers to promote new entries to TDEs. Unblocked now that drift detection is reliable (cli-3.21.0, #229/#231 in #235).

CLI-only release: cli-3.22.0 (no framework change).

Behavior

After an interactive charter close (the --from-template paths are skipped — no prompt context):

  1. Detect — runs the default followups drift scan (committed git range ∪ working tree) over the recently-written AILOGs. No-op if the project has no follow-ups registry or nothing is unextracted.
  2. Extract — writes any §Follow-ups / R<N> (new) content not yet in the registry into ## Bucket: ready (same semantics as followups drift --apply, so nothing is lost).
  3. Promote inline — for each new entry, prompts Promote FU-NNN — <desc> to a TDE? [y/N] against the four AGENT-RULES.md §3 criteria. Declining leaves it extracted (captured, not promoted); accepting runs the followups promote flow (creates the TDE with promoted_from_followup traceability). Entries extracted as suspected-closed are flagged in the prompt (likely already resolved → rarely transversal debt).

Design note — scan scope

The scan reuses the stabilized default drift (git range ∪ working tree), not originating_ailogs. That field is the ex-ante seed of the Charter (the AILOGs that motivated it), not the execution AILOGs where follow-ups are written — and it is empty for greenfield (originating_spec) Charters. At close time the default scan captures exactly the just-written work, with no fragile attribution logic.

Implementation

Refactored followups drift into two reusable, side-effect-free cores, shared by followups drift and the close integration (drift's own output is unchanged):

  • detect_drift_candidates(project_root, registry, scan_all, range) -> Vec<…> — scan + per-follow-up content-hash dedup, no stdout/exit.
  • apply_candidates(registry_path, registry, drifted, today) -> ApplyReport — writes the registry and returns the created FU-NNN ids (the handle the close hook needs for the promotion prompts).

The close hook (offer_followup_promotions) lives in charter/close.rs, guarded to the interactive flow (TTY already confirmed by require_interactive).

Tests

  • tier3_detect_apply_dedup_roundtrip — end-to-end of the core without git/TTY: detect → apply → assert the returned FU-001 id + Source-hash written → re-detect is empty (dedup).
  • Existing followups drift integration suite (21 tests) green — the refactor preserved behavior.
  • Full suite: 24 suites green. New code clippy-clean.

Note: the interactive close prompt path can't be integration-tested (assert_cmd has no TTY; require_interactive rejects), same limitation as the existing interactive-close tests. Coverage lives in the unit test of the extracted cores.

Closes #135

🤖 Generated with Claude Code

…TDE promotion (#135 Tier 3)

Closes the loop between Charter close and the follow-ups registry — the last
open tier of the follow-ups automation roadmap (#135), unblocked now that
drift detection is reliable (cli-3.21.0, #229/#231).

After an interactive `charter close`, the command runs the default
`followups drift` scan (committed git range ∪ working tree) over the
just-written AILOGs, extracts any §Follow-ups / R<N> (new) content not yet in
the registry into `## Bucket: ready`, then offers per-entry TDE promotion
against the four AGENT-RULES.md §3 criteria. Declining leaves the follow-up
extracted (captured, not promoted); accepting runs the `followups promote`
flow. No-op without a registry or when nothing is unextracted; skipped on the
--from-template paths. The scan reuses the stabilized default drift, not
`originating_ailogs` (that field is the ex-ante seed, not the execution
AILOGs where follow-ups live).

Refactors `followups drift` into reusable side-effect-free cores —
detect_drift_candidates() and apply_candidates() (returns the created FU ids)
— shared by `followups drift` and the close integration. drift output
unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@montfort montfort merged commit 7b95ffc into main Jun 11, 2026
1 check passed
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.

RFC: Roadmap for automating the follow-ups backlog — 4 tiers + crystallization gates

1 participant