create-claude-cabinet 0.51.0 → 0.53.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/README.md +35 -28
  2. package/lib/cli.js +2 -2
  3. package/lib/modules.js +5 -4
  4. package/package.json +1 -1
  5. package/templates/CLAUDE.md +196 -31
  6. package/templates/EXTENSIONS.md +7 -0
  7. package/templates/README.md +3 -3
  8. package/templates/briefing/_briefing-template.md +1 -1
  9. package/templates/briefing/_briefing-work-tracking-template.md +3 -3
  10. package/templates/cabinet/_cabinet-member-template.md +10 -7
  11. package/templates/cabinet/memory-lifecycle-contract.md +16 -0
  12. package/templates/cabinet/pib-db-access.md +1 -1
  13. package/templates/cabinet/pib-db-triggers.md +20 -16
  14. package/templates/cabinet/watchtower-contracts.md +321 -10
  15. package/templates/engagement/pib-db-patches/pib-db-mcp-server.mjs +2 -2
  16. package/templates/memory/patterns/_pattern-template.md +1 -1
  17. package/templates/mux/bin/mux +5 -0
  18. package/templates/mux/config/mux-server.py +7 -5
  19. package/templates/rules/enforcement-pipeline.md +2 -2
  20. package/templates/rules/memory-capture.md +2 -2
  21. package/templates/scripts/__tests__/absorption-no-prune.test.mjs +89 -0
  22. package/templates/scripts/__tests__/assessment-recalibration.test.mjs +0 -2
  23. package/templates/scripts/__tests__/batch-disposition.test.mjs +7 -9
  24. package/templates/scripts/__tests__/category-expiry.test.mjs +130 -0
  25. package/templates/scripts/__tests__/detector-registry.test.mjs +41 -7
  26. package/templates/scripts/__tests__/draft-surfacing.test.mjs +46 -162
  27. package/templates/scripts/__tests__/extraction-classification.test.mjs +306 -0
  28. package/templates/scripts/__tests__/fixtures/read-pass-2026-07-14.json +325 -0
  29. package/templates/scripts/__tests__/fold-similarity.test.mjs +290 -0
  30. package/templates/scripts/__tests__/friction-actionability.test.mjs +180 -0
  31. package/templates/scripts/__tests__/hold-verb.test.mjs +149 -0
  32. package/templates/scripts/__tests__/memory-budget-debt.test.mjs +264 -0
  33. package/templates/scripts/__tests__/reach1-inbox-relations.test.mjs +274 -0
  34. package/templates/scripts/__tests__/reach2-significance.test.mjs +300 -0
  35. package/templates/scripts/__tests__/read-pass-fixture.test.mjs +71 -0
  36. package/templates/scripts/__tests__/ring2-pattern-gate.test.mjs +315 -0
  37. package/templates/scripts/__tests__/ring2-roster-review.test.mjs +75 -16
  38. package/templates/scripts/__tests__/ring3-completion-filter.test.mjs +167 -105
  39. package/templates/scripts/__tests__/ring3-outage-backfill.test.mjs +156 -0
  40. package/templates/scripts/__tests__/roster-ambient-render.test.mjs +132 -0
  41. package/templates/scripts/__tests__/routine-dispatch.test.mjs +29 -1
  42. package/templates/scripts/__tests__/routine-moment-expiry.test.mjs +192 -0
  43. package/templates/scripts/memory-consolidation-scan.mjs +149 -0
  44. package/templates/scripts/pib-db-mcp-server.mjs +2 -2
  45. package/templates/scripts/skill-validator.sh +7 -4
  46. package/templates/scripts/watchtower-build-context.mjs +33 -1
  47. package/templates/scripts/watchtower-lib.mjs +225 -6
  48. package/templates/scripts/watchtower-queue.mjs +245 -59
  49. package/templates/scripts/watchtower-ring1.mjs +194 -2
  50. package/templates/scripts/watchtower-ring2.mjs +488 -190
  51. package/templates/scripts/watchtower-ring3-close.mjs +994 -115
  52. package/templates/scripts/watchtower-routines.mjs +107 -1
  53. package/templates/skills/audit/SKILL.md +5 -5
  54. package/templates/skills/cabinet-anthropic-insider/SKILL.md +35 -2
  55. package/templates/skills/cabinet-anti-confirmation/SKILL.md +24 -0
  56. package/templates/skills/cabinet-cc-health/SKILL.md +22 -0
  57. package/templates/skills/cabinet-data-integrity/SKILL.md +19 -0
  58. package/templates/skills/cabinet-debugger/SKILL.md +36 -0
  59. package/templates/skills/cabinet-deployment/SKILL.md +22 -0
  60. package/templates/skills/cabinet-elegance/SKILL.md +12 -0
  61. package/templates/skills/cabinet-goal-alignment/SKILL.md +11 -0
  62. package/templates/skills/cabinet-historian/SKILL.md +33 -0
  63. package/templates/skills/cabinet-organized-mind/SKILL.md +11 -0
  64. package/templates/skills/cabinet-process-therapist/SKILL.md +132 -6
  65. package/templates/skills/cabinet-qa/SKILL.md +63 -0
  66. package/templates/skills/cabinet-roster-check/SKILL.md +12 -0
  67. package/templates/skills/cabinet-system-advocate/SKILL.md +2 -2
  68. package/templates/skills/cabinet-workflow-cop/SKILL.md +65 -3
  69. package/templates/skills/cc-feedback/SKILL.md +4 -4
  70. package/templates/skills/cc-remember/SKILL.md +4 -4
  71. package/templates/skills/close/SKILL.md +63 -9
  72. package/templates/skills/debrief/SKILL.md +14 -8
  73. package/templates/skills/debrief/phases/qa-handoff-sweep.md +12 -9
  74. package/templates/skills/dx-feedback/SKILL.md +1 -1
  75. package/templates/skills/inbox/SKILL.md +85 -16
  76. package/templates/skills/memory/SKILL.md +1 -1
  77. package/templates/skills/onboard/SKILL.md +42 -33
  78. package/templates/skills/onboard/phases/detect-state.md +3 -2
  79. package/templates/skills/onboard/phases/generate-briefing.md +3 -2
  80. package/templates/skills/onboard/phases/generate-session-loop.md +70 -37
  81. package/templates/skills/onboard/phases/interview.md +17 -12
  82. package/templates/skills/onboard/phases/modularity-menu.md +33 -19
  83. package/templates/skills/onboard/phases/options.md +3 -1
  84. package/templates/skills/onboard/phases/post-onboard-audit.md +17 -11
  85. package/templates/skills/onboard/phases/summary.md +15 -12
  86. package/templates/skills/onboard/phases/work-tracking.md +14 -8
  87. package/templates/skills/orient/SKILL.md +7 -5
  88. package/templates/skills/pulse/SKILL.md +23 -18
  89. package/templates/skills/seed/phases/build-member.md +5 -3
  90. package/templates/skills/session-handoff/SKILL.md +72 -45
  91. package/templates/skills/spring-clean/SKILL.md +15 -13
  92. package/templates/skills/triage-audit/SKILL.md +3 -3
package/README.md CHANGED
@@ -18,8 +18,9 @@ and weigh in when their expertise matters:
18
18
  - **Briefings** — project context members read before weighing in
19
19
  - **Committees** — members grouped by concern so you convene the right
20
20
  experts for the right question
21
- - **The session loop** — `/orient` briefs you at the start, `/debrief`
22
- closes the loop for next time
21
+ - **The session loop** — watchtower keeps your project's state current in
22
+ the background and hands it to you when a session opens; `/close` ends a
23
+ session (legacy: `/orient` + `/debrief` by hand)
23
24
 
24
25
  ## Install
25
26
 
@@ -56,25 +57,28 @@ it's done, open Claude Code and run `/onboard`.
56
57
 
57
58
  ## What You Get
58
59
 
59
- ### The Session Loop (always installed)
60
+ ### The Session Loop (installed by default)
60
61
 
61
- This is the foundation. You run these commands they don't happen
62
- automatically.
62
+ Continuity between sessions, so Claude never starts blind. By default this
63
+ is **watchtower** — a background system that keeps your project's state
64
+ current and hands it to Claude when a session opens.
63
65
 
64
- - **`/orient`** open every session with this. Claude reads project
65
- state, checks health, surfaces what needs attention, and briefs you
66
- so you never start blind. Think of it as the briefing before the
67
- cabinet gets to work.
68
- - **`/debrief`** — close every session with this. Claude marks work
69
- done, records lessons, updates state, and prepares the briefing for
70
- next time. Without debrief, the next orient starts with stale
71
- information. The loop is what gives Claude memory across sessions.
66
+ - **Sessions start informed** watchtower's SessionStart hook injects the
67
+ current state (what you were working on, what's due, what broke). No
68
+ start-of-session command to run.
69
+ - **`/briefing`** review what needs attention across the project.
70
+ - **`/close`** (or **`/session-handoff`**) end a session; the background
71
+ rings handle inventory, lesson capture, and routing after you walk away.
72
72
 
73
- **The habit matters.** Orient and debrief take 30 seconds each. Skip
74
- them and sessions start from zero Claude forgets what happened,
75
- repeats mistakes, and you spend the first 10 minutes re-explaining
76
- context. Keep the loop and each session picks up where the last one
77
- left off.
73
+ Watchtower is installed by default; its background rings start when you run
74
+ **`/watchtower install`**. Until then it ships the skills and a dormant
75
+ SessionStart hook nothing runs in the background and no API cost is
76
+ incurred.
77
+
78
+ **Prefer to run it by hand?** Opt out of watchtower and use the legacy
79
+ loop instead — **`/orient`** at the start (reads state and briefs you) and
80
+ **`/debrief`** at the end (marks work done, records lessons). Both still
81
+ ship, but watchtower replaces them.
78
82
 
79
83
  ### The Cabinet (included in lean)
80
84
 
@@ -129,7 +133,7 @@ you already use GitHub Issues, Linear, or something else.
129
133
  Claude Code has built-in file memory, but no guardrails around it.
130
134
  The memory module adds structure:
131
135
 
132
- - **`/cc-remember`** — write a new memory with automatic indexing. Every memory gets its own file and is made reachable from `MEMORY.md` — by a direct entry or a region pointer — so `/orient` can find it next session.
136
+ - **`/cc-remember`** — write a new memory with automatic indexing. Every memory gets its own file and is made reachable from `MEMORY.md` — by a direct entry or a region pointer — so the session loop can surface it next session.
133
137
  - **`/memory`** — browse and search what Claude remembers.
134
138
  - **Validation** — `validate-memory.mjs` checks that the index stays within Claude Code's session-start budget and that every memory file is reachable from `MEMORY.md`. A PostToolUse hook flags unreachable writes in real time.
135
139
 
@@ -181,14 +185,17 @@ e2e harness.
181
185
 
182
186
  The rhythm of each session:
183
187
 
184
- 1. **Start a session** → `/orient` (get briefed)
188
+ 1. **Start a session** → watchtower briefs you automatically; `/briefing`
189
+ for the full picture (legacy loop: `/orient`)
185
190
  2. **Do your work** → talk to Claude, use `/plan` for anything non-trivial
186
191
  3. **Build it** → `/execute` to implement approved plans with cabinet oversight
187
192
  4. **Check quality** → `/audit` occasionally for a full cabinet review
188
- 5. **Close the session** → `/debrief` (close the loop)
193
+ 5. **Close the session** → `/close` (the rings capture the rest after you
194
+ walk away; legacy loop: `/debrief`)
189
195
 
190
- Steps 1 and 5 are the minimum. Everything in between is yours to use as
191
- needed. The more you use, the more the cabinet learns about your project.
196
+ Step 5 is the minimum start is automatic under watchtower. Everything in
197
+ between is yours to use as needed. The more you use, the more the cabinet
198
+ learns about your project.
192
199
 
193
200
  ## How It Works
194
201
 
@@ -243,7 +250,7 @@ npx create-claude-cabinet --frontier-model claude-fable-5 # Designate your fron
243
250
 
244
251
  ### Frontier-model watchdog
245
252
 
246
- `--frontier-model <model>` records, once, which model your heavy thinking is supposed to run on. The designation is per-operator (stored in `~/.claude/cc-registry.json` under `frontierModel`, not per-project), and the installer prints the effective value on every run. From then on, `/orient` and, on watchtower installs, the SessionStart hook — compares the session's actual model against it and leads the briefing with a loud warning on mismatch. The key can be an exact model ID (`claude-fable-5`, exact match required) or a family alias (`fable`, matches any model ID containing it). This is **visibility only**: nothing is pinned, blocked, or rerouted — it just makes "you're accidentally on the wrong model" impossible to miss. A stale key after a model-family transition nags loudly by design; update it with the same flag.
253
+ `--frontier-model <model>` records, once, which model your heavy thinking is supposed to run on. The designation is per-operator (stored in `~/.claude/cc-registry.json` under `frontierModel`, not per-project), and the installer prints the effective value on every run. From then on, the SessionStart hook (on watchtower installs, the default) and `/orient` on the legacy loop — compares the session's actual model against it and leads the briefing with a loud warning on mismatch. The key can be an exact model ID (`claude-fable-5`, exact match required) or a family alias (`fable`, matches any model ID containing it). This is **visibility only**: nothing is pinned, blocked, or rerouted — it just makes "you're accidentally on the wrong model" impossible to miss. A stale key after a model-family transition nags loudly by design; update it with the same flag.
247
254
 
248
255
  ## What Gets Installed
249
256
 
@@ -252,7 +259,7 @@ source code.
252
259
 
253
260
  ```
254
261
  .claude/
255
- ├── skills/ # orient, debrief, plan, execute, audit, etc.
262
+ ├── skills/ # watchtower, plan, execute, audit, orient, debrief, etc.
256
263
  │ └── cabinet-*/ # 34 cabinet member definitions
257
264
  ├── cabinet/ # committees, lifecycle, composition patterns
258
265
  │ # (incl. pib-db-access.md, pib-db-triggers.md)
@@ -294,10 +301,10 @@ with Claude everywhere.
294
301
  - **Your identity** (`~/.claude/CLAUDE.md`) — set up once, carries to
295
302
  every project. Claude always knows who you are and what you do.
296
303
  - **Project registry** (`~/.claude/cc-registry.json`) — tracks all
297
- your projects. `/onboard` asks how they relate; `/orient` flags
304
+ your projects. `/onboard` asks how they relate; the session loop flags
298
305
  when work in one might affect another.
299
- - **Debrief maintenance** — if you mention something new about yourself
300
- or your project evolves, `/debrief` proposes updating your profile
306
+ - **Profile maintenance** — if you mention something new about yourself
307
+ or your project evolves, session close proposes updating your profile
301
308
  and registry so the next session starts current.
302
309
 
303
310
  Install in each project folder. They're independent but aware of each
package/lib/cli.js CHANGED
@@ -1832,8 +1832,8 @@ async function run() {
1832
1832
  console.log('\n ✅ Cabinet assembled!\n');
1833
1833
  console.log(' Next steps:');
1834
1834
  console.log(' 1. Run /onboard in Claude Code — Claude will interview you and prepare the briefings');
1835
- console.log(' 2. Start each session with /orientget briefed');
1836
- console.log(' 3. End each session with /debrief close the loop for next time');
1835
+ console.log(' 2. Run /watchtower install to start the background rings sessions then open pre-briefed');
1836
+ console.log(' 3. /briefing is your daily surface; end sessions with /close (or /session-handoff)');
1837
1837
  const skippedKeys = Object.keys(skippedModules);
1838
1838
  if (skippedKeys.length > 0) {
1839
1839
  console.log(`\n Skipped modules: ${skippedKeys.join(', ')}`);
package/lib/modules.js CHANGED
@@ -15,8 +15,8 @@
15
15
  // unchanged.
16
16
  const MODULES = {
17
17
  'session-loop': {
18
- name: 'Session Loop (orient + debrief)',
19
- description: 'The briefing cycle. Claude starts each session informed, ends by preparing the next briefing.',
18
+ name: 'Session Loop (shared verbs + legacy orient/debrief)',
19
+ description: 'The mandatory session verbs (/menu, /session-handoff) plus the legacy orient/debrief skeletons and their -classic reversibility copies. Watchtower (installed by default) is the live session loop; orient/debrief are the opt-out fallback.',
20
20
  mandatory: true,
21
21
  templates: [
22
22
  'skills/orient',
@@ -209,9 +209,9 @@ const MODULES = {
209
209
  },
210
210
  watchtower: {
211
211
  name: 'Watchtower (continuous background state)',
212
- description: 'Replaces orient/debrief with continuous background processing. Three rings (mechanical cron, Claude intelligence, session-aware), ambient state injection via SessionStart hook, and an inbox for extracted knowledge and signals. Sessions start informed with minimal context cost.',
212
+ description: 'The default session loop. Continuous background processing replaces the legacy orient/debrief skeletons: four rings (mechanical cron, Claude intelligence, session-aware, truth reconciliation), ambient state injection via SessionStart hook, and an inbox for extracted knowledge and signals. Sessions start informed with minimal context cost. Installing the module ships the skills + dormant SessionStart hook; the background rings start only when you run /watchtower install. Opt out to fall back to the legacy orient/debrief loop.',
213
213
  mandatory: false,
214
- default: false,
214
+ default: true,
215
215
  lean: false,
216
216
  templates: [
217
217
  'scripts/watchtower-validate.mjs',
@@ -251,6 +251,7 @@ const MODULES = {
251
251
  'scripts/watchtower-ring4.mjs',
252
252
  'scripts/watchtower-ring4-runner.sh',
253
253
  'scripts/watchtower-status.sh',
254
+ 'scripts/memory-consolidation-scan.mjs',
254
255
  'skills/briefing',
255
256
  'skills/threads',
256
257
  'skills/catch-up',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-claude-cabinet",
3
- "version": "0.51.0",
3
+ "version": "0.53.0",
4
4
  "description": "Claude Cabinet — opinionated process scaffolding for Claude Code projects",
5
5
  "bin": {
6
6
  "create-claude-cabinet": "bin/create-claude-cabinet.js"
@@ -319,9 +319,22 @@ consumes the registry stays in cli.js).
319
319
  ring-filed inbox category to `{reconciler}` or `{exempt}` (exactly
320
320
  one), enforced by the structural filing-site test
321
321
  `__tests__/detector-registry.test.mjs`: it scans `category:` literals
322
- at createItem sites across ring1 + ring2 + ring3-close (read-only
323
- source scan) and fails on an unregistered category or a non-literal
324
- category value inside a filing owner (act:4d11fd53).
322
+ at createItem sites across ring1 + ring2 + ring3-close + **ring4 +
323
+ routines** (read-only source scan) and fails on an unregistered
324
+ category or a non-literal category value inside a filing owner
325
+ (act:4d11fd53; act:ea23b3a5 added the last two scripts and their
326
+ `doc-drift` / `routine` entries, closing the gap act:c2f06955 item 5
327
+ named — the contract's "maps every ring-filed category" claim was
328
+ false while ring4 and the routine engine sat outside the scan). Census
329
+ at 2026-07-26: 27 filing sites, 20 distinct categories, 20 registry
330
+ entries. **The census binds a `category:` literal to its NEAREST
331
+ PRECEDING call opener and recognises only `createItem(` and `file(` as
332
+ filing owners** — an injectable filing dep under any other name reads
333
+ as a query filter and its category silently drops out of the census.
334
+ That is not hypothetical: act:ea23b3a5's ring2 memory-budget dep, first
335
+ written as `createItemFn`, dropped `watchtower-health` out of the
336
+ filing set and the suite caught it. Name an injected filing seam
337
+ `file`.
325
338
  `GENERATED_STATE_PATTERNS`/`generatedStateIsDisposable` — the JS SSOT
326
339
  for machine-written generated state (UNTRACKED `??` lines only:
327
340
  `.claude/verification/`, advisories-state.json, checklist-stats.json,
@@ -376,15 +389,43 @@ consumes the registry stays in cli.js).
376
389
  to the lib's `resolveProjectFromTranscriptSlug` (feature-detected by
377
390
  name on the namespace import) and then to `project_unresolved: true` —
378
391
  inbox filing proceeds, but no state-file or thread key is minted from
379
- a raw slug. Phase 2c's `completionReviewEmitGuard` adds the
380
- create-vs-complete filter (act:9eebbac4): an action whose db `created`
381
- date falls inside the session's day window (+1 for past-midnight
382
- spill) with confidence below `high` is not a completion candidate (an
383
- action born this session whose only evidence is its own creation);
384
- mechanical (db row, the same prepared statement as the status
385
- re-check) and FAIL-OPEN in every gap no sessionDate, an unparseable
386
- sessionDate (windowEnd is a required conjunct), a missing `created`
387
- column, or a thrown lookup all emit. coverage-warning is now a
392
+ a raw slug. Phase 2c's `completionReviewEmitGuard` was **rebuilt on
393
+ measurement** (act:ea23b3a5): act:9eebbac4's create-vs-complete
394
+ day-window filter is DELETED and the model's `confidence: 'high'` is
395
+ SUPPRESSED instead. Over all 223 items this category had ever filed,
396
+ each joined against the cited action's OWN project db, `high` scored
397
+ 30% precision (12 acted-on / 28 dismissed-noise) against 60% for
398
+ medium+low (48 / 32) the model rates high when a session *talks
399
+ about* an action (files it, plans it, discusses it), not when it
400
+ quietly finishes one. The deleted filter exempted `high` from its
401
+ born-this-session skip, so it suppressed the BEST cohort (same-day
402
+ creation + medium/low: 74%) and passed the worst (same-day + high:
403
+ 33%); split at its 2026-07-12 ship date the category went **0-for-23**
404
+ — zero acted-on, 19 dismissed as noise. A **calibration fence** sits on
405
+ the check: the result holds for the Phase 2c confidence rubric AS
406
+ WRITTEN, so rewording that rubric requires re-running the measurement.
407
+ The per-fid dedup corpus gained `expired` + `superseded`, load-bearing
408
+ because the category's 14-day expiry equals
409
+ `COMPLETION_REVIEW_DEDUP_DAYS` (without them a fid leaves every corpus
410
+ exactly when its item expires and refiles forever). A
411
+ quoted-completion-evidence check (`verifyCompletionQuote` +
412
+ `decodeTranscriptText`) ships as **INSTRUMENTATION ONLY** — stamped to
413
+ `evidence.quote_verified`, counted per session, gating nothing: the
414
+ haystack is `preprocessTranscript`'s JSON-serialized output, so a
415
+ substring gate rejects ordinary multi-line prose (a newline is the two
416
+ characters `\` + `n`) and reliably ACCEPTS serialized TodoWrite
417
+ arguments; `decodeTranscriptText` drops `tool_use` blocks for exactly
418
+ that reason, and even decoded, containment proves a span EXISTS, never
419
+ that it means the work is done. Phase 2g (upstream friction) gained a
420
+ **three-arm actionability gate** (act:ea23b3a5, Phase 2f's
421
+ verification-gate shape): a named route from the closed vocabulary
422
+ `cc-feedback | project-tracker | config-change` with a non-empty detail
423
+ files `upstream-friction`; a durable no-route platform constraint files
424
+ `knowledge-extraction` (4 of the 5 friction items the operator KEPT
425
+ exited `captured-to-memory`, so a two-arm gate would have discarded the
426
+ useful half of the lens); anything else files nothing and is COUNTED.
427
+ Contract in `watchtower-contracts.md` ("Upstream-Friction
428
+ Actionability"). coverage-warning is now a
388
429
  STANDING-DEBT aggregation (act:e888dd63): ONE pending item per
389
430
  (project, debt-class — `COVERAGE_DEBT_CLASS`) whose evidence APPENDS
390
431
  per session (session-id union, so a reprocess replay can't inflate
@@ -394,7 +435,17 @@ consumes the registry stays in cli.js).
394
435
  at 5, urgent at 15); resolving closes the accumulated view and a
395
436
  persisting debt refiles FRESH next session. The `## Last Session`
396
437
  block names its authoritative per-session record (`appendRecordPointer`
397
- → `<slug>/sessions/<date>-<sessionId>.md`; act:8c076580).
438
+ → `<slug>/sessions/<date>-<sessionId>.md`; act:8c076580). Phase 2d
439
+ classifies non-durable facts AT extraction (act:471dd701 N2 +
440
+ act:a69c21f8): `derivable` (recomputable from a live source → home
441
+ `derivation`, the recompute instruction visible) and its twin
442
+ `perishable` (true-at-a-moment, will become false, NOT recomputable —
443
+ `perishes_when` names what falsifies it → home `session-record`);
444
+ both ALWAYS FILED to acknowledge/dismiss, never memory, never
445
+ dropped; derivable wins when both apply; the type/home vocabulary is
446
+ the exported `KNOWLEDGE_EXTRACTION_TYPES`/`_HOMES` consts
447
+ (watchtower-queue) with createItem boundary checks + a prompt-parity
448
+ test (`__tests__/extraction-classification.test.mjs`).
398
449
  - `watchtower-queue.mjs` — inbox queue CRUD library (atomic temp+rename,
399
450
  no-index convention); also home of the staff-QA recipient gate
400
451
  (2026-06-11): every terminal exit on a `qa-handoff` item is structural —
@@ -405,7 +456,19 @@ consumes the registry stays in cli.js).
405
456
  exempts the category). `emitPatternPromotion` files one deduplicated
406
457
  pattern-promotion inbox item at >=3 sweep instances of a failure class.
407
458
  `listItems()` exposes filtered item listing (project/category/status/since)
408
- for the Ring 3 dedup corpora. Terminal exits on any dispatched-category
459
+ for the Ring 3 dedup corpora. **Category expiry is single-sourced here**
460
+ (act:ea23b3a5): `expiryDaysFor` / `categoryNeverExpires` /
461
+ `CATEGORY_EXPIRE_DAYS` / `DEFAULT_EXPIRE_DAYS`, with
462
+ `categoryNeverExpires` sitting beside `expireItem`'s throw because the
463
+ qa-handoff carve-out is STRUCTURAL (returning anything but null for it
464
+ crashes the caller's loop). There are TWO expiry engines — Ring 2's
465
+ `escalateQueueItems` cron and `runExpiry`, which `/inbox` and
466
+ `/briefing` call — and each previously hardcoded 30 days with its own
467
+ inlined carve-out, so a per-category policy set in one was silently
468
+ violated by whichever reached the item first. Both now delegate.
469
+ completion-review is the first override at 14 days; note that a
470
+ shortened expiry can open a refile loop when it meets its filing site's
471
+ dedup window (see the "Category Expiry" contract). Terminal exits on any dispatched-category
409
472
  item (`qa-handoff`, `routine` — the DISPATCHED_CATEGORIES set; resolve /
410
473
  typed dismiss / supersede / expire) also clear the matching mux
411
474
  dispatch-queue descriptor — queued AND in-flight, across all desk dirs —
@@ -491,6 +554,23 @@ consumes the registry stays in cli.js).
491
554
  descriptor through `mux qa dispatch` — the SAME hardened desk-dispatch path
492
555
  as qa-handoffs, never a fork. Pending-item dedup blocks refiring; stale
493
556
  pending firings (default 24h) are superseded + redispatched.
557
+ `sweepExpiredMoments` (act:ea23b3a5) adds **end-of-day moment expiry for
558
+ `time-of-day` triggers**: Ring 1's tick supersedes a pending item once
559
+ the calendar day it was FILED on has ended, instead of waiting 24h for
560
+ the next firing. End-of-day rather than a fixed window is a measured
561
+ choice — the portfolio's one time-of-day routine had 10 real pickups in
562
+ six weeks, 8 within four hours and 2 after (4.4h, 8.6h), so a 4h window
563
+ would have destroyed two genuine pickups to clear one stale item.
564
+ Scoped to Ring 1's PORTFOLIO tick (Ring 3's single-project
565
+ session-close call would otherwise sweep every other project's items,
566
+ once per replayed session during a reprocess drain), classified from
567
+ `item.evidence.trigger` rather than config (so a de-registered routine
568
+ still classifies instead of rotting), and an unparseable `filed_at`
569
+ ABSTAINS loudly rather than sweeping (the `stale_after_hours` path
570
+ treats the same input as stale — two mechanisms disagreeing silently is
571
+ worse than one abstaining out loud). For time-of-day the moment sweep
572
+ now pre-empts the `stale_after_hours` supersede; interval /
573
+ path-nonempty / session-close have no moment and are untouched.
494
574
  `buildPickupPrompt` (the dispatch pickup-prompt wording, including the
495
575
  resolve-on-run that clears the badge) is exported and reused by the
496
576
  build-context missed-routine re-delivery (act:4b4fa7d9), so the wording is
@@ -745,7 +825,9 @@ modules total.
745
825
 
746
826
  ## session-loop (mandatory)
747
827
 
748
- orient + debrief skeleton skills.
828
+ The LEGACY orient + debrief skeleton skills plus shared session verbs.
829
+ Watchtower (default-installed) is now the live session loop; orient/debrief
830
+ are the opt-out fallback, kept shipping via this mandatory module.
749
831
  `/orient` leads with the frontier-model watchdog (core phase #0): compares
750
832
  the session model against the per-operator `frontierModel` key in
751
833
  `~/.claude/cc-registry.json` (set via the `--frontier-model` installer flag;
@@ -776,9 +858,17 @@ dedup-vs-pending discipline as Ring 3 Phase 2m; see "Session Advisor Pass" in
776
858
  UNTRACKED marker with neither — and the rendered line cites the filed id;
777
859
  debrief's 16b also verifies persistence.
778
860
  Ships `/session-handoff`, the **default session-close verb**: a thin wrapper
779
- over `/debrief` that runs three phases (1) debrief, whose
780
- `qa-handoff-sweep.md` instruction phase performs a `/qa-handoff` for every
781
- worktree→main merge this session still needs one for; (2) propose a
861
+ over `/close` plus the handoff extras the rings can't own after walk-away
862
+ (act:9ce4dfde repointed off full `/debrief`, whose ring-redundant capture
863
+ was the defect). It runs three phases (1) `/close` (commit + push, and on
864
+ a worktree its conditional gated-merge offer), then debrief's
865
+ `qa-handoff-sweep.md` phase (a `/qa-handoff` for every worktree→main merge
866
+ this session still needs one for) and `methodology-capture.md` (the one
867
+ capture phase with no ring twin — Ring 3 only DETECTS an already-written
868
+ `.claude/methodology/` record, it can't author one or ask the four-choice
869
+ question, so it stays on the default path); the heavy debrief capture
870
+ (lessons/knowledge/upstream-friction/session-advisors) is NOT run — the
871
+ rings own it after close; (2) propose a
782
872
  next-session seed prompt (non-QA work thread only — QA drains belong to
783
873
  window 1's standing station), operator approves/rejects, and ONLY on approve
784
874
  launch the next session in a **fresh worktree** (via the `mux handoff
@@ -792,7 +882,9 @@ window is already up): it surfaces this project's watchtower threads/cursors
792
882
  in plain English (read-only, temporal-labeled, cap 3) and offers at most one
793
883
  well-explained inbox decision (drained via `applyBatch`, gated/dispatched
794
884
  categories excluded) — strictly skippable, two frozen sections, growth routes
795
- to `/briefing`. Plain `/debrief` stays the "nothing queued" close. The sweep
885
+ to `/briefing`. Plain `/close` is the "nothing queued" close; plain
886
+ `/debrief` is the opt-in heavy synchronous capture (kept, off the default
887
+ path — act:9ce4dfde). The sweep
796
888
  self-skips without watchtower; the launch degrades to a saved seed path
797
889
  without mux; the epilogue self-skips without watchtower.
798
890
  Also ships `/orient-classic` and `/debrief-classic` (act:6fa60c7d):
@@ -855,11 +947,16 @@ provider-agnostic email/MCP/file/API transport). 3 primary skills
855
947
  for old skill names. `requires: ['work-tracking']` (the pib-db adapter is the
856
948
  engine's data source). Evolved from the former handoff module.
857
949
 
858
- ## watchtower (opt-in, off by default)
950
+ ## watchtower (default-installed, opt-out)
859
951
 
860
- Continuous background state management replacing orient/debrief with four
952
+ THE default session loop. Continuous background state management replacing
953
+ the legacy orient/debrief with four
861
954
  processing rings (mechanical cron, Claude intelligence, session-aware,
862
- periodic truth reconciliation). All four rings implemented: Ring 1
955
+ periodic truth reconciliation). Installing the module ships the skills + a
956
+ dormant SessionStart hook; the metered background rings start only on
957
+ `/watchtower install`, so a fresh default install incurs no API cost until
958
+ the operator activates them. Opt out to fall back to the legacy
959
+ orient/debrief loop. All four rings implemented: Ring 1
863
960
  (mechanical heartbeat, 5-min cron; also delivers the global CC feedback
864
961
  outbox every tick via `flushFeedbackOutbox()`, ticks declared-routine
865
962
  triggers via `runRoutinePass()`, surfaces a READ-ONLY
@@ -894,7 +991,17 @@ summary attention aggregates portfolio-wide pib errors into ONE line (almost
894
991
  always a single system-level fault; Ring 2's `openPibDb` logs instead of
895
992
  silently nulling); the memory-integrity check delegates to
896
993
  `checkMemoryReachability` (watchtower-lib) — reachability, never
897
- filename-substring (act:49cb1c27). Ring 1's worktree-unmerged +
994
+ filename-substring (act:49cb1c27). Standing Issues also renders the
995
+ **cabinet-roster ambient lines** (act:ea23b3a5, `readRosterMetrics` +
996
+ `renderRosterEntries`): dormant-skill and stale-briefing counts stopped
997
+ being `advisor-finding` queue items and became a Ring 2 measurement that
998
+ Ring 1 renders — the same relationship as the recall canary (the
999
+ measurement is Ring 2's, the render is Ring 1's, because Ring 1 owns the
1000
+ per-project state file). Rendered ON CHANGE only and carrying skill
1001
+ NAMES, because ambient state has no dismiss verb and a number that never
1002
+ moves is furniture by the third read; the count itself had to be fixed
1003
+ first, since `ROSTER_DORMANT_LIST_CAP` saturated it and every project
1004
+ ever measured reported exactly "12 dead". Ring 1's worktree-unmerged +
898
1005
  branch-diverged detectors flag on CONTENT, not ahead-count (act:a152cf6c): a
899
1006
  squash-merge leaves a branch a non-ancestor of main with phantom "ahead"
900
1007
  commits but an IDENTICAL tree, so the old ancestry/`aheadCount` gates flagged
@@ -942,11 +1049,60 @@ knowledge-extraction drafts with freshness (cited `act:` fids positively
942
1049
  CLOSED in the item's own project pib-db — parameter-bound lookups via
943
1050
  `openPibDb`, now `timeout: 5000` for lock parity with Ring 3) and fold
944
1051
  proposals (the watchtower-queue recipe), demoting them out of batch
945
- sign-off, never dismissing; unreadable dbs and out-of-config drafts are
946
- counted LOUDLY (`skipped_projects`/`unscanned_items`) and every run
947
- writes the positive-confirmation sidecar
1052
+ sign-off, never dismissing; act:09184ad7 added a SECOND fold corpus —
1053
+ pending pattern-promotion items, grouped per `evidence.target_member`
1054
+ (cross-member similarity is never a duplicate), so near-duplicate
1055
+ pattern variants arrive pre-annotated for the next consolidation pass
1056
+ (`pattern_items_scanned`/`pattern_fold_annotated`/
1057
+ `unscanned_pattern_items` counters); act:ea23b3a5 added a THIRD corpus —
1058
+ pending `raised-unhandled` loose ends, grouped per project
1059
+ (`loose_end_items_scanned`/`loose_end_fold_annotated`). That third corpus
1060
+ is where the spec's "aggregate recurring loose ends into ONE item"
1061
+ landed after measurement refused the merge: `proposeFolds` scores with
1062
+ `overlapCoefficient` (act:421a8ab2 retired `unigramJaccard`), whose
1063
+ `min()` denominator lets two three-token titles sharing ONE word clear
1064
+ `FOLD_SIMILARITY_THRESHOLD = 0.22` — four false folds in fifteen pairs
1065
+ against the six live titles — and the five timelog specimens were
1066
+ resolved `deferred` (real work the operator postponed, across two
1067
+ projects and three date ranges), so merging would have buried which gaps
1068
+ remain. The threshold was calibrated for ADVISORY retrieval, not a
1069
+ destructive merge: **a lexical matcher may propose, never silently
1070
+ suppress.** Unreadable dbs and out-of-config
1071
+ items are counted LOUDLY (`skipped_projects`/`unscanned_items`) and
1072
+ every run writes the positive-confirmation sidecar
948
1073
  `state/draft-annotations-health.json`, so "no annotations" is
949
- distinguishable from "never ran"), Ring 3 (session close, transcript
1074
+ distinguishable from "never ran". The slow tier also owns the
1075
+ **memory-budget standing debt + its retraction** (act:ea23b3a5):
1076
+ `surfacePersistentViolations` files ONE accumulating `watchtower-health`
1077
+ item per project instead of a fresh one every 7 days — keyed by CALENDAR
1078
+ DAY (a per-run key would count ~48 cron ticks a day and make the replay
1079
+ guard dead code), appended via `annotateItemEvidence` so `filed_at` is
1080
+ never bumped, carrying `session_count` because that is the spelling
1081
+ `itemSessionWeight` already reads — and `retractClearedMemoryBudgetItems`
1082
+ retracts on the SAME pass over the `passProjects` `runMemoryHygiene`
1083
+ already computes. Deliberately not in Ring 1: a second memory-health
1084
+ producer is forbidden by name in `watchtower-contracts.md`, and at a
1085
+ 30-minute throttle against ring2's 30-minute cadence it would buy zero
1086
+ freshness. Both selectors match the LEGACY `{violations, streak}` title
1087
+ shape as well as the new `debt_class`, because every item on disk when
1088
+ this shipped carried the former. The cabinet-roster review now files only
1089
+ `uncovered-tech` (a proposed cabinet seat is a decision); `dormant-skill`
1090
+ and `stale-briefing` became ambient metrics in `state/roster-review.json`
1091
+ (`parseDormantSkills` reports TRUE counts — the cap bounds the NAME list
1092
+ only) and `retireRosterFindingItems` supersedes any of the two retired
1093
+ kinds still pending, since the filing site was the only code that ever
1094
+ touched them. The slow tier's `scanAuditPatterns`
1095
+ (the pattern-promotion filing site) now runs the act:09184ad7
1096
+ emission-quality SHAPE GATE — `patternHasRequiredShape` requires the
1097
+ `**Evidence:**` + `**Gap:**` blocks Phase 2e's prompt mandates, rejecting
1098
+ document echoes (wave ledgers, dependency graphs, recipes, transcript
1099
+ fragments — 17/144 items in the 2026-07-26 consolidation) BEFORE the
1100
+ routing Claude call; rejections are counted loudly
1101
+ (`rejected_malformed_total`/`last_scan_rejected` in
1102
+ `state/pattern-detection.json`) and their hashes marked processed, never
1103
+ retried. Calibrated against the consolidation corpus: 120/120 legitimate
1104
+ bodies pass, 17/17 fragments fail; hermetic suite in
1105
+ `__tests__/ring2-pattern-gate.test.mjs`), Ring 3 (session close, transcript
950
1106
  processing; fires session-close routines as Phase 2j2; runs the standing
951
1107
  session advisors as Phase 2m — see
952
1108
  below; runs three session-close extraction lenses (act:4ff2cfb3) — Phase 2n
@@ -954,7 +1110,12 @@ raised-but-unhandled (loose ends the session raised but neither did nor filed
954
1110
  → inbox category `raised-unhandled`), Phase 2o skill-candidate (a manual
955
1111
  procedure repeated by hand → `skill-candidate` inbox item), Phase 2p
956
1112
  checklist-catch (a surfaced change-impact check that caught a real bug →
957
- `checklist-stats.json`); its Phase 2h feedback "flush" was deleted 2026-06-12
1113
+ `checklist-stats.json`); its Phase 2e quality-pattern prompt is the exported
1114
+ `QUALITY_PATTERN_SYSTEM_PROMPT` carrying the act:09184ad7 generation-side
1115
+ exclusions — no-gap positives, transcript-artifact observations, document
1116
+ echoes are never patterns — the prompt half of ring2's mechanical shape
1117
+ gate, guarded by `__tests__/ring2-pattern-gate.test.mjs`; its Phase 2h
1118
+ feedback "flush" was deleted 2026-06-12
958
1119
  — it marked without delivering), Ring 4 (periodic truth reconciliation,
959
1120
  act:36dae795 — stage-1 BUILT, weekly cadence; cron/launchd registration is a
960
1121
  deferred `/watchtower install` follow-up). Ring 4 mechanically compares
@@ -1015,9 +1176,13 @@ mid-session awareness refresh — diffs current watchtower state against a
1015
1176
  per-session baseline captured at session start and shows only what CHANGED
1016
1177
  since; new inbox items, advanced/new threads, new/cleared git attention,
1017
1178
  freshly-due deferrals; thin orchestrator over `watchtower-snapshot.mjs`;
1018
- act:a8057f87), `/close` (fast session-end verb — commit + push only; the
1019
- background rings handle inventory/capture/routing after you walk away;
1020
- targets 15–30s, never `--no-verify`; act:8bf86966), and `/qa-handoff`
1179
+ act:a8057f87), `/close` (fast session-end verb — commit + push, plus on an
1180
+ ORPHANED worktree only (unmerged content AND no qa-handoff filed) a
1181
+ conditional offer to land the branch via the existing `/execute` Step 8 /
1182
+ qa-handoff merge-now recipe, so the rings don't file `worktree-unmerged`
1183
+ (act:9ce4dfde) — `/qa-handoff` stays the primary merge path; the background
1184
+ rings handle inventory/capture/routing after you walk away; targets 15–30s,
1185
+ never `--no-verify`; act:8bf86966), and `/qa-handoff`
1021
1186
  (package a worktree branch into a surfaced `qa-handoff` inbox item — what
1022
1187
  merged, what the worktree could NOT runtime-verify, what hangs on the next
1023
1188
  step — then push it to the desk's main window via `mux qa dispatch`; usually
@@ -15,6 +15,13 @@ You and Claude will make different choices for your project. These
15
15
  examples show what choices Flow made and why — not what you should do,
16
16
  but what's possible.
17
17
 
18
+ > **Note — orient/debrief are legacy.** Watchtower is CC's default session
19
+ > loop now; the orient/debrief skeletons used as examples below are the
20
+ > opt-out fallback, and Flow itself has since moved to watchtower. These
21
+ > tables are preserved as a worked example of the **phase-file extension
22
+ > mechanism**, which applies to any skeleton skill — not as a
23
+ > recommendation to build new work on orient/debrief.
24
+
18
25
 
19
26
  ## Flow's Phase File Overrides by Skill
20
27
 
@@ -47,8 +47,8 @@ templates, see [EXTENSIONS.md](EXTENSIONS.md).
47
47
  | `skills/memory/` | Browse, search, validate, and manage built-in memory at `~/.claude/projects/<slug>/memory/`. Writing happens via /cc-remember. |
48
48
  | `skills/menu/` | Dynamically discover and display all available skills. Reads from `_index.json`. |
49
49
  | `skills/onboard/` | Conversational onboarding. Interviews you, generates briefings, wires the session loop. Re-runnable. 8 phase files. |
50
- | `skills/orient/` | Session start. Load context, sync data, scan work, run health checks, spawn cabinet consultations, show skills menu. 7 phase files. |
51
- | `skills/orient-quick/` | Quick orient variant — core phases only, skip presentation. |
50
+ | `skills/orient/` | Session start (legacy loop — watchtower is the default). Load context, sync data, scan work, run health checks, spawn cabinet consultations, show skills menu. 7 phase files. |
51
+ | `skills/orient-quick/` | Quick orient variant (legacy) — core phases only, skip presentation. |
52
52
  | `skills/plan/` | Structured planning with cabinet critique. Research, overlap check, draft, critique, completeness, present, file. 9 phase files. |
53
53
  | `skills/cc-publish/` | Publish workflow (CC source repo only, not shipped to consumers). |
54
54
  | `skills/pulse/` | Self-description accuracy check. Count freshness, dead references, staleness. 3 phase files. |
@@ -173,7 +173,7 @@ into your project's `.claude/` directory. The minimum viable adoption:
173
173
 
174
174
  You now have git safety and skill discovery. Add more modules as needed:
175
175
 
176
- - **Session loop:** `skills/orient/`, `skills/debrief/`
176
+ - **Session loop (default):** `skills/watchtower/` + the SessionStart hook. Legacy fallback: `skills/orient/`, `skills/debrief/`
177
177
  - **Planning:** `skills/plan/`, `skills/execute/`
178
178
  - **Audit:** `skills/audit/`, `skills/pulse/`, `skills/triage-audit/`, plus `cabinet/` infrastructure and `scripts/`
179
179
  - **Cabinet members:** Copy individual `skills/cabinet-*/` directories for the experts you want
@@ -54,7 +54,7 @@ Template: `_briefing-cabinet-template.md`.
54
54
 
55
55
  ### `_briefing-work-tracking.md` — Work Tracking
56
56
  How the project tracks planned work — storage, query interface,
57
- mutation interface. Referenced by /plan, /execute, /orient, /debrief.
57
+ mutation interface. Referenced by /plan, /execute, and the session loop.
58
58
  Template: `_briefing-work-tracking-template.md`.
59
59
 
60
60
  ### `_briefing-api.md` — API Configuration
@@ -1,7 +1,7 @@
1
1
  # Work Tracking — [Your Project Name]
2
2
 
3
3
  How this project tracks planned work. Skills that manage work items
4
- (/plan, /execute, /orient, /debrief) reference this file.
4
+ (/plan, /execute, and the session loop) reference this file.
5
5
 
6
6
  ## Work Item Storage
7
7
  *Where work items live.*
@@ -27,8 +27,8 @@ already tracking. It sits quietly until you unblock it yourself.
27
27
 
28
28
  **Trigger-gated deferral** is for work waiting on an identifiable
29
29
  external condition — a dependency landing, a stack decision
30
- finalizing, a referenced file appearing. Every session, orient
31
- re-evaluates each trigger against the current session's context
30
+ finalizing, a referenced file appearing. Every session, the session
31
+ loop re-evaluates each trigger against the current session's context
32
32
  and surfaces items whose conditions have fired. Use
33
33
  `pib_defer_with_trigger` (or `defer-with-trigger` CLI). See
34
34
  `cabinet/pib-db-triggers.md` for the full convention.
@@ -26,11 +26,13 @@ briefing:
26
26
  # Add other briefing files relevant to this member's domain
27
27
  # Common: .claude/cabinet/_briefing-architecture.md, _briefing-jurisdictions.md, _briefing-api.md
28
28
  standing-mandate: audit
29
- # Add plan, execute, orient, debrief if this member should activate
30
- # in those contexts. Most members are audit-only. Two session-boundary
31
- # contexts exist for standing advisors (watchtower installs):
32
- # session-close (Ring 3's automatic transcript-fed advisor pass) and
33
- # briefing (/briefing's live advisor panel).
29
+ # Add plan or execute if this member should activate in those contexts.
30
+ # Most members are audit-only. Two session-boundary contexts exist for
31
+ # standing advisors (watchtower is the default loop): session-close
32
+ # (Ring 3's automatic transcript-fed advisor pass) and briefing
33
+ # (/briefing's live advisor panel). The legacy orient/debrief contexts
34
+ # still work on projects that opted out of watchtower, but new advisors
35
+ # should use session-close/briefing.
34
36
  tools:
35
37
  # List every external tool/command this member uses.
36
38
  # Format: "tool-name (scope -- what it does)"
@@ -40,8 +42,9 @@ tools:
40
42
  # - grep patterns (all projects -- dead code detection)
41
43
  # Use "tools: []" for pure-reasoning members with no tool stage.
42
44
  directives:
43
- # Only if standing-mandate includes plan, execute, orient, debrief,
44
- # session-close, or briefing. Each directive is a one-sentence focused
45
+ # Only if standing-mandate includes plan, execute, session-close,
46
+ # briefing, or (legacy loop) orient, debrief. Each directive is a
47
+ # one-sentence focused
45
48
  # task for that context. A mandate without a matching directive is a
46
49
  # data error — consumers skip the member and say so.
47
50
  # plan: >
@@ -115,6 +115,22 @@ into a corner):
115
115
  pinned/load-bearing entry files to the inbox; it never auto-applies,
116
116
  because the *gist* becomes the retrieved truth and a wrong gist erases
117
117
  a load-bearing detail.
118
+
119
+ **Evidence this verb has real work (act:421a8ab2, N5 of
120
+ grp:retro-remeaning):** two blind reads of the maginnis durable-memory
121
+ corpus (2026-07-19) found ~47-60% of sampled files involved in a hard
122
+ duplicate — overwhelmingly outage-recovery extractions and the
123
+ 2026-07-14 read-pass, both bulk-written without a MEMORY.md index line
124
+ (region-pointer-covered instead), which made the dedup structurally
125
+ blind to them. `templates/scripts/memory-consolidation-scan.mjs` is the
126
+ dry-run PROPOSAL half of this verb, built ahead of the full Stage 2 gate:
127
+ it reuses the (now overlap-coefficient, dual-scored — see
128
+ `proposeFolds` in `watchtower-queue.mjs`) fold detector over an actual
129
+ memory directory's files instead of the pending inbox queue, and reports
130
+ candidate pairs with a `consolidated_from` pointer. It never merges or
131
+ writes — the human decides. Running the full MERGE half (rewriting
132
+ files, folding gists) is still gated on the spill-rate data per this
133
+ contract; the scan only proposes what the merge would act on.
118
134
  - **supersede** — mark an entry false/obsolete so retrieval stops
119
135
  surfacing it as live truth (kept on disk for audit, with a reverse
120
136
  breadcrumb in its successor). Deferred until the frontmatter-parsing