@caddis/cli 0.2.5 → 0.2.6
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/bundles/antigravity-plugin/plugin.json +1 -1
- package/bundles/antigravity-plugin/skills/_registry.md +1 -0
- package/bundles/antigravity-plugin/skills/advisory-hub/reference/succession.md +22 -0
- package/bundles/antigravity-plugin/skills/spawn-hub/SKILL.md +33 -0
- package/bundles/antigravity-plugin/skills/spawn-session/SKILL.md +213 -0
- package/bundles/manifest.json +2 -2
- package/dist/cli.js +10 -2
- package/package.json +1 -1
|
@@ -85,6 +85,7 @@
|
|
|
85
85
|
| Ship Merge | `ship-merge/` | Merge an already-green, already-reviewed PR behind an explicit deploy-confirm, monitor the deploy, validate prod, then clean up the branch — only on green. |
|
|
86
86
|
| Ship Pr | `ship-pr/` | Open a reviewed PR for the current feature branch — rebase-safe push, PR create/update, monitor CI, STOP at green. Never merges, never deploys (that's /ship-merge). |
|
|
87
87
|
| Spawn Hub | `spawn-hub/` | Hand the Advisory Hub role to a fresh session — run the mechanical audit, then generate the succession prompt with a context self-check the new Hub must pass |
|
|
88
|
+
| Spawn Session | `spawn-session/` | Hand the WORK to a fresh session — generate the handover from the repo, then validate the successor by re-deriving its answers |
|
|
88
89
|
| Tdd | `tdd/` | Run a strict red-green-refactor TDD cycle for a unit of behavior |
|
|
89
90
|
| Ui Brief | `ui-brief/` | Design-first UI brief — lock the aesthetic before writing any code |
|
|
90
91
|
| Usage Review | `usage-review/` | Review local caddis usage over a window, surface prioritised recommendations, and apply config changes in one step |
|
|
@@ -92,5 +92,27 @@ the funnel's `offered` count, and why is it NOT `SUM(OfferedInd)`?"* — the nai
|
|
|
92
92
|
the correct one 4,783, because the raw flags do not nest. A Hub that only skimmed **fails visibly
|
|
93
93
|
instead of silently**, which is the entire point.
|
|
94
94
|
|
|
95
|
+
### Four rules that make the self-check mean something
|
|
96
|
+
|
|
97
|
+
Shared with `/caddis:spawn-session`, which transfers the WORK where this transfers the ROLE. Both
|
|
98
|
+
run on `scripts/caddis_spawn.py`, so a fix lands in both.
|
|
99
|
+
|
|
100
|
+
1. **DERIVE the questions from what CHANGED. Do not choose them.** An agent picking its own exam
|
|
101
|
+
picks what it remembers, which is the thing under test. Spread them: oldest settled decisions
|
|
102
|
+
catch a successor that read only the recent sections; the newest changes catch one that read only
|
|
103
|
+
the summary.
|
|
104
|
+
2. **A SUPERSEDED fact is the highest-signal question there is**, because the obvious answer is the
|
|
105
|
+
stale one. The measured discriminator was *"which model serves chat?"* — the answer had changed
|
|
106
|
+
**twice**, and naming only the most recent replacement proved the history had not been read.
|
|
107
|
+
3. **Every question must be answerable from a committed file**, verified with
|
|
108
|
+
`caddis_spawn.py verify-question`, not assumed. A question whose answer is not written down tests
|
|
109
|
+
memory — the thing this mechanism replaces.
|
|
110
|
+
4. **Store NO answer key. Re-derive at validation time.** A stored key freezes the outgoing agent's
|
|
111
|
+
belief: if it was wrong, the key is wrong and the check certifies the error. Re-deriving validates
|
|
112
|
+
the DOCUMENT as well as the reader — and validating only the reader is precisely what failed, when
|
|
113
|
+
a Hub passed a thirteen-question check on a handover containing four factual errors.
|
|
114
|
+
|
|
115
|
+
**Six questions maximum.** Past six the successor writes an essay and the outgoing agent skims it.
|
|
116
|
+
|
|
95
117
|
---
|
|
96
118
|
|
|
@@ -151,8 +151,12 @@ audit trail this pattern has.
|
|
|
151
151
|
generator:**
|
|
152
152
|
|
|
153
153
|
```
|
|
154
|
+
python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_spawn.py" preflight
|
|
154
155
|
python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_inventory.py" --with-tests
|
|
155
156
|
```
|
|
157
|
+
|
|
158
|
+
`preflight` **refuses on a dirty tree**: the incoming Hub pulls, so uncommitted work is invisible to
|
|
159
|
+
it. Commit first, or name every uncommitted file in the handover.
|
|
156
160
|
(falls back to `scripts/caddis_inventory.py` in a source checkout; skip the step if absent — it
|
|
157
161
|
degrades open like every other machine step here.)
|
|
158
162
|
|
|
@@ -191,6 +195,28 @@ Then write the judgement half yourself. It must contain:
|
|
|
191
195
|
> pass while understanding nothing. Rotate it, and prefer a fact the *most recent* milestone
|
|
192
196
|
> established, since that is what the incoming Hub is least likely to have absorbed.
|
|
193
197
|
|
|
198
|
+
> **DERIVE the questions from what CHANGED — do not choose them.** An agent that picks its own
|
|
199
|
+
> exam picks what it remembers, which is the thing under test. Spread them: the oldest settled
|
|
200
|
+
> decisions catch a Hub that read only the recent sections; the most recent changes catch one
|
|
201
|
+
> that read only the summary; **a SUPERSEDED fact is the highest-signal question of all**,
|
|
202
|
+
> because the obvious answer is the stale one.
|
|
203
|
+
|
|
204
|
+
> **Every question must be answerable from a committed file. Prove it, do not assume it:**
|
|
205
|
+
>
|
|
206
|
+
> ```
|
|
207
|
+
> python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_spawn.py" verify-question \
|
|
208
|
+
> --answer-in .caddis/kb/some-note.md --needle "the phrase that answers it"
|
|
209
|
+
> ```
|
|
210
|
+
>
|
|
211
|
+
> A question whose answer is not written down tests memory — the thing this mechanism exists to
|
|
212
|
+
> replace. It is not a harder question; it is the old failure wearing an exam's clothes.
|
|
213
|
+
|
|
214
|
+
> **Store NO answer key.** Re-derive each answer from the repo when the incoming Hub replies. A
|
|
215
|
+
> stored key freezes your belief at capture time: if you were wrong, the key is wrong and the
|
|
216
|
+
> check certifies the error. Re-deriving validates the DOCUMENT as well as the reader — which is
|
|
217
|
+
> exactly what `.caddis/parking-lot/done/004-*` found missing, where a Hub passed a
|
|
218
|
+
> thirteen-question check on a handover carrying four factual errors.
|
|
219
|
+
|
|
194
220
|
Good traps share a shape: a figure that looks obvious, a correct value that differs, and a reason
|
|
195
221
|
rooted in the data rather than in the code. On the reference project, one generation asked why the
|
|
196
222
|
funnel's `offered` is not `SUM(OfferedInd)` (naive 3,814, correct 4,783 — the raw flags do not
|
|
@@ -250,8 +276,15 @@ exists to shed.
|
|
|
250
276
|
```
|
|
251
277
|
python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_gate.py" handover-check \
|
|
252
278
|
--doc .caddis/advisory-hub-reports/hub-NN.spawn.md
|
|
279
|
+
python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_spawn.py" check \
|
|
280
|
+
--doc .caddis/advisory-hub-reports/hub-NN.spawn.md
|
|
253
281
|
```
|
|
254
282
|
|
|
283
|
+
The second one blocks on a **commit hash or test count given as current state**. Both go stale
|
|
284
|
+
within the hour — measured twice — and the fix is never a fresher number, it is to write the command
|
|
285
|
+
that produces it. A historical hash is only noted, not blocked: those are durable, and flagging them
|
|
286
|
+
is how a check earns a reputation for crying wolf.
|
|
287
|
+
|
|
255
288
|
It fails when the prompt names a file that does not exist. **Validate the DOCUMENT, not just the
|
|
256
289
|
reader.** The context self-check in Step 4 proves the incoming Hub read carefully; it proves nothing
|
|
257
290
|
about whether what it read was true. One incoming Hub passed a thirteen-question check on a handover
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spawn-session
|
|
3
|
+
description: Hand the WORK to a fresh session — generate the handover from the repo, then validate the successor by re-deriving its answers
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /caddis:spawn-session — generate the handover, then validate the successor
|
|
7
|
+
|
|
8
|
+
Use this when a session is long enough that its own recall has become the risk. It replaces
|
|
9
|
+
`/caddis:handoff` for that case: `/handoff` writes down what you remember, and **what you remember
|
|
10
|
+
is the failure mode.**
|
|
11
|
+
|
|
12
|
+
**Sibling, not duplicate, of `/caddis:spawn-hub`.** `spawn-hub` hands over a validation ROLE;
|
|
13
|
+
this hands over the WORK. Both run on `scripts/caddis_spawn.py`, so a fix to the machinery lands in
|
|
14
|
+
both.
|
|
15
|
+
|
|
16
|
+
## The failure this exists to catch
|
|
17
|
+
|
|
18
|
+
A long session does not forget. **It recalls superseded facts fluently.** Measured in one session:
|
|
19
|
+
|
|
20
|
+
- two throughput figures the agent had **itself withdrawn**, re-quoted days later
|
|
21
|
+
- *"E8 is blocked on F1"* repeated for three days without a re-test
|
|
22
|
+
- a commit hash written into a handover that went stale **within the hour**
|
|
23
|
+
|
|
24
|
+
Each was stated with conviction and was wrong. Asking that agent what it knows cannot find any of
|
|
25
|
+
it.
|
|
26
|
+
|
|
27
|
+
The successor is what to pick up first: **$ARGUMENTS** (if empty, derive it from the parking-lot
|
|
28
|
+
and the active plan).
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Round 0 — validate your OWN handover. No relay trip.
|
|
33
|
+
|
|
34
|
+
**Do this before writing the prompt.** It is the cheapest round and the one this whole command is
|
|
35
|
+
about: in the manual run, a child caught a stale hash the parent could have caught alone — a wasted
|
|
36
|
+
relay trip, and the relay trip is the expensive part.
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_spawn.py" preflight
|
|
40
|
+
python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_spawn.py" fingerprint --with-tests
|
|
41
|
+
```
|
|
42
|
+
(falls back to `scripts/caddis_spawn.py` in a source checkout.)
|
|
43
|
+
|
|
44
|
+
`preflight` **refuses on a dirty tree** — the successor pulls, so uncommitted work is invisible to
|
|
45
|
+
it and it will either redo that work or build on a state that does not exist. Commit first.
|
|
46
|
+
|
|
47
|
+
### Capture from the repo, never from recall
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_inventory.py" --with-tests
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Then add the four things the inventory cannot derive:
|
|
54
|
+
|
|
55
|
+
| Capture | Why |
|
|
56
|
+
|---|---|
|
|
57
|
+
| **Open parking-lot count** | The integrity check. A successor that revives 13 of 15 has silently dropped two, and nothing else would show it. |
|
|
58
|
+
| **WITHDRAWN and SUPERSEDED facts, as an explicit list** | Highest-value content, easiest to lose. Two withdrawn figures were re-quoted by their own author. |
|
|
59
|
+
| **Anything learned this session that lives in no file** | A screenshot of the consuming UI changed a task's priority. It existed only in the chat. |
|
|
60
|
+
| **State verified, not asserted** — run the tests, the gate, `git status` | One handover said "1,066 tests"; it was 1,090 an hour later. |
|
|
61
|
+
|
|
62
|
+
**Nothing may be written from recall.** Every number comes from a command run during this capture,
|
|
63
|
+
or from a file quoted by path.
|
|
64
|
+
|
|
65
|
+
### Then check what you wrote
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_spawn.py" check --doc .caddis/spawn-session/<id>-prompt.md
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
It **blocks** on a commit hash or test count given as current state, and on any path that does not
|
|
72
|
+
exist. It only **notes** a historical hash — those are durable, and flagging them was how the first
|
|
73
|
+
version produced seven findings on one document and taught the reader to skim.
|
|
74
|
+
|
|
75
|
+
**A claim that cannot be re-derived does not go in the handover.**
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Round 1 — the questions. One relay trip.
|
|
80
|
+
|
|
81
|
+
**Up to six. Derived from what changed, never chosen.** An agent that picks its own exam picks what
|
|
82
|
+
it remembers, which is the thing under test.
|
|
83
|
+
|
|
84
|
+
| Slot | Source | Catches |
|
|
85
|
+
|---|---|---|
|
|
86
|
+
| 1–2 | the **oldest** settled decisions | a successor that read only the recent sections |
|
|
87
|
+
| 3–4 | what changed **most recently** | one that read only the summary |
|
|
88
|
+
| 5 | a fact that was **SUPERSEDED** | the highest-signal question — the obvious answer is the stale one |
|
|
89
|
+
| 6 | a live **hazard or cost** | forces a consequence, not a fact |
|
|
90
|
+
|
|
91
|
+
**At least one question's obvious answer must be WRONG.** In the manual run the discriminator was
|
|
92
|
+
*"which model serves chat?"* — the answer had changed **twice**, and a successor naming only the
|
|
93
|
+
most recent replacement had not read the history.
|
|
94
|
+
|
|
95
|
+
**Every question must be answerable from a committed file. Prove it:**
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
python "${CLAUDE_PLUGIN_ROOT}/scripts/caddis_spawn.py" verify-question \
|
|
99
|
+
--answer-in .caddis/kb/some-note.md --needle "the phrase that answers it"
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
A question whose answer is not written down tests memory — the thing being replaced. It is not a
|
|
103
|
+
harder question; it is the old failure wearing an exam's clothes.
|
|
104
|
+
|
|
105
|
+
### Store NO answer key
|
|
106
|
+
|
|
107
|
+
Do not write `<id>-key.md`. Two reasons, and the second is the one that matters:
|
|
108
|
+
|
|
109
|
+
1. The child can read it. Any exclusion rule is one path-glob away from failing.
|
|
110
|
+
2. **A stored key freezes your belief at capture time.** If you were wrong, the key is wrong, and
|
|
111
|
+
the check certifies the error.
|
|
112
|
+
|
|
113
|
+
**Re-derive each answer from the repo at validation time instead.** That validates the DOCUMENT and
|
|
114
|
+
the READER at once — which is exactly what `.caddis/parking-lot/done/004-*` said was missing, where
|
|
115
|
+
a successor passed a thirteen-question check on a handover containing four factual errors.
|
|
116
|
+
|
|
117
|
+
### What the child sends back
|
|
118
|
+
|
|
119
|
+
Three lines, carried by the user:
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
SPAWN <id> | head <sha> | <n> tests | answers in .caddis/spawn-session/<id>-answers.md
|
|
123
|
+
Q1-Q6 answered with citations. <n> commands run. <n> facts I could not find in a file.
|
|
124
|
+
<one line: the single most important thing I believe about the current state>
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
The fingerprint lets you detect a stale or mismatched paste **before grading anything**.
|
|
128
|
+
|
|
129
|
+
**The third line is the real test.** A successor that understood the work states the current state
|
|
130
|
+
in one sentence. One that merely parsed the files produces a generic line, and that is visible
|
|
131
|
+
immediately.
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## The verdict — three, not two
|
|
136
|
+
|
|
137
|
+
| Verdict | Condition | You write |
|
|
138
|
+
|---|---|---|
|
|
139
|
+
| **PASS** | every answer correct, citations check out | a short go-ahead naming the first task |
|
|
140
|
+
| **ACCEPT WITH CORRECTIONS** | broadly right; one or two facts stale or a citation wrong | the corrections, each with the file that proves it |
|
|
141
|
+
| **REJECT** | a settled decision misremembered, a withdrawn figure quoted, or a hazard misunderstood | an instruction to re-read named sections and re-answer. **Do not let it start work** |
|
|
142
|
+
|
|
143
|
+
**REJECT exists because a confidently wrong successor is more dangerous than a confused one.** In
|
|
144
|
+
this project the failure has never been *"I don't know"* — it has been a fluent wrong answer.
|
|
145
|
+
|
|
146
|
+
The vocabulary matches `/caddis:validate-phase` on purpose: same discipline, different object.
|
|
147
|
+
|
|
148
|
+
**Two REJECTs on one spawn means the HANDOVER is at fault, not the successor. Regenerate it** rather
|
|
149
|
+
than coaching the child through it.
|
|
150
|
+
|
|
151
|
+
### When the fault is yours, fix the class
|
|
152
|
+
|
|
153
|
+
If validation finds an error that came from your handover, **fix the source document in the same
|
|
154
|
+
turn** — and fix the class, not the instance. In the manual run a successor found a stale commit
|
|
155
|
+
hash; the fix was not a fresher hash, it was to **remove hashes from both documents** and write the
|
|
156
|
+
command instead. A handover patched per-instance goes stale again on the next commit.
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Round 2 — the first task, scoped small, reviewed. One relay trip.
|
|
161
|
+
|
|
162
|
+
**Not more questions.** Two rounds of questions would be overkill; two rounds of the right things
|
|
163
|
+
are not.
|
|
164
|
+
|
|
165
|
+
**The questions validate RECALL. The first task validates JUDGEMENT** — and a successor can answer
|
|
166
|
+
six questions perfectly and still build the wrong thing. In the manual run round 2 caught a wrong
|
|
167
|
+
instruction from the parent, a wrong fact left by a predecessor, and a better design than the parent
|
|
168
|
+
had specified.
|
|
169
|
+
|
|
170
|
+
Round 1's verdict sets round 2's size:
|
|
171
|
+
|
|
172
|
+
| Round 1 | Round 2 task |
|
|
173
|
+
|---|---|
|
|
174
|
+
| PASS | a normal next item; review the outcome |
|
|
175
|
+
| ACCEPT WITH CORRECTIONS | a **small, reversible** item that writes nothing permanent; review closely |
|
|
176
|
+
| REJECT | no task — re-read and re-answer |
|
|
177
|
+
|
|
178
|
+
Review the result **by re-deriving it**, exactly as you reviewed the answers — not by reading the
|
|
179
|
+
successor's account of it.
|
|
180
|
+
|
|
181
|
+
### Then stop gating
|
|
182
|
+
|
|
183
|
+
**After round 2 passes, stop.** A successor that answered six questions with citations and then did
|
|
184
|
+
one real task correctly has demonstrated as much as a gate can. Continuing to review every item
|
|
185
|
+
turns you into a bottleneck and the successor into a relay — which is the cost this command exists
|
|
186
|
+
to remove.
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## Files — all three committed
|
|
191
|
+
|
|
192
|
+
```
|
|
193
|
+
.caddis/spawn-session/
|
|
194
|
+
<id>-prompt.md generated by you. The user pastes its "For the successor" section
|
|
195
|
+
<id>-answers.md written by the CHILD
|
|
196
|
+
<id>-verdict.md written by you, after re-deriving
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
`<id>` is short, unique and sortable — `2026-08-16-a`. Two spawns on one day must not collide.
|
|
200
|
+
|
|
201
|
+
They are committed for the same reason the register is a file: **a validation that happened only in
|
|
202
|
+
chat cannot be reviewed**, and cannot be re-read when the next handover asks what good looked like.
|
|
203
|
+
|
|
204
|
+
## Refuse to
|
|
205
|
+
|
|
206
|
+
| Refusal | Why |
|
|
207
|
+
|---|---|
|
|
208
|
+
| Run with a dirty tree | uncommitted work is invisible to the successor |
|
|
209
|
+
| Write a commit hash or test count as current state | both went stale within the hour, twice |
|
|
210
|
+
| Write a question whose answer is not in a committed file | it would test memory |
|
|
211
|
+
| Store an answer key | it freezes your belief, and the child can read it |
|
|
212
|
+
| Grade your own answers | you validate; the child answers |
|
|
213
|
+
| Proceed when the open-item count is unknown | that count is the integrity check |
|
package/bundles/manifest.json
CHANGED
package/dist/cli.js
CHANGED
|
@@ -4765,7 +4765,7 @@ function renderEnvironment(report, problems) {
|
|
|
4765
4765
|
item("info", `platform ${process2.platform} ${process2.arch} (${os3.release()})`);
|
|
4766
4766
|
if (report.cliUpdate) {
|
|
4767
4767
|
item("warn", `@caddis/cli ${report.cliVersion} ${color.dim("\u2192")} ${color.bold(report.cliUpdate.latest)} available`);
|
|
4768
|
-
detail("
|
|
4768
|
+
detail('so EVERY "current" below may be wrong \u2014 it only means "matches the pool this install carries"');
|
|
4769
4769
|
problems.push({
|
|
4770
4770
|
kind: "problem",
|
|
4771
4771
|
text: `@caddis/cli itself is behind: ${report.cliUpdate.current} installed, ${report.cliUpdate.latest} published`,
|
|
@@ -5020,7 +5020,15 @@ async function status3(options) {
|
|
|
5020
5020
|
}
|
|
5021
5021
|
line("");
|
|
5022
5022
|
line(
|
|
5023
|
-
|
|
5023
|
+
// The pool is named as the YARDSTICK, in the header, because that is what every verdict below
|
|
5024
|
+
// is measured against and status cannot see the marketplace — it is deliberately network-free.
|
|
5025
|
+
// A tool that cannot know something must not print a verdict that implies it does.
|
|
5026
|
+
//
|
|
5027
|
+
// Deliberately NOT a footer line. The first attempt added one, and it broke the existing
|
|
5028
|
+
// "stays quiet when everything is current" test — correctly: a qualifier phrased like a warning
|
|
5029
|
+
// fires on every healthy run, and a warning that always fires is the one nobody reads. doctor
|
|
5030
|
+
// carries the strong version, because doctor is where the network check actually happens.
|
|
5031
|
+
` ${color.bold("caddis")} cli ${color.bold(report.cliVersion)} \xB7 pool ${color.bold(report.poolVersion)} ${color.dim('(what "current" is measured against)')}` + (report.extrasVersion ? ` \xB7 extras ${color.bold(report.extrasVersion)}` : "")
|
|
5024
5032
|
);
|
|
5025
5033
|
line("");
|
|
5026
5034
|
line(renderTable(["AGENT", "DETECTED", "CADDIS", "EXTRAS", "STATE"], report.agents.map(toRow)));
|
package/package.json
CHANGED