create-claude-cabinet 0.46.0 → 0.48.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.
- package/README.md +3 -6
- package/lib/CLAUDE.md +218 -0
- package/lib/cli.js +397 -382
- package/lib/copy.js +182 -6
- package/lib/db-setup.js +122 -17
- package/lib/engagement-server-setup.js +1 -17
- package/lib/engagement-setup.js +1 -1
- package/lib/installer-gate.js +135 -0
- package/lib/metadata.js +51 -2
- package/lib/modules.js +292 -0
- package/lib/mux-setup.js +1 -17
- package/lib/project-context.js +16 -96
- package/lib/settings-merge.js +194 -13
- package/lib/site-audit-setup.js +23 -7
- package/lib/verify-setup.js +20 -9
- package/lib/watchtower-setup.js +23 -7
- package/package.json +1 -1
- package/templates/CLAUDE.md +959 -0
- package/templates/briefing/_briefing-template.md +6 -11
- package/templates/cabinet/advisories-state-schema.md +1 -1
- package/templates/cabinet/checklist-stats-schema.md +15 -1
- package/templates/cabinet/eval-protocol.md +27 -10
- package/templates/cabinet/memory-lifecycle-contract.md +135 -0
- package/templates/cabinet/pib-db-access.md +13 -0
- package/templates/cabinet/watchtower-contracts.md +453 -0
- package/templates/cabinet/worktree-invocation-contract.md +111 -0
- package/templates/engagement/OVERVIEW.md +12 -0
- package/templates/engagement/__tests__/checklist-visibility.test.mjs +76 -0
- package/templates/engagement/__tests__/engagement.test.mjs +177 -2
- package/templates/engagement/__tests__/invoice-doc.test.mjs +195 -0
- package/templates/engagement/engagement-checklist.mjs +26 -2
- package/templates/engagement/engagement-preview.mjs +100 -0
- package/templates/engagement/engagement-schema.md +248 -6
- package/templates/engagement/engagement.mjs +391 -11
- package/templates/engagement/pib-db-patches/pib-db-lib.mjs +49 -9
- package/templates/engagement/pib-db-patches/pib-db-mcp-server.mjs +5 -44
- package/templates/engagement/pib-db-patches/pib-db-schema.sql +1 -1
- package/templates/engagement/pib-db-patches/pib-db.mjs +9 -3
- package/templates/engagement/sql-constants.mjs +9 -1
- package/templates/engagement-server/__tests__/cross-tenant-auth.test.mjs +87 -0
- package/templates/engagement-server/server.mjs +65 -40
- package/templates/hooks/action-completion-gate.sh +19 -3
- package/templates/hooks/action-quality-gate.sh +10 -0
- package/templates/hooks/memory-index-guard.sh +17 -11
- package/templates/hooks/skill-telemetry.sh +10 -5
- package/templates/hooks/skill-tool-telemetry.sh +11 -5
- package/templates/hooks/watchtower-session-start.sh +24 -2
- package/templates/mcp/pib-db.json +1 -4
- package/templates/mux/bin/mux +8 -1
- package/templates/mux/config/help.txt +1 -0
- package/templates/rules/acknowledge-when-corrected.md +33 -0
- package/templates/rules/enforcement-pipeline.md +0 -12
- package/templates/rules/maintainability.md +11 -0
- package/templates/rules/memory-capture.md +26 -4
- package/templates/rules/plan-before-bulk-or-irreversible-actions.md +48 -0
- package/templates/rules/verify-before-asserting.md +79 -0
- package/templates/scripts/__tests__/ahead-check-origin.test.mjs +355 -0
- package/templates/scripts/__tests__/api-usage-idle-gate.test.mjs +81 -0
- package/templates/scripts/__tests__/batch-disposition.test.mjs +98 -0
- package/templates/scripts/__tests__/bsql-loader-verify.test.mjs +47 -0
- package/templates/scripts/__tests__/claude-churn-authored.test.mjs +90 -0
- package/templates/scripts/__tests__/cross-ring-reader.test.mjs +505 -0
- package/templates/scripts/__tests__/dx-captures-briefing.test.mjs +169 -0
- package/templates/scripts/__tests__/hook-runner.test.mjs +247 -0
- package/templates/scripts/__tests__/inbox-assessment.test.mjs +341 -0
- package/templates/scripts/__tests__/memory-reachability.test.mjs +150 -0
- package/templates/scripts/__tests__/narrative-corpus.test.mjs +247 -0
- package/templates/scripts/__tests__/phase-shim.test.mjs +112 -0
- package/templates/scripts/__tests__/qa-handoff-merge-state.test.mjs +162 -0
- package/templates/scripts/__tests__/resolve-cli.test.mjs +314 -0
- package/templates/scripts/__tests__/ring-state-ownership.test.mjs +120 -0
- package/templates/scripts/__tests__/ring1-content-detector.test.mjs +168 -0
- package/templates/scripts/__tests__/ring1-flagged-actions.test.mjs +135 -0
- package/templates/scripts/__tests__/ring1-pib-error-surfacing.test.mjs +69 -0
- package/templates/scripts/__tests__/ring1-script-drift.test.mjs +126 -0
- package/templates/scripts/__tests__/ring1-stale-open-counts.test.mjs +143 -0
- package/templates/scripts/__tests__/ring2-queue-reader.test.mjs +80 -0
- package/templates/scripts/__tests__/ring2-recall-canary.test.mjs +150 -0
- package/templates/scripts/__tests__/ring2-roster-review.test.mjs +311 -0
- package/templates/scripts/__tests__/ring3-chunk-merge.test.mjs +122 -0
- package/templates/scripts/__tests__/ring3-close-lenses.test.mjs +359 -0
- package/templates/scripts/__tests__/ring3-dedup.test.mjs +92 -12
- package/templates/scripts/__tests__/ring3-memory-titles.test.mjs +187 -0
- package/templates/scripts/__tests__/ring3-novelty-rescue.test.mjs +148 -0
- package/templates/scripts/__tests__/ring3-recent-slice.test.mjs +101 -0
- package/templates/scripts/__tests__/ring3-thread-capture.test.mjs +213 -0
- package/templates/scripts/__tests__/ring4-reconcile.test.mjs +393 -0
- package/templates/scripts/__tests__/shared-thread-reader.test.mjs +187 -0
- package/templates/scripts/__tests__/suppression-ledger.test.mjs +148 -0
- package/templates/scripts/__tests__/verify-backfill.test.mjs +103 -0
- package/templates/scripts/__tests__/verify-coverage.test.mjs +80 -0
- package/templates/scripts/__tests__/watchtower-snapshot.test.mjs +261 -0
- package/templates/scripts/__tests__/watchtower-status-ring4.test.mjs +89 -0
- package/templates/scripts/__tests__/watchtower-sync.test.mjs +311 -0
- package/templates/scripts/audit-coherence-check.mjs +123 -0
- package/templates/scripts/audit-synth.mjs +117 -0
- package/templates/scripts/load-triage-history.js +5 -2
- package/templates/scripts/merge-findings.js +4 -1
- package/templates/scripts/patterns-scope-check.mjs +122 -0
- package/templates/scripts/pib-db-lib.mjs +61 -11
- package/templates/scripts/pib-db-mcp-server.mjs +7 -45
- package/templates/scripts/pib-db-path.mjs +61 -0
- package/templates/scripts/pib-db.mjs +7 -3
- package/templates/scripts/review-server.mjs +7 -12
- package/templates/scripts/triage-server.mjs +7 -8
- package/templates/scripts/validate-memory.mjs +214 -16
- package/templates/scripts/watchtower-advisories.mjs +7 -3
- package/templates/scripts/watchtower-build-context.mjs +192 -8
- package/templates/scripts/watchtower-cross-ring-reader.mjs +714 -0
- package/templates/scripts/watchtower-hook-runner.mjs +422 -0
- package/templates/scripts/watchtower-inbox-assessment.mjs +706 -0
- package/templates/scripts/watchtower-lib.mjs +555 -8
- package/templates/scripts/watchtower-narrative-corpus.mjs +385 -0
- package/templates/scripts/watchtower-phase-shim.mjs +171 -0
- package/templates/scripts/watchtower-queue.mjs +341 -3
- package/templates/scripts/watchtower-ring1.mjs +481 -81
- package/templates/scripts/watchtower-ring2.mjs +748 -80
- package/templates/scripts/watchtower-ring3-close.mjs +1147 -167
- package/templates/scripts/watchtower-ring4-runner.sh +85 -0
- package/templates/scripts/watchtower-ring4.mjs +753 -0
- package/templates/scripts/watchtower-routines.mjs +1 -1
- package/templates/scripts/watchtower-snapshot.mjs +452 -0
- package/templates/scripts/watchtower-status.sh +17 -0
- package/templates/scripts/watchtower-sync.mjs +393 -0
- package/templates/scripts/work-tracker-server.mjs +26 -22
- package/templates/skills/audit/SKILL.md +18 -5
- package/templates/skills/audit/phases/structural-checks.md +22 -0
- package/templates/skills/briefing/SKILL.md +289 -41
- package/templates/skills/cabinet-accessibility/SKILL.md +1 -1
- package/templates/skills/cabinet-process-therapist/SKILL.md +28 -0
- package/templates/skills/cabinet-security/SKILL.md +11 -0
- package/templates/skills/catch-up/SKILL.md +113 -0
- package/templates/skills/cc-publish/SKILL.md +89 -18
- package/templates/skills/cc-remember/SKILL.md +45 -0
- package/templates/skills/close/SKILL.md +107 -0
- package/templates/skills/collab-client/SKILL.md +22 -5
- package/templates/skills/collab-consultant/SKILL.md +110 -2
- package/templates/skills/debrief/SKILL.md +21 -4
- package/templates/skills/debrief/phases/audit-pattern-capture.md +13 -0
- package/templates/skills/debrief-classic/SKILL.md +696 -0
- package/templates/skills/debrief-classic/calibration.md +44 -0
- package/templates/skills/debrief-classic/phases/audit-pattern-capture.md +78 -0
- package/templates/skills/debrief-classic/phases/auto-maintenance.md +48 -0
- package/templates/skills/debrief-classic/phases/checklist-feedback.md +123 -0
- package/templates/skills/debrief-classic/phases/close-work.md +163 -0
- package/templates/skills/debrief-classic/phases/health-checks.md +54 -0
- package/templates/skills/debrief-classic/phases/inventory.md +40 -0
- package/templates/skills/debrief-classic/phases/loose-ends.md +52 -0
- package/templates/skills/debrief-classic/phases/methodology-capture.md +223 -0
- package/templates/skills/debrief-classic/phases/qa-handoff-sweep.md +78 -0
- package/templates/skills/debrief-classic/phases/record-lessons.md +177 -0
- package/templates/skills/debrief-classic/phases/report.md +59 -0
- package/templates/skills/debrief-classic/phases/update-state.md +48 -0
- package/templates/skills/debrief-classic/phases/upstream-feedback.md +185 -0
- package/templates/skills/debrief-classic/phases/verify-coverage.md +101 -0
- package/templates/skills/execute/SKILL.md +71 -6
- package/templates/skills/execute/phases/commit-and-deploy.md +8 -0
- package/templates/skills/execute-group/SKILL.md +23 -26
- package/templates/skills/generate-plan-groups/SKILL.md +20 -0
- package/templates/skills/inbox/SKILL.md +177 -31
- package/templates/skills/memory/SKILL.md +22 -6
- package/templates/skills/orient/SKILL.md +75 -5
- package/templates/skills/orient-classic/SKILL.md +770 -0
- package/templates/skills/orient-classic/phases/auto-maintenance.md +52 -0
- package/templates/skills/orient-classic/phases/briefing.md +53 -0
- package/templates/skills/orient-classic/phases/cabinet.md +46 -0
- package/templates/skills/orient-classic/phases/checklist-status.md +54 -0
- package/templates/skills/orient-classic/phases/context.md +88 -0
- package/templates/skills/orient-classic/phases/data-sync.md +35 -0
- package/templates/skills/orient-classic/phases/deferred-check.md +55 -0
- package/templates/skills/orient-classic/phases/dx-captures.md +53 -0
- package/templates/skills/orient-classic/phases/health-checks.md +50 -0
- package/templates/skills/orient-classic/phases/verify-backfill.md +109 -0
- package/templates/skills/orient-classic/phases/work-scan.md +69 -0
- package/templates/skills/pulse/SKILL.md +10 -8
- package/templates/skills/qa-drain/SKILL.md +38 -0
- package/templates/skills/qa-handoff/SKILL.md +287 -46
- package/templates/skills/setup-accounts/SKILL.md +38 -16
- package/templates/skills/spring-clean/SKILL.md +1 -1
- package/templates/skills/spring-clean/phases/execute-decisions.md +1 -1
- package/templates/skills/threads/SKILL.md +4 -0
- package/templates/skills/validate/phases/validators.md +127 -0
- package/templates/skills/watchtower/SKILL.md +174 -30
- package/templates/verify-runtime/CONVENTIONS.md +9 -0
- package/templates/verify-runtime/README.md +37 -0
- package/templates/watchtower/config.json.template +8 -2
- package/templates/workflows/deliberative-audit.js +258 -87
- package/templates/workflows/execute-group-complete.js +26 -3
- package/templates/workflows/execute-group-implement.js +16 -2
|
@@ -5,10 +5,13 @@ description: |
|
|
|
5
5
|
project by project — plain-English state, what deserves attention,
|
|
6
6
|
and the project's pending inbox items batched into proposed
|
|
7
7
|
dispositions you approve in-conversation. Decisions are chunked by
|
|
8
|
-
project, never interleaved. Also handles /recap (factual-only mode)
|
|
8
|
+
project, never interleaved. Also handles /recap (factual-only mode)
|
|
9
|
+
and a per-project decision-lineage drill-down ("why is this project
|
|
10
|
+
the way it is — what still constrains it").
|
|
9
11
|
Use when: "briefing", "brief me", "/briefing", "what's the landscape",
|
|
10
|
-
"recap", "/recap", "what happened", "what did I do yesterday"
|
|
11
|
-
|
|
12
|
+
"recap", "/recap", "what happened", "what did I do yesterday",
|
|
13
|
+
"decision lineage", "why is this the way it is".
|
|
14
|
+
argument-hint: "scope — e.g., 'today', 'this week', 'maginnis only', 'recap', 'lineage'"
|
|
12
15
|
---
|
|
13
16
|
|
|
14
17
|
# /briefing — The Daily Surface
|
|
@@ -21,10 +24,19 @@ the conversation. The success test: the operator runs this daily
|
|
|
21
24
|
because it is pleasant, and the inbox drains through batch decisions
|
|
22
25
|
here instead of item-by-item `/inbox` walks.
|
|
23
26
|
|
|
24
|
-
Tone contract for every section below
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
Tone contract for every section below — **non-negotiable, every run**:
|
|
28
|
+
plain English, conversational, concept-first. No insider jargon, no
|
|
29
|
+
fid/jargon walls. Say "the background system files one note when the
|
|
30
|
+
same mistake keeps happening" — not "Ring 2 emitPatternPromotion
|
|
31
|
+
dedups by failure class." Name the thing in words the operator would
|
|
32
|
+
use, then add the id only as a trailing reference. Item ids and `act:`
|
|
33
|
+
fids appear on request or in disposition confirmations — never as the
|
|
34
|
+
narrative spine. Lead with what matters; counts and mechanics trail.
|
|
35
|
+
This recurred live (2026-06-14): a briefing slipped into "Ring 2
|
|
36
|
+
meta-critiques / generator leak" and the operator could not act on it
|
|
37
|
+
until it was re-said plainly. If you catch yourself writing a term a
|
|
38
|
+
non-author wouldn't recognize, rewrite the sentence. See also the
|
|
39
|
+
decision/context structure rule under Step 3c.
|
|
28
40
|
|
|
29
41
|
## The Anti-Accretion Invariant (structural rule)
|
|
30
42
|
|
|
@@ -57,6 +69,9 @@ rules, not sections:
|
|
|
57
69
|
- If `$ARGUMENTS` contains the word "recap", or the skill was invoked
|
|
58
70
|
as `/recap`: **Factual mode.** Deliver Step 2's summary, write the
|
|
59
71
|
timestamp (Step 5), and stop. No walk, no dispositions, no cabinet.
|
|
72
|
+
- If `$ARGUMENTS` contains "lineage", "why is", or "decision history":
|
|
73
|
+
**Lineage mode.** Render THIS desk's project decision lineage (see
|
|
74
|
+
"Lineage Mode" below), then stop. No walk, no dispositions, no cabinet.
|
|
60
75
|
- Otherwise: **Full mode.** Summary, then the project walk with batch
|
|
61
76
|
dispositions, then the cross-portfolio close.
|
|
62
77
|
|
|
@@ -81,6 +96,87 @@ The time window scopes the NARRATIVE (sessions, threads, what
|
|
|
81
96
|
happened); pending inbox items are always loaded in full — old pending
|
|
82
97
|
items are exactly what batch dispositions exist to drain.
|
|
83
98
|
|
|
99
|
+
## Lineage Mode: Decision-Lineage Drill-Down (act:a2efc0ce)
|
|
100
|
+
|
|
101
|
+
On-demand, read-only. Answers "why is THIS desk's project the way it is —
|
|
102
|
+
what past decisions still constrain it, and what's safely reversible?"
|
|
103
|
+
This is a **projection** over existing stores (the inbox, threads, memory
|
|
104
|
+
`decision_*.md`, `.claude/methodology/`, pib-db), never a new store, and
|
|
105
|
+
it **writes nothing**. It is current-project-scoped in Stage 1: it reads
|
|
106
|
+
the project the current desk's cwd belongs to (worktree-aware). If the
|
|
107
|
+
operator named a *different* project, say plainly that lineage is
|
|
108
|
+
per-desk for now — run it from that project's desk — then either run it
|
|
109
|
+
for the current project or stop. (Cross-project lineage is deferred.)
|
|
110
|
+
|
|
111
|
+
Distinct from `/threads arc <slug>`, which tells **one work thread's**
|
|
112
|
+
evolution. Lineage tells the **whole project's decision causality**.
|
|
113
|
+
|
|
114
|
+
**L1 — corpus (inbox + threads).** Run the read-only helper (it lives
|
|
115
|
+
beside the queue lib, in the project-root `scripts/` dir):
|
|
116
|
+
```bash
|
|
117
|
+
node scripts/watchtower-narrative-corpus.mjs --corpus --project-path "$(pwd)"
|
|
118
|
+
```
|
|
119
|
+
It returns `project_identity`, `inbox_decisions` (knowledge-extraction
|
|
120
|
+
items, captured-to-memory duplicates already dropped, `superseded`
|
|
121
|
+
included), `thread_cursors` (full `cursor_history` timelines),
|
|
122
|
+
`per_store_counts`, and `skipped_unresolved`. If `reason` is
|
|
123
|
+
`project-unresolved`, say the desk isn't a watchtower project and stop.
|
|
124
|
+
|
|
125
|
+
**L2 — memory decisions + recorded edges.** Resolve the project's
|
|
126
|
+
built-in memory dir the way orient does (prefer
|
|
127
|
+
`node -e "console.log(require('./scripts/project-context.cjs').resolveMemoryDir())"`
|
|
128
|
+
when that script exists; else `~/.claude/projects/<dashified-cwd>/memory`),
|
|
129
|
+
then have the SAME helper parse the decision files (the consumer resolves
|
|
130
|
+
the path; the helper owns the edge rule):
|
|
131
|
+
```bash
|
|
132
|
+
node scripts/watchtower-narrative-corpus.mjs --memory "<memory-dir>"
|
|
133
|
+
```
|
|
134
|
+
Each entry carries `supersedes` (RECORDED, directional edges) and
|
|
135
|
+
`see_also` (undirected wikilinks — **never** render a see-also as a
|
|
136
|
+
supersession).
|
|
137
|
+
|
|
138
|
+
**L3 — methodology "why" (richest substrate).** If `.claude/methodology/`
|
|
139
|
+
exists in the cwd, read its `README.md` index and the `-internal.md`
|
|
140
|
+
bodies relevant to the load-bearing decisions — these carry the
|
|
141
|
+
Claim→Evidence→Skeptic→Counter reasoning the other stores summarize away.
|
|
142
|
+
|
|
143
|
+
**L4 — pib-db design rationale.** `pib_list_actions` for the current
|
|
144
|
+
project (resolve the `prj:` fid via `pib_list_projects`; if the name is
|
|
145
|
+
ambiguous, ask — never guess). Action notes carry `absorbs act:…` /
|
|
146
|
+
`Supersedes …` prose — these are **inferred** edges (prose, not a
|
|
147
|
+
structural field), mark them so.
|
|
148
|
+
|
|
149
|
+
**L5 — synthesize, ANSWER-FIRST** (plain English, concept-first; the tone
|
|
150
|
+
contract above applies in full):
|
|
151
|
+
|
|
152
|
+
1. **What still constrains this project right now** — lead with this. The
|
|
153
|
+
decisions/constraints from earlier that later work still depends on;
|
|
154
|
+
for the ones the operator might want to revisit, say whether anything
|
|
155
|
+
still hangs on them (reversible vs load-bearing). This is the answer
|
|
156
|
+
the drill-down exists to give.
|
|
157
|
+
2. **Supersession chains** — what replaced what, with **provenance**:
|
|
158
|
+
*recorded* (a parsed `**Supersedes:**` block or a pib `absorbs act:`
|
|
159
|
+
marker — citable) vs *inferred* (read from prose) — labeled, never
|
|
160
|
+
conflated. A narrative is a trust surface: do not present an inferred
|
|
161
|
+
link as recorded history, and never render a `[[wikilink]]` as a
|
|
162
|
+
supersede.
|
|
163
|
+
3. **The causal timeline** — OPTIONAL deep-read, placed **below** the
|
|
164
|
+
answer. Chapter by causal **pivot / phase transition** (the moments
|
|
165
|
+
direction changed — a constraint discovered, an approach superseded),
|
|
166
|
+
not by raw time gaps. Skip this entirely when the corpus is sparse.
|
|
167
|
+
|
|
168
|
+
**Honesty footer.** Report `per_store_counts` and `skipped_unresolved` in
|
|
169
|
+
plain words when either is notable: "history may be incomplete — N inbox
|
|
170
|
+
items couldn't be attributed to a project and may belong here." Never
|
|
171
|
+
present a silently-truncated history as complete.
|
|
172
|
+
|
|
173
|
+
**Sparse / empty.** If the combined decision count (inbox_kept + memory
|
|
174
|
+
decisions) is under ~3, say "not enough decision history to narrate yet
|
|
175
|
+
(N found)" and stop — a story needs enough points to have an arc.
|
|
176
|
+
|
|
177
|
+
Lineage mode renders inline and stops. It writes nothing — no state file,
|
|
178
|
+
no inbox item, no memory write.
|
|
179
|
+
|
|
84
180
|
## Step 1: Gather Data
|
|
85
181
|
|
|
86
182
|
No Claude API calls — pure filesystem reads plus the queue lib. State
|
|
@@ -116,18 +212,58 @@ and titles. Also collect resolved `qa-handoff` items whose
|
|
|
116
212
|
pib-db (`pib_get_action` or `node scripts/pib-db.mjs get <fid>`) and
|
|
117
213
|
keep only still-open ones — these are the open QA debts for Step 4.
|
|
118
214
|
|
|
119
|
-
### 1d.
|
|
215
|
+
### 1d. Cross-ring portfolio view (state, threads, git attention, resolution history)
|
|
120
216
|
|
|
121
|
-
|
|
122
|
-
|
|
217
|
+
Run the cross-ring reader — ONE gather call that replaces the old
|
|
218
|
+
per-store reads (state files + threads) and adds two signals nothing
|
|
219
|
+
here consulted before: the inbox **resolution history** (with
|
|
220
|
+
`resolution_mix` ratios — what the operator's past decisions actually
|
|
221
|
+
engaged vs discarded, per project) and the structured **git-attention
|
|
222
|
+
facts**:
|
|
123
223
|
|
|
124
|
-
|
|
224
|
+
```bash
|
|
225
|
+
XRING="$(mktemp)"
|
|
226
|
+
node scripts/watchtower-cross-ring-reader.mjs --portfolio > "$XRING"
|
|
227
|
+
# with a project filter active: --project "<name or slug>" instead
|
|
228
|
+
# (config-key name preferred; a unique slug match also resolves)
|
|
229
|
+
```
|
|
125
230
|
|
|
126
|
-
|
|
231
|
+
**Consume by Reading the file, never by echoing it through Bash** — a
|
|
232
|
+
live portfolio view runs to a few hundred KB and Bash tool output
|
|
233
|
+
truncates long before that (a truncated JSON parse is the failure this
|
|
234
|
+
instruction exists to prevent). Read the envelope's top (counts +
|
|
235
|
+
honesty fields) for Step 2, then Read each project's view slice as you
|
|
236
|
+
walk that chunk in Step 3; the JSON is pretty-printed, so each
|
|
237
|
+
project's view is one contiguous block.
|
|
238
|
+
|
|
239
|
+
Per project it returns the parsed Ring 1 state sections (Active Plans,
|
|
240
|
+
Last Session, Standing Issues, Tech Stack), git-attention facts, recent
|
|
241
|
+
session summaries, thread cursor timelines (capped to the newest 3
|
|
242
|
+
snapshots with `history_total` — the full evolution is lineage mode's
|
|
243
|
+
job; a legacy lone-`cursor` file arrives as a single-entry history;
|
|
244
|
+
current cursor = the LAST history entry), pending counts by
|
|
245
|
+
category/urgency, and the resolution history (`resolution_mix` carries
|
|
246
|
+
full counts; the event list is capped with `resolution_events_total`).
|
|
247
|
+
Every cap reports its total — "3 of 85" is signal, not truncation. The
|
|
248
|
+
envelope's honesty fields (`unattributed_items`, `orphan_threads`,
|
|
249
|
+
`orphaned_state_files`) are real signal — surface them in plain words
|
|
250
|
+
in Step 4 when notable. Pending COUNTS here are a narration snapshot;
|
|
251
|
+
1c's live `listPending()` load stays the disposition source of truth.
|
|
252
|
+
|
|
253
|
+
**Fallback (script absent — a consumer that hasn't reinstalled since
|
|
254
|
+
the reader shipped):** read the raw stores directly as 1e describes,
|
|
255
|
+
and proceed without the resolution-history/git-attention signals.
|
|
256
|
+
|
|
257
|
+
### 1e. Active threads (fallback path only)
|
|
258
|
+
|
|
259
|
+
Normally covered by the 1d view. When the 1d fallback is in effect,
|
|
260
|
+
read `state/threads/*.json`; collect `status: "active"` threads. The
|
|
127
261
|
current cursor is `cursor_history[last].cursor` (older files may carry
|
|
128
262
|
a lone `cursor` object — treat it as current). Extract `what`,
|
|
129
263
|
`where_left_off`, `next_steps`, `last_updated`, session count. Sort by
|
|
130
|
-
`last_updated` descending.
|
|
264
|
+
`last_updated` descending. (Also read `state/projects/*.md` — Active
|
|
265
|
+
Plans, Last Session, Standing Issues per project, scope-filtered if a
|
|
266
|
+
project filter is active.)
|
|
131
267
|
|
|
132
268
|
### 1f. Last briefing timestamp
|
|
133
269
|
|
|
@@ -155,6 +291,29 @@ observation is Step 4 close material. Include only members who said
|
|
|
155
291
|
something; silence is fine and is the common case. In recap mode, skip
|
|
156
292
|
the panel entirely — it spawns only on full-mode invocation.
|
|
157
293
|
|
|
294
|
+
### 1h. Unprocessed DX captures (mux's global capture list)
|
|
295
|
+
|
|
296
|
+
Read mux's global DX-capture store — `~/.local/share/mux/dx.json` — the
|
|
297
|
+
single cross-project list where `mux dx "..."` and `/dx-feedback` drop
|
|
298
|
+
developer-experience ideas and friction. A pure filesystem read with no
|
|
299
|
+
ordering dependency on the panel spawn. If the file is absent or
|
|
300
|
+
unparseable (mux not installed, or no captures yet), skip silently — it
|
|
301
|
+
is a mux-owned store and its absence is normal, not an error.
|
|
302
|
+
|
|
303
|
+
An item is **active** (unprocessed) only when BOTH `done` is false AND
|
|
304
|
+
`filed` is false. `done` items were cleared; `filed` items already live
|
|
305
|
+
in pib-db (an action or feedback) — resurfacing either is exactly the
|
|
306
|
+
write-only-telemetry bug this duty exists to kill. Collect each active
|
|
307
|
+
item's `text`, `created_at`, `origin`, and its **global active-list
|
|
308
|
+
position** (1-based index among active items — the position
|
|
309
|
+
`manage-dx.py` addresses when draining). Resolve each item's `origin` to
|
|
310
|
+
a walk project where you can: labels like `"claude-cabinet"` or `"flow"`
|
|
311
|
+
map to a project chunk; labels like `"session-observation"` or
|
|
312
|
+
`"unknown"` do not — those are portfolio-level (Step 4). If there are
|
|
313
|
+
zero active items, skip silently. (This was orient's job; post-orient
|
|
314
|
+
nothing reads these unless the briefing does — see
|
|
315
|
+
`lesson_write_only_telemetry_wire_a_reader`.)
|
|
316
|
+
|
|
158
317
|
## Step 2: Top Brief
|
|
159
318
|
|
|
160
319
|
Ten lines or fewer — the whole portfolio in one glance, curated. Not a
|
|
@@ -183,11 +342,19 @@ gate.").
|
|
|
183
342
|
|
|
184
343
|
## Step 3: The Project Walk
|
|
185
344
|
|
|
186
|
-
One project at a time, in curated order:
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
345
|
+
One project at a time, in curated order: lead with the chunks the
|
|
346
|
+
operator can actually act on from this session — the current desk and
|
|
347
|
+
any project with dispositionable (ungated, this-desk) items — then
|
|
348
|
+
projects with pending gated items, then urgent items, then by thread
|
|
349
|
+
recency and pending count; quiet projects last (and a project with
|
|
350
|
+
nothing to say gets one line or silence — absence of news is news the
|
|
351
|
+
operator doesn't need). A project filter scopes the walk to that
|
|
352
|
+
project. **Why actionable-first:** a cross-desk gated item can only be
|
|
353
|
+
"left queued for its own desk" from here — it is read-only from this
|
|
354
|
+
session, so surfacing it (and a wall of another desk's state) before
|
|
355
|
+
the operator's own decisions just front-loads context they must hold.
|
|
356
|
+
Surface it, but later. A gated item is never dropped (floor #1); it is
|
|
357
|
+
only re-ordered.
|
|
191
358
|
|
|
192
359
|
**Decisions are never interleaved.** Each project's chunk completes —
|
|
193
360
|
narrative, attention items, dispositions executed — before the next
|
|
@@ -204,9 +371,11 @@ Each chunk has three movements:
|
|
|
204
371
|
### 3a. State, in plain English
|
|
205
372
|
|
|
206
373
|
Two to four sentences synthesized from the project's threads, Last
|
|
207
|
-
Session, and standing issues
|
|
208
|
-
|
|
209
|
-
|
|
374
|
+
Session, and standing issues — all already in hand from the Step 1d
|
|
375
|
+
cross-ring view (no second read; its parsed sections, session bullets,
|
|
376
|
+
and cursor timelines are the input). Concept-first — "the publish
|
|
377
|
+
pipeline is built but has never run against a live tag" — not file
|
|
378
|
+
paths and fids. This
|
|
210
379
|
is the operator-facing register (`cabinet/skill-output-conventions.md`
|
|
211
380
|
§9) as the briefing's whole default; keep it that way. Offer nothing
|
|
212
381
|
here; drill-down happens by the operator asking.
|
|
@@ -231,6 +400,14 @@ floor-or-not) — a new duty adds an entry here, never a section:
|
|
|
231
400
|
shows ≥3 stale project(s) OR ≥2 completion candidate(s) (Ring 1 renders
|
|
232
401
|
these counts) · one line max, "backlog showing cruft — consider
|
|
233
402
|
/spring-clean" · decays once the counts fall; never its own section.
|
|
403
|
+
- **Backlog rot** · this project's PENDING inbox is rotting: items older
|
|
404
|
+
than the rot threshold (30d) with ~0 recent dispositions — the
|
|
405
|
+
`not-consumed` verdict from `scripts/watchtower-inbox-assessment.mjs`
|
|
406
|
+
(co-equal with the keep ratio: a great keep ratio on an untouched pile
|
|
407
|
+
is still rot). Weigh high while it holds · one line, "N items sitting
|
|
408
|
+
30+ days unworked — work a batch now" pointing straight at this
|
|
409
|
+
project's 3c decay/sign-off batch · decays the moment the pile is
|
|
410
|
+
worked; never its own section.
|
|
234
411
|
- **Environment advisories** · `suggested` entries in
|
|
235
412
|
`.claude/cabinet/advisories-state.json` (the watchtower context builder's
|
|
236
413
|
advisory pass already wrote them) for this chunk's project · one line
|
|
@@ -238,6 +415,13 @@ floor-or-not) — a new duty adds an entry here, never a section:
|
|
|
238
415
|
just read the surfacing state.
|
|
239
416
|
- **Verify signals** · shipped-uncovered warnings · weigh as they arrive.
|
|
240
417
|
- **State-file flags** · anything in Standing Issues that needs a human.
|
|
418
|
+
- **Unprocessed DX captures** · active items in mux's global `dx.json`
|
|
419
|
+
(1h) whose `origin` resolves to this chunk's project · weigh fresh,
|
|
420
|
+
then decay like any aged item — one line each, with a process/dismiss
|
|
421
|
+
path so the list actually drains (handling below) · not a floor:
|
|
422
|
+
captures are freely drainable and dismissable. Captures whose origin
|
|
423
|
+
resolves to no walk project go to the Step 4 close — never silently
|
|
424
|
+
dropped.
|
|
241
425
|
|
|
242
426
|
Everything else stays in the batch counts below.
|
|
243
427
|
|
|
@@ -254,7 +438,7 @@ Advisor signals come from two sources, both weighed here:
|
|
|
254
438
|
ungated items — legal batch material in 3c.
|
|
255
439
|
- **Live panel observations** (Step 1g) that named this project.
|
|
256
440
|
|
|
257
|
-
|
|
441
|
+
Three categories get specific handling when selected:
|
|
258
442
|
|
|
259
443
|
- **Gated items (`qa-handoff`):** present what merged and what hangs
|
|
260
444
|
on it, then offer exactly two paths — run the recipient gate now in
|
|
@@ -269,10 +453,48 @@ Two categories get specific handling when selected:
|
|
|
269
453
|
`acted-on`. If the moment passed (yesterday's morning briefing),
|
|
270
454
|
propose it for the stale batch below — routine items are dispatched
|
|
271
455
|
but not gated, and the engine supersedes stale ones anyway.
|
|
456
|
+
- **DX captures:** write-only until something drains them. Surface each
|
|
457
|
+
active capture as one plain line (the idea · when · where it came
|
|
458
|
+
from) and offer exactly two paths, one decision at a time — **process**
|
|
459
|
+
it (act on it now, or file it to pib-db as an action or feedback, then
|
|
460
|
+
mark it filed) or **dismiss** it as no-longer-relevant. Both paths
|
|
461
|
+
drain the list through mux's own tooling — single source of truth,
|
|
462
|
+
never hand-edit `dx.json`:
|
|
463
|
+
|
|
464
|
+
```bash
|
|
465
|
+
# dismiss (clear) a capture — n is its position in the active list
|
|
466
|
+
python3 ~/.config/mux/manage-dx.py done <origin> <n>
|
|
467
|
+
# after filing a capture to pib-db, mark it filed (drops it from the panel)
|
|
468
|
+
python3 ~/.config/mux/manage-dx.py mark-filed <origin> <n>
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
`<n>` is the global active-list position, and positions renumber as
|
|
472
|
+
items leave — when draining several, clear from the **highest position
|
|
473
|
+
down** (or re-read positions between marks) so an earlier removal can't
|
|
474
|
+
shift the index out from under you. `<origin>` is context only; the
|
|
475
|
+
number addresses the global active list regardless of origin.
|
|
272
476
|
|
|
273
477
|
### 3c. Batch dispositions
|
|
274
478
|
|
|
275
|
-
|
|
479
|
+
**First, the sign-off batch — the SAVE direction (M4, act:ffae4eec).**
|
|
480
|
+
Before any decay clustering, partition this project's ungated pending
|
|
481
|
+
items with `partitionForBatchSignoff` (the lib owns the predicate). Its
|
|
482
|
+
`signoff` set is the high-confidence pre-drafted knowledge-extraction
|
|
483
|
+
items (non-empty `draft_artifact`, not urgent, not low-confidence) —
|
|
484
|
+
work the rings already did that needs a nod, not a judgment. Offer the
|
|
485
|
+
whole set as ONE sign-off decision ("the background system drafted these
|
|
486
|
+
N memory entries; approving writes them to memory — sign off on all?").
|
|
487
|
+
On approval, write each `draft_artifact` to memory (`/cc-remember` or a
|
|
488
|
+
direct write), THEN one `applyBatch` resolve with
|
|
489
|
+
`resolution_type: 'captured-to-memory'`. This is the throughput valve:
|
|
490
|
+
M1/M2 raise inflow and success = filed × approval-rate (the M5 canary
|
|
491
|
+
tracks it), so a fast sign-off keeps drafts from ageing out
|
|
492
|
+
unadjudicated. Pulled-out items get per-item `/inbox` treatment after
|
|
493
|
+
the walk; everything else falls to the decay flow below — still one
|
|
494
|
+
decision at a time, the sign-off batch presented first.
|
|
495
|
+
|
|
496
|
+
**Then, decay clustering.** Cluster this project's REMAINING pending
|
|
497
|
+
items into **at most three
|
|
276
498
|
proposed batches** by theme — category × age × thread is the usual
|
|
277
499
|
axis. For each batch, propose a disposition in plain English with the
|
|
278
500
|
reasoning visible. Decay lives here: the curator's default proposal
|
|
@@ -283,27 +505,40 @@ A batch proposal must name: what's in it (count + a few example
|
|
|
283
505
|
titles), the proposed disposition, and the typed reason that will land
|
|
284
506
|
on every item.
|
|
285
507
|
|
|
286
|
-
Ask for approval
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
508
|
+
Ask for approval **one decision at a time** — never a stack of
|
|
509
|
+
questions under a wall of context, never a same-turn dialog. Two
|
|
510
|
+
failure modes, both observed live: a same-turn dialog eclipses the
|
|
511
|
+
reasoning above it, so the operator approves logic they cannot see
|
|
512
|
+
(recurred 2026-06-13); and a long narrative followed by several
|
|
513
|
+
questions at the end forces the operator to hold every batch's
|
|
514
|
+
rationale in their head at once, which they cannot (recurred
|
|
515
|
+
2026-06-14). **The decision/context structure rule:** the only thing
|
|
516
|
+
that should require working memory is the single decision in front of
|
|
517
|
+
the operator, with its reason immediately beside it.
|
|
518
|
+
|
|
519
|
+
The shape: present **one batch** — what's in it (count + a few example
|
|
520
|
+
titles), the proposed disposition, the typed reason — then a one-line
|
|
521
|
+
question ("Dismiss these 14 as stale? y / n / show me") and the turn
|
|
522
|
+
STOPS. The operator answers in prose. Apply it, confirm in one line,
|
|
523
|
+
then present the next batch the same way. Pure read-only material —
|
|
524
|
+
portfolio state for desks the operator isn't on, platform notes,
|
|
525
|
+
anything needing no decision — is delivered AFTER all decisions are
|
|
526
|
+
made; it costs nothing to hold, so it never sits above a decision.
|
|
527
|
+
Reserve `AskUserQuestion` only for a self-contained choice whose
|
|
528
|
+
options stand on their own inside the dialog (e.g. a layout pick with
|
|
529
|
+
previews); batch dispositions never qualify.
|
|
297
530
|
|
|
298
531
|
Execute approved batches immediately via the queue lib, then say what
|
|
299
532
|
happened in one line each and move to the next project:
|
|
300
533
|
|
|
301
534
|
```bash
|
|
302
535
|
node --input-type=module -e "
|
|
303
|
-
import { applyBatch } from './scripts/watchtower-queue.mjs';
|
|
536
|
+
import { applyBatch, partitionForBatchSignoff, listPending } from './scripts/watchtower-queue.mjs';
|
|
537
|
+
// Sign-off batch (M4): partitionForBatchSignoff(listPending({project})).signoff
|
|
538
|
+
// → resolve 'captured-to-memory' (write each draft_artifact FIRST). Decay='dismiss'.
|
|
304
539
|
const r = applyBatch([/* ids */], {
|
|
305
|
-
disposition: 'dismiss', // or 'resolve'
|
|
306
|
-
resolution_type: 'stale', // typed reason — required
|
|
540
|
+
disposition: 'dismiss', // or 'resolve' (the sign-off batch)
|
|
541
|
+
resolution_type: 'stale', // typed reason — required ('captured-to-memory' for sign-off)
|
|
307
542
|
notes: '<the reason shown to the operator, verbatim>',
|
|
308
543
|
});
|
|
309
544
|
console.log(JSON.stringify(r));
|
|
@@ -325,10 +560,15 @@ include a part only when it has signal.
|
|
|
325
560
|
|
|
326
561
|
- **Cross-cutting synthesis** — patterns spanning projects (the same
|
|
327
562
|
friction filed from two desks, a theme across threads, a decision
|
|
328
|
-
made in one project that answers a question open in another).
|
|
329
|
-
is
|
|
330
|
-
|
|
331
|
-
|
|
563
|
+
made in one project that answers a question open in another). The
|
|
564
|
+
substrate is the Step 1d cross-ring portfolio view — synthesize from
|
|
565
|
+
its per-project views (git-attention facts across projects,
|
|
566
|
+
`resolution_mix` ratios, thread/session convergence) instead of
|
|
567
|
+
re-deriving from raw stores. Its honesty fields belong here too, in
|
|
568
|
+
plain words when notable: "N inbox items couldn't be attributed to
|
|
569
|
+
any project", "one active thread matches no configured project".
|
|
570
|
+
The synthesis itself stays live — the reader gathers, this session
|
|
571
|
+
thinks.
|
|
332
572
|
- **Standing debts** — floor #2: while any QA filed-gaps remain open,
|
|
333
573
|
one roll-up line each ("X still owes the migration test filed by
|
|
334
574
|
last week's QA — act:fid"). Same treatment for unmerged-worktree
|
|
@@ -338,6 +578,11 @@ include a part only when it has signal.
|
|
|
338
578
|
historian precedent that answers an open question, a platform delta
|
|
339
579
|
from the insider, a legibility flag from the user-advocate). One line
|
|
340
580
|
each, only members who said something — never a roll call.
|
|
581
|
+
- **Unprocessed DX captures, portfolio-level** — active `dx.json`
|
|
582
|
+
captures (1h) whose `origin` resolved to no walk project land here,
|
|
583
|
+
one line each, with the same process/dismiss drain path as the
|
|
584
|
+
per-project handling (3b). Only when some exist; never a standing
|
|
585
|
+
section.
|
|
341
586
|
|
|
342
587
|
Close with one sentence: dispositions applied this run (N resolved, M
|
|
343
588
|
dismissed, across K projects), what remains pending, and — only if
|
|
@@ -367,6 +612,9 @@ After the briefing completes (any mode), atomically write
|
|
|
367
612
|
the watchtower module): deliver the read-only briefing from global
|
|
368
613
|
state and say dispositions need a watchtower-installed project.
|
|
369
614
|
- Corrupt/unparseable item files: skip with a one-line warning count.
|
|
615
|
+
- No mux DX store (`~/.local/share/mux/dx.json` missing, or mux not
|
|
616
|
+
installed): skip the DX-capture candidate silently — a mux-owned
|
|
617
|
+
store's absence is normal, not an error.
|
|
370
618
|
- An `applyBatch` throw is a stop-and-show, not a retry loop: name the
|
|
371
619
|
item that tripped the gate, pull it into per-item handling, re-offer
|
|
372
620
|
the rest as a new batch.
|
|
@@ -11,7 +11,7 @@ briefing:
|
|
|
11
11
|
- .claude/cabinet/_briefing-jurisdictions.md
|
|
12
12
|
standing-mandate: audit
|
|
13
13
|
files:
|
|
14
|
-
# Adjust to your component paths. See .claude/cabinet/_briefing.md §
|
|
14
|
+
# Adjust to your component paths. See .claude/cabinet/_briefing-jurisdictions.md § App Source
|
|
15
15
|
- src/**/*.tsx
|
|
16
16
|
- src/components/**/*.tsx
|
|
17
17
|
topics:
|
|
@@ -125,3 +125,31 @@ universal patterns below. Absent is normal — it is seeded by debrief
|
|
|
125
125
|
when recurring findings accumulate.
|
|
126
126
|
|
|
127
127
|
<!-- Universal patterns below this line -->
|
|
128
|
+
|
|
129
|
+
### Don't redo work that's already done or already specified
|
|
130
|
+
|
|
131
|
+
Recurring inefficiency: discovery is run for things already in hand, and
|
|
132
|
+
complete plans are rebuilt instead of executed.
|
|
133
|
+
|
|
134
|
+
- **Use what you already know directly.** Don't run discovery
|
|
135
|
+
(ToolSearch, phase-file hunts, grep archaeology) for a tool name,
|
|
136
|
+
path, or spec you already have. A targeted lookup or direct attempt
|
|
137
|
+
beats a discovery loop; reserve discovery for the genuinely unknown.
|
|
138
|
+
- **Don't re-encode a complete plan.** If the prompt is already ordered
|
|
139
|
+
and explicit, execute it rather than rebuilding it as tasks that
|
|
140
|
+
mirror it. A task layer earns its cost only when it adds structure the
|
|
141
|
+
prompt lacks: progress-tracking through a long single-session run, or
|
|
142
|
+
a durable record when the work will span sessions. Match the vehicle
|
|
143
|
+
to the lifespan — an in-session task list for progress (it is lost on
|
|
144
|
+
interruption), a `.claude/plans/` doc or pib-db action for anything
|
|
145
|
+
that must outlive the session.
|
|
146
|
+
- **Bound your research.** Stop at minimum-viable understanding, not
|
|
147
|
+
maximal confidence. If you are hunting for something the user believes
|
|
148
|
+
exists, ask where it lives before a long search.
|
|
149
|
+
- **Reconcile on resume.** A continuation prompt is a claim about the
|
|
150
|
+
past; check current state (query the named action FIDs) before acting
|
|
151
|
+
on it.
|
|
152
|
+
- **Spawn with a sync point.** Load context before launching parallel
|
|
153
|
+
sub-agents, and define where you will collect and surface their
|
|
154
|
+
output. No fire-and-forget black boxes — no completion check, no
|
|
155
|
+
output handling.
|
|
@@ -108,3 +108,14 @@ universal patterns below. Absent is normal — it is seeded by debrief
|
|
|
108
108
|
when recurring findings accumulate.
|
|
109
109
|
|
|
110
110
|
<!-- Universal patterns below this line -->
|
|
111
|
+
|
|
112
|
+
### Secrets pasted into the conversation need an active response
|
|
113
|
+
|
|
114
|
+
When a secret lands in the chat — a PAT, API key, password, connection
|
|
115
|
+
string the user pastes to unblock something — do not just consume it
|
|
116
|
+
silently. Two reflexes: (1) advise against pasting secrets in plain text
|
|
117
|
+
and point at the safer path (env var, secret store, the OS secure dialog
|
|
118
|
+
the engagement flow uses); (2) when you must echo or reference it,
|
|
119
|
+
redact/truncate it (`ghp_…abcd`) rather than reprinting it in full.
|
|
120
|
+
Silently using a plaintext secret normalizes leaking it into transcripts
|
|
121
|
+
and logs.
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: catch-up
|
|
3
|
+
description: |
|
|
4
|
+
Mid-session awareness refresh. Watchtower injects state once, at session
|
|
5
|
+
start; a long session then drifts from that snapshot as other sessions
|
|
6
|
+
advance threads, the background rings file inbox items and detect new git
|
|
7
|
+
state, and deferred tasks come due. /catch-up shows what CHANGED since this
|
|
8
|
+
session started — a short, plain-English delta, not a re-dump of everything.
|
|
9
|
+
Read-only. Use when: "catch-up", "/catch-up", "what changed", "what's new
|
|
10
|
+
since I started", "what did I miss", "refresh my context", "poll watchtower",
|
|
11
|
+
"re-orient".
|
|
12
|
+
argument-hint: "(none)"
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# /catch-up — What Changed Since This Session Started
|
|
16
|
+
|
|
17
|
+
Watchtower runs continuously in the background, but it injects its state into
|
|
18
|
+
a session exactly **once**, at session start. Over a long session that
|
|
19
|
+
snapshot goes stale: other desks advance shared work threads, Ring 2 enriches
|
|
20
|
+
and files inbox items, Ring 1 detects new git state, deferred actions come due.
|
|
21
|
+
This skill closes that gap — it compares the current watchtower state against
|
|
22
|
+
the **baseline captured when this session started** and tells you, in plain
|
|
23
|
+
language, only what's new.
|
|
24
|
+
|
|
25
|
+
This skill is **read-only**. It reads state and renders a delta. It never
|
|
26
|
+
triages, resolves, or writes anything except (when no baseline exists yet) a
|
|
27
|
+
fresh baseline for next time.
|
|
28
|
+
|
|
29
|
+
It is the manual, on-demand half of mid-session awareness. The automatic
|
|
30
|
+
"notify me when something significant changes" version is a deliberate later
|
|
31
|
+
enhancement (see the plan's Option B) — not this skill.
|
|
32
|
+
|
|
33
|
+
## How the baseline works
|
|
34
|
+
|
|
35
|
+
At session start, the watchtower SessionStart hook captures a structured
|
|
36
|
+
snapshot of watchtower state, keyed by this session's id, at
|
|
37
|
+
`~/.claude-cabinet/watchtower/state/session-snapshots/<session-id>.json`.
|
|
38
|
+
`/catch-up` re-reads current state and diffs it against that baseline. All the
|
|
39
|
+
snapshot/diff/render logic lives in one place —
|
|
40
|
+
`~/.claude-cabinet/watchtower/scripts/watchtower-snapshot.mjs` — which this
|
|
41
|
+
skill just drives; it does not re-implement any of it.
|
|
42
|
+
|
|
43
|
+
## Step 1 — Locate the runtime and this session's baseline
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
WT="${HOME}/.claude-cabinet/watchtower"
|
|
47
|
+
SNAP="${WT}/scripts/watchtower-snapshot.mjs"
|
|
48
|
+
SID="${CLAUDE_CODE_SESSION_ID:-}"
|
|
49
|
+
BASE="${WT}/state/session-snapshots/${SID}.json"
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Resolve three facts:
|
|
53
|
+
|
|
54
|
+
- **Watchtower installed?** If `${SNAP}` does not exist, say plainly that
|
|
55
|
+
watchtower isn't installed (or this project isn't using it), so there's
|
|
56
|
+
nothing to catch up on, and stop.
|
|
57
|
+
- **Session id known?** `CLAUDE_CODE_SESSION_ID` is the session's id (a UUID;
|
|
58
|
+
it matches the session transcript name and the id the SessionStart hook keys
|
|
59
|
+
the baseline under). If it is empty, there is no per-session baseline to diff
|
|
60
|
+
against — say so plainly and stop (do **not** read or write a keyless/shared
|
|
61
|
+
baseline file; a shared "unknown" baseline would show you another session's
|
|
62
|
+
changes as if they were yours).
|
|
63
|
+
- **Baseline present?** Whether `${BASE}` exists decides Step 2's branch.
|
|
64
|
+
|
|
65
|
+
## Step 2 — Diff, or self-seed if there's no baseline yet
|
|
66
|
+
|
|
67
|
+
**If `${BASE}` exists** — run the diff and relay it:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
node "${SNAP}" --diff "${BASE}" --project-path "$(pwd)"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The module prints the delta already in plain, concept-first English (deferred
|
|
74
|
+
tasks that came due, new inbox items, threads that advanced or appeared, new or
|
|
75
|
+
cleared git attention) — or a single "Nothing new since this session started"
|
|
76
|
+
line. **Relay that output directly.** Don't reformat it into field dumps or
|
|
77
|
+
re-expand it into the full state; the whole point is the delta. You may add one
|
|
78
|
+
short framing sentence, but the rendered delta is the answer.
|
|
79
|
+
|
|
80
|
+
Phrase anything you add as *project-level* change ("since your session started,
|
|
81
|
+
the project picked up…"), never as something you personally did — in a worktree,
|
|
82
|
+
a concurrent session's work legitimately shows up in this delta.
|
|
83
|
+
|
|
84
|
+
**If `${BASE}` does NOT exist** — this session predates the feature, or the
|
|
85
|
+
SessionStart hook didn't capture a baseline. Self-seed one now so the *next*
|
|
86
|
+
`/catch-up` works, and say so honestly:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
node "${SNAP}" --emit-snapshot "${BASE}" --project-path "$(pwd)" --session-id "${SID}"
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Then tell the user, plainly: there was no start-of-session baseline to compare
|
|
93
|
+
against, so you've captured one as of now — run `/catch-up` again later to see
|
|
94
|
+
what's changed since this point. Do not invent a delta you can't compute.
|
|
95
|
+
|
|
96
|
+
## Step 3 — Keep it short
|
|
97
|
+
|
|
98
|
+
The value here is the delta, surfaced fast. Lead with the headline ("2 new
|
|
99
|
+
inbox items, one thread advanced, a deferred task came due"), let the rendered
|
|
100
|
+
detail follow, and stop. If a new item or freshly-due task clearly wants
|
|
101
|
+
action, you may name the one next step — but routing and triage belong to
|
|
102
|
+
`/inbox` and `/briefing`; this skill just makes you current.
|
|
103
|
+
|
|
104
|
+
## Calibration
|
|
105
|
+
|
|
106
|
+
**Without this skill:** the only way to re-orient mid-session is to restart, so
|
|
107
|
+
a session works for an hour against a start-of-session snapshot while threads
|
|
108
|
+
move, items get filed, and deferrals fire — all invisible until the next
|
|
109
|
+
session.
|
|
110
|
+
|
|
111
|
+
**With this skill:** one command answers "what did I miss while I was heads
|
|
112
|
+
down?" against a real baseline — the single upgrade that makes watchtower feel
|
|
113
|
+
alive mid-session rather than boundary-only.
|