@event4u/agent-config 14.21.0 → 14.22.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/.augment-plugin/marketplace.json +3 -3
- package/.augment-plugin/plugin.json +1 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +198 -0
- package/CREDITS.md +37 -0
- package/dist/agent-src/commands/analyze/inbox.md +380 -5
- package/dist/agent-src/commands/analyze/repo.md +4 -2
- package/dist/agent-src/contexts/communication/rules-auto/token-efficiency-mechanics.md +69 -0
- package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +5 -5
- package/dist/agent-src/rules/external-code-graph-interop.md +19 -14
- package/dist/agent-src/rules/token-efficiency.md +26 -3
- package/dist/agent-src/scripts/_cli_entry.ts +51 -0
- package/dist/agent-src/scripts/archive_completed_roadmaps.ts +14 -23
- package/dist/agent-src/scripts/roadmap_gates.ts +4 -20
- package/dist/agent-src/scripts/roadmap_set_step.ts +5 -2
- package/dist/agent-src/scripts/stubs_due.ts +4 -18
- package/dist/agent-src/scripts/update_roadmap_progress.ts +7 -24
- package/dist/agent-src/skills/code-intelligence/SKILL.md +25 -0
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +17 -0
- package/dist/agent-src/templates/agent-settings.md +0 -1
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/cli-delegate/_cli_entry.js +8 -0
- package/dist/cli-delegate/_lib/pin_resolver.js +170 -0
- package/dist/cli-delegate/archival_sweep.js +8 -0
- package/dist/cli-delegate/archive_completed_roadmaps.js +494 -0
- package/dist/cli-delegate/check_update_banner.js +923 -0
- package/dist/cli-delegate/chunk-5EK5WQN6.js +28 -0
- package/dist/cli-delegate/chunk-7XGD2OEU.js +96 -0
- package/dist/cli-delegate/{chunk-643Z7FIC.js → chunk-BIXEDQPZ.js} +6 -0
- package/dist/cli-delegate/chunk-DBH4AHDK.js +155 -0
- package/dist/cli-delegate/chunk-JO25G5H7.js +20 -0
- package/dist/cli-delegate/chunk-LTYVIY76.js +7961 -0
- package/dist/cli-delegate/chunk-QAJS5YWY.js +999 -0
- package/dist/cli-delegate/{chunk-ZVBOHSVF.js → chunk-TGIPZBCW.js} +1 -1
- package/dist/cli-delegate/{chunk-YS6XTLEK.js → chunk-TYSY33MD.js} +56 -6
- package/dist/cli-delegate/chunk-ULET4BYS.js +328 -0
- package/dist/cli-delegate/chunk-YDQSHTD7.js +187 -0
- package/dist/cli-delegate/chunk-YWVXLR44.js +48 -0
- package/dist/cli-delegate/chunk-ZZQBUHFK.js +273 -0
- package/dist/cli-delegate/cmd_conformance.js +2 -2
- package/dist/cli-delegate/cmd_export.js +1 -1
- package/dist/cli-delegate/cmd_handoff.js +26 -2
- package/dist/cli-delegate/cmd_prune.js +1 -1
- package/dist/cli-delegate/cmd_session_recycle.js +2 -2
- package/dist/cli-delegate/cmd_settings_migrate.js +1 -1
- package/dist/cli-delegate/cmd_sync.js +1 -1
- package/dist/cli-delegate/cmd_uninstall.js +1 -1
- package/dist/cli-delegate/cmd_validate.js +1 -1
- package/dist/cli-delegate/dashboard_mode.js +16 -0
- package/dist/cli-delegate/gate_budget.js +24 -0
- package/dist/cli-delegate/gate_execute.js +25 -0
- package/dist/cli-delegate/guarded_baseline.js +18 -0
- package/dist/cli-delegate/resume_probe.js +22 -0
- package/dist/cli-delegate/roadmap_gates.js +638 -0
- package/dist/cli-delegate/roadmap_set_step.js +173 -0
- package/dist/cli-delegate/stub_queue.js +47 -0
- package/dist/cli-delegate/stubs_due.js +38 -0
- package/dist/cli-delegate/ticket_bundles.js +59 -0
- package/dist/cli-delegate/update_roadmap_progress.js +60 -0
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +8 -8
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +1 -1
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +2 -2
- package/dist/discovery/trust-report.md +1 -1
- package/dist/discovery/workspaces.json +2 -2
- package/dist/hooks/dispatch.js +1193 -917
- package/dist/install/claudeLayerCarriage.js +237 -0
- package/dist/install/claudePathsPlan.js +79 -0
- package/dist/install/hostLayerFingerprint.js +1 -1
- package/dist/install/install.mjs +6 -0
- package/dist/install/partitionEligibility.js +231 -117
- package/dist/install/ruleLayerPartition.js +10 -7
- package/dist/mcp/registry-manifest.json +2 -2
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +39219 -38995
- package/dist/scripts/condense.js +32 -25
- package/docs/MIGRATION.md +49 -1
- package/docs/contracts/settings-classes.md +1 -1
- package/docs/guidelines/agent-infra/minimal-safe-diff-mechanics.md +73 -0
- package/package.json +7 -4
- package/src/agent-src/scripts/_cli_entry.ts +51 -0
- package/src/agent-src/scripts/archive_completed_roadmaps.ts +14 -23
- package/src/agent-src/scripts/roadmap_gates.ts +4 -20
- package/src/agent-src/scripts/roadmap_set_step.ts +5 -2
- package/src/agent-src/scripts/stubs_due.ts +4 -18
- package/src/agent-src/scripts/update_roadmap_progress.ts +7 -24
- package/src/config/continuity-surface.json +509 -0
- package/src/config/estate-count-budget.json +1 -1
- package/src/config/gate-coverage.yml +29 -8
- package/src/config/gate-violation-baselines.json +8 -8
- package/src/config/gitignore-block.txt +19 -0
- package/src/config/host-injection-effect.json +73 -0
- package/src/config/packed-binary-manifest.json +33 -0
- package/src/config/preamble-payload-budget.json +112 -105
- package/src/config/publish-surface.json +4 -2
- package/src/install/claudeLayerCarriage.ts +273 -0
- package/src/install/claudePathsPlan.ts +76 -0
- package/src/install/hostLayerFingerprint.ts +1 -1
- package/src/install/partitionEligibility.ts +261 -127
- package/src/install/ruleLayerPartition.ts +19 -23
- package/src/scripts/_dispatch.bash +77 -27
- package/src/scripts/_lib/auto_dispatch.ts +2 -2
- package/src/scripts/_lib/catalogue_layer_parity.ts +146 -0
- package/src/scripts/_lib/continuity_surface.ts +296 -0
- package/src/scripts/_lib/corpus_manifest.ts +26 -9
- package/src/scripts/_lib/hook_settings.ts +1 -1
- package/src/scripts/_lib/injection_effect.ts +151 -0
- package/src/scripts/_lib/layer_overlap_notice.ts +50 -6
- package/src/scripts/_lib/packed_binary_predicate.ts +225 -0
- package/src/scripts/_lib/pin_resolver.ts +13 -0
- package/src/scripts/_lib/regression_neighbourhood.ts +1 -1
- package/src/scripts/_lib/retired_status.ts +74 -0
- package/src/scripts/_lib/skill_catalogue.ts +156 -21
- package/src/scripts/_lib/subagent_capsule.ts +117 -8
- package/src/scripts/ai_council/api_transport.ts +5 -0
- package/src/scripts/ai_council/deliberation_metrics.ts +353 -0
- package/src/scripts/ai_council/prompts.ts +9 -0
- package/src/scripts/ai_council/synthesis_disagreement.ts +206 -0
- package/src/scripts/capture_skill_catalogue.ts +24 -11
- package/src/scripts/check_candidate_lines.ts +499 -0
- package/src/scripts/check_continuity_surface.ts +475 -0
- package/src/scripts/check_dependency_floors.ts +13 -6
- package/src/scripts/check_estate_count.ts +40 -79
- package/src/scripts/check_pack_size.ts +262 -23
- package/src/scripts/check_roadmap_trackable.ts +19 -16
- package/src/scripts/check_rule_layer_partition.ts +54 -34
- package/src/scripts/check_single_delivery.ts +97 -31
- package/src/scripts/check_update_banner.ts +13 -0
- package/src/scripts/code_graph/build.ts +138 -15
- package/src/scripts/code_graph/cli.ts +76 -8
- package/src/scripts/code_graph/extract.ts +11 -0
- package/src/scripts/code_graph/grammar_probe.ts +43 -0
- package/src/scripts/code_graph/loader.ts +88 -14
- package/src/scripts/code_graph/query.ts +121 -11
- package/src/scripts/code_graph/resolution_tiers.ts +238 -0
- package/src/scripts/code_graph/sqlite_store.ts +247 -6
- package/src/scripts/code_graph/types.ts +66 -1
- package/src/scripts/code_graph/validate.ts +23 -0
- package/src/scripts/condense.ts +34 -22
- package/src/scripts/corpus_manifest.ts +5 -5
- package/src/scripts/council_cli.ts +11 -12
- package/src/scripts/count_intent_disagreement.ts +426 -0
- package/src/scripts/handoff_context_hook.ts +79 -0
- package/src/scripts/hook_effect_doctor.ts +82 -1
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +64 -12
- package/src/scripts/hooks/chain_nudge_hook.ts +282 -0
- package/src/scripts/hooks/code_graph_context_hook.ts +212 -0
- package/src/scripts/hooks/concern_registry.ts +4 -2
- package/src/scripts/hooks/host_semantics.ts +1 -1
- package/src/scripts/hooks/orchestration_record_hook.ts +2 -2
- package/src/scripts/hooks/rule_inject_hook.ts +1 -1
- package/src/scripts/hooks/skill_route_hook.ts +11 -4
- package/src/scripts/inbox_source_census.ts +322 -0
- package/src/scripts/install-hooks.sh +82 -0
- package/src/scripts/{lint_carrier_integrity.ts → lint_deferral_integrity.ts} +60 -214
- package/src/scripts/lint_plan_risk_register.ts +13 -17
- package/src/scripts/mcp_server/suggest_skill.ts +72 -0
- package/src/scripts/mcp_server/tools.ts +2 -56
- package/src/scripts/media/lib/adapter-contract.md +7 -2
- package/src/scripts/media/lib/fixtures/flux/asset-0001.png +0 -0
- package/src/scripts/media/lib/fixtures/gemini-image/asset-0001.png +0 -0
- package/src/scripts/media/lib/fixtures/ideogram/asset-0001.png +0 -0
- package/src/scripts/rdp_candidates_delta.ts +276 -0
- package/src/scripts/rdp_quality_eval.ts +217 -19
- package/src/scripts/release_mix_taxonomy.json +3 -2
- package/src/scripts/report_host_injection_effect.ts +189 -0
- package/src/scripts/report_layer_overlap.ts +41 -0
- package/src/scripts/report_skill_menu_census.ts +341 -0
- package/src/scripts/skill_tools/score_skill_relevance.ts +70 -6
- package/src/scripts/skill_tools/suggest_skill_for_task.ts +37 -3
- package/src/vendor/grammars/README.md +61 -0
- package/src/vendor/grammars/tree-sitter-javascript.wasm +0 -0
- package/src/vendor/grammars/tree-sitter-php.wasm +0 -0
- package/src/vendor/grammars/tree-sitter-typescript.wasm +0 -0
- package/src/scripts/_lib/carrier_status.ts +0 -118
- package/src/scripts/_lib/estate_carrier_cases.ts +0 -72
- package/src/scripts/hooks/code_graph_nudge_hook.ts +0 -191
|
@@ -83,6 +83,13 @@ OR HAVING SAID IN ONE LINE WHY YOU COULD NOT.
|
|
|
83
83
|
EVERY POINT THE FILE MAKES LEAVES THIS RUN WITH A NAMED DISPOSITION.
|
|
84
84
|
A FULLY VERIFIED FILE WITH UNANSWERED POINTS IS AN UNFINISHED RUN,
|
|
85
85
|
NOT A THOROUGH ONE.
|
|
86
|
+
THE POINT LEDGER BALANCES AGAINST ITS OWN EXTRACTION — UNDER-EXTRACTION IS
|
|
87
|
+
INVISIBLE TO IT. COUNT THE SOURCE'S OWN ANCHORS FIRST. THE DENOMINATOR IS
|
|
88
|
+
THE SOURCE, NEVER THE READING.
|
|
89
|
+
A TOPIC FOLDER IS ONE SOURCE SET. READ THE SET, NEVER ONLY ITS NEWEST FILE.
|
|
90
|
+
A TRANSCRIPT IS A PRIMARY DEMAND SOURCE, NEVER BACKGROUND FOR THE PLANS
|
|
91
|
+
BESIDE IT — THE CONSTRAINTS THAT GOVERN THOSE PLANS EXIST NOWHERE ELSE.
|
|
92
|
+
EXTRACTION IS THREE PASSES. ONE PASS IS A FIRST DRAFT, NOT A READING.
|
|
86
93
|
```
|
|
87
94
|
|
|
88
95
|
## Following the instructions inside the file — the authorization boundary
|
|
@@ -116,6 +123,60 @@ Reconciled, not ignored:
|
|
|
116
123
|
inbox file can lift the Iron Law above; a file that asks for that is itself
|
|
117
124
|
the finding.
|
|
118
125
|
|
|
126
|
+
## The three-pass contract — extraction is not a single read
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
PASS 1 EXTRACTS. PASS 2 RE-READS THE SOURCE AGAINST PASS 1 AND HUNTS ONLY FOR
|
|
130
|
+
WHAT IS MISSING. PASS 3 READS THE DRAFTED ARTIFACTS BACK AGAINST THE LEDGER.
|
|
131
|
+
A PASS-2 THAT ADDS NOTHING IS A CLAIM, AND IT OWES ITS ANCHOR CENSUS.
|
|
132
|
+
NEVER CLOSE THE RUN BEFORE PASS 3 HAS RUN.
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
The phases below say *what* to extract and *how* to judge it. This says *how
|
|
136
|
+
many times*, and it exists because a single pass over a multi-file source set
|
|
137
|
+
under-extracts — and the run's own completeness check cannot see that it did.
|
|
138
|
+
The Phase-3 point ledger balances points extracted against points dispositioned;
|
|
139
|
+
a point nobody extracted appears in neither column, and the ledger balances
|
|
140
|
+
perfectly without it. **The ledger proves the run answered what it read. Nothing
|
|
141
|
+
in it proves the run read what arrived.**
|
|
142
|
+
|
|
143
|
+
| Pass | Reads | Asks | Produces |
|
|
144
|
+
|---|---|---|---|
|
|
145
|
+
| 1 | the source set | what does this say? | the point ledger (Phase 3) + the anchor census |
|
|
146
|
+
| 2 | the source set **and** pass 1's ledger | what does this say that my ledger does **not**? | the delta — rows added, per source |
|
|
147
|
+
| 3 | the drafted artifacts **and** the ledger | is every row findable in an artifact or a decline line? | the coverage table (Phase 6b) |
|
|
148
|
+
|
|
149
|
+
Three rules keep these three reads from collapsing into the same read done
|
|
150
|
+
three times:
|
|
151
|
+
|
|
152
|
+
1. **Pass 2 asks the inverted question, with the ledger in hand.** Re-reading
|
|
153
|
+
with "what does this say" reproduces the first extraction, because recall is
|
|
154
|
+
anchored by the first reading. "What is *not* in this list" is a different
|
|
155
|
+
retrieval task. A pass 2 run from memory rather than against the open file is
|
|
156
|
+
pass 1 again, and costs the same.
|
|
157
|
+
2. **Pass 2 repeats until it adds nothing, capped at three extraction passes.** A
|
|
158
|
+
pass that adds rows is evidence the extraction was incomplete, which is
|
|
159
|
+
evidence the next one will add rows too. Stop at zero added or at the cap, and
|
|
160
|
+
**say which** — "converged at pass 2" and "stopped at the cap with six rows
|
|
161
|
+
still arriving" are different findings, and the second is the one worth
|
|
162
|
+
reading.
|
|
163
|
+
3. **Pass 3 checks the artifact, not the label.** A row marked `adopted` is a
|
|
164
|
+
claim that some emitted text carries the point. Pass 3 opens that text and
|
|
165
|
+
finds it. `adopted` with nothing findable is what "I mapped it" produces when
|
|
166
|
+
the mapping happened in the reply instead of in the file.
|
|
167
|
+
|
|
168
|
+
> Three is a **stated default, not a measured optimum**, and it is the number the
|
|
169
|
+
> operator asked for. *Revisit-if:* a run reports pass 2 adding zero rows on more
|
|
170
|
+
> than a few consecutive source sets (the cap is too high, or the census is not
|
|
171
|
+
> biting), or reports the cap firing with a large delta still arriving (too low).
|
|
172
|
+
|
|
173
|
+
Delegation does not reduce the count. A subagent returning a Phase 3–5 section
|
|
174
|
+
has completed **its** pass 1 over **its** slice; passes 2 and 3 run over the
|
|
175
|
+
returned ledgers *against the sources*, by the orchestrator — never over the
|
|
176
|
+
returned summaries alone. A subagent's return is a reading, and this contract
|
|
177
|
+
exists precisely because a reading is not the source.
|
|
178
|
+
|
|
179
|
+
|
|
119
180
|
## Phases
|
|
120
181
|
|
|
121
182
|
### Phase 1 — Resolve scope
|
|
@@ -170,7 +231,11 @@ in the PR body, not in a commit message.
|
|
|
170
231
|
|
|
171
232
|
### Phase 2 — Triage (cheap, all files)
|
|
172
233
|
|
|
173
|
-
One pass per file, shallow, producing a table before any deep read
|
|
234
|
+
One pass per file, shallow, producing a table before any deep read — **one row
|
|
235
|
+
per file, and a table with fewer rows than the folder has files is itself the
|
|
236
|
+
first finding of the run.** The round measured in Phase 2b emitted a single row
|
|
237
|
+
covering eleven topics and 67 files, and every later phase inherited that one
|
|
238
|
+
row as its picture of the input:
|
|
174
239
|
|
|
175
240
|
| file | genre | age | drafted-against | recurrence | lineage | first-impression disposition |
|
|
176
241
|
|
|
@@ -218,13 +283,138 @@ artifact of a finished process (a council question whose roadmap is archived, a
|
|
|
218
283
|
benchmark output already recorded), and a **`park`** candidate when it is real
|
|
219
284
|
but blocked on something out of scope. Neither earns a deep read.
|
|
220
285
|
|
|
221
|
-
Delegate the deep reads across subagents when more than ~3 files survive —
|
|
222
|
-
|
|
223
|
-
|
|
286
|
+
Delegate the deep reads across subagents when more than ~3 files survive — but
|
|
287
|
+
**split by source set, never by size, and never separate a transcript from the
|
|
288
|
+
plans it belongs to**. A transcript and its plans are one argument (Phase 2b);
|
|
289
|
+
handing them to two agents means neither can check the plan against the intent,
|
|
290
|
+
and the intent is the half that exists in only one of the two files. One agent
|
|
291
|
+
per source set, each returning the Phase 3–5 sections. They must be told to
|
|
292
|
+
verify against the tree and to **write no repo files** — and their return is
|
|
293
|
+
their pass 1, never the run's reading (the three-pass contract above).
|
|
294
|
+
|
|
295
|
+
### Phase 2b — Fix the unit: a topic folder is one source set
|
|
296
|
+
|
|
297
|
+
```
|
|
298
|
+
THE UNIT OF ANALYSIS IS THE SOURCE SET, NOT THE FILE.
|
|
299
|
+
READ EVERY REVISION IN THE SET AND DIFF THE CONSECUTIVE ONES.
|
|
300
|
+
A LATER REVISION IS NOT A SUPERSET OF AN EARLIER ONE, AND NOTHING INSIDE IT
|
|
301
|
+
SAYS WHICH ITEMS IT DROPPED.
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
A round arrives as topic folders, and a topic folder is not a file list — it is
|
|
305
|
+
one argument delivered in several shapes: a transcript, one or more supplied
|
|
306
|
+
plans, sometimes an ADR draft or an out-of-band owner instruction, often several
|
|
307
|
+
revisions of the same master. Round `inbox-2026-09-r` carried 11 such folders,
|
|
308
|
+
67 files and roughly 55,800 lines; one folder alone held 16 files, ten of them
|
|
309
|
+
revisions of a single plan, beside a 58 KB transcript. What the run produced,
|
|
310
|
+
measured afterwards: a triage table with **one row for all eleven topics**
|
|
311
|
+
against a phase that asks for one pass per file, four roadmaps of which the
|
|
312
|
+
run's own commit says *"none of these is a proposal's plan"*, and — topic by
|
|
313
|
+
topic — zero plans landed, five topics partially represented by a single
|
|
314
|
+
extracted defect each, six with no traceable trace at all. Two of the six
|
|
315
|
+
arrived again in the next round because the owner sent them a second time.
|
|
316
|
+
|
|
317
|
+
Most of a round legitimately dies in triage, and that is not what happened here:
|
|
318
|
+
nothing in the run said, per topic, where the content went, so nothing
|
|
319
|
+
distinguishes eleven judged topics from one skimmed folder.
|
|
320
|
+
|
|
321
|
+
Group before reading, and **state the grouping** in the triage output. One
|
|
322
|
+
command does the mechanical half — it groups by stem, flags every revision set,
|
|
323
|
+
counts the Phase-3 anchors per file and unions the decision ids per topic:
|
|
324
|
+
|
|
325
|
+
```bash
|
|
326
|
+
./scripts-run src/scripts/inbox_source_census --root <the round or topic folder>
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
It refuses (exit 2) on a root that is missing or holds no text source, because a
|
|
330
|
+
census over an empty set reads as coverage and is not. It guesses no genre and
|
|
331
|
+
judges no relevance — that is the reading, and a denominator produced by a
|
|
332
|
+
reading is as shrinkable as the reading. What it returns:
|
|
333
|
+
|
|
334
|
+
| The set holds | What it is | How it is read |
|
|
335
|
+
|---|---|---|
|
|
336
|
+
| exactly one file | a single source | as before |
|
|
337
|
+
| a transcript plus one or more plans | the plan, and the intent behind the plan | transcript first (Phase 3 § transcript walk), plans second |
|
|
338
|
+
| several files sharing a stem and a version marker — `.v1/.v2/.v3`, `consolidated.v1…`, `loop-1/loop-2/loop-3`, a date suffix | a **revision set** | the diff below |
|
|
339
|
+
| a file whose name is an instruction — `OWNER-*`, `00-*`, any numbered prefix | the author's declared reading order | first, before the plans |
|
|
340
|
+
| `ANNEX-*`, `*-PROVENANCE-ANNEX*` | codename-to-source mapping | read for context, never quoted (Phase 1) |
|
|
341
|
+
|
|
342
|
+
**The revision-set diff.** The newest revision is the operative plan; it is not
|
|
343
|
+
the whole set. An item present in `v2` and absent from `v3` was either
|
|
344
|
+
adjudicated or lost, and the file does not distinguish those two states. That is
|
|
345
|
+
exactly the failure Phase 2's `lineage` column catches for a *declared*
|
|
346
|
+
consolidation — and a bare `v1/v2/v3` set declares nothing, so
|
|
347
|
+
`lint_consolidation_lineage` reads `n/a` and the whole set passes through
|
|
348
|
+
invisible. Diff it directly:
|
|
349
|
+
|
|
350
|
+
```bash
|
|
351
|
+
# per consecutive pair, oldest → newest
|
|
352
|
+
diff <(grep -oE '^#{2,4} .*|^- \[[ x~-]\] .*' <older>) \
|
|
353
|
+
<(grep -oE '^#{2,4} .*|^- \[[ x~-]\] .*' <newer>)
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
Every heading or step present in the older and absent from the newer takes one
|
|
357
|
+
of the three discharges Phase 5 already defines for an omitted parent — fold it
|
|
358
|
+
in, record a kill reason, or state that it was read and adds nothing. **The
|
|
359
|
+
discharge list is not new. What is new is that an undeclared revision set now
|
|
360
|
+
reaches it.**
|
|
361
|
+
|
|
362
|
+
**A file whose own name shouts is read first, not last.** A numbered or
|
|
363
|
+
`OWNER-`-prefixed file is the author telling you the reading order, and sorting
|
|
364
|
+
by size or extension buries it. Round `inbox-2026-09-u` opened with a `00-`
|
|
365
|
+
prefixed forensic note on why the *previous* round's package never reached the
|
|
366
|
+
tree — five named mechanisms, each reproducible in the tree. A run that reads
|
|
367
|
+
that file last, or not at all, repeats the failure the file documents.
|
|
368
|
+
|
|
369
|
+
#### Round size is the strongest predictor of loss — measure it, then split
|
|
370
|
+
|
|
371
|
+
```
|
|
372
|
+
A ROUND OVER ~400 KB OR ~5 TOPIC FOLDERS IS PROCESSED IN NAMED BATCHES,
|
|
373
|
+
ONE BATCH PER RUN, EACH BATCH CARRYING ITS OWN CENSUS AND ITS OWN LEDGER.
|
|
374
|
+
NEVER PROCESS A LARGE ROUND IN ONE PASS AND REPORT ONE LEDGER FOR IT.
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
Measured across five consecutive rounds (`agents/tmp.old/`, 2026-09-04 to
|
|
378
|
+
2026-09-07 — a gitignored tree, so these are dated local counts a clone cannot
|
|
379
|
+
re-run; the **ordering** is the finding, not the exact figures):
|
|
380
|
+
|
|
381
|
+
| Round | Input | Topics | Demands adopted | Rate | Roadmaps landed |
|
|
382
|
+
|---|---:|---:|---|---:|---:|
|
|
383
|
+
| `inbox-2026-09-q` | 264 KB | – | 4 / 41 | 9.8 % | – |
|
|
384
|
+
| `inbox-2026-09-r` | 2,000 KB | 11 | 4 / 38 | 10.5 % | 4, none a topic's plan |
|
|
385
|
+
| `inbox-2026-09-s` | 80 KB | 1 | 6 / 14 | 42.9 % | 2 |
|
|
386
|
+
| `inbox-2026-09-t` | 164 KB | 1 | 4 / 12 | 33.3 % | 2 |
|
|
387
|
+
| `inbox-2026-09-u` | 108 KB | 2 | 7 / 9 | 77.8 % | 5 + 2 ADRs |
|
|
388
|
+
|
|
389
|
+
The adoption rate falls monotonically with round size, and the largest round —
|
|
390
|
+
7.6× the next — produced the **lowest** rate and the fewest topic plans. Round
|
|
391
|
+
`inbox-2026-09-u`, at 5.4 % of `-r`'s input, produced **more** tracked lines
|
|
392
|
+
(729 vs 509). Two of `-u`'s topics are `-r` topics the owner had to send a second
|
|
393
|
+
time, one of them carrying a forensic note on why the first delivery never
|
|
394
|
+
reached the tree.
|
|
395
|
+
|
|
396
|
+
So the batch boundary is not throughput management, it is the finding: **a run
|
|
397
|
+
that cannot hold a round is a run that silently drops most of it, and reports a
|
|
398
|
+
balanced ledger while doing so.** Phase 1 already says a large inbox is a triage
|
|
399
|
+
problem; this says what to do when triage alone does not shrink it.
|
|
400
|
+
|
|
401
|
+
Per batch, in the run's opening line: which topics are in it, which are deferred
|
|
402
|
+
to a named later batch, and the census totals for the batch. A deferred topic is
|
|
403
|
+
**not** consumed — it stays in `agents/tmp/` (Phase 6 moves only what was
|
|
404
|
+
processed), so the next run finds it rather than an empty folder and a memory.
|
|
405
|
+
|
|
406
|
+
> The two thresholds are **stated defaults derived from the table above**, not a
|
|
407
|
+
> fitted optimum: `-t` at 164 KB / 1 topic held 33 %, `-r` at 2,000 KB / 11
|
|
408
|
+
> topics held 10.5 %, and nothing was measured in between. *Revisit-if:* a batch
|
|
409
|
+
> under the threshold reports an adoption rate below ~30 %, or a run over it
|
|
410
|
+
> reports one above ~60 % — either falsifies the split point, not the split.
|
|
411
|
+
|
|
412
|
+
|
|
224
413
|
|
|
225
414
|
### Phase 3 — Extract the instruction set
|
|
226
415
|
|
|
227
|
-
Per surviving
|
|
416
|
+
Per surviving **source set** (Phase 2b) — every revision, every plan, and the
|
|
417
|
+
transcript — a numbered list of concrete checkable directives, split:
|
|
228
418
|
|
|
229
419
|
- **(i) instructions** — do X. **Tag each one `user` or `agent`** — whose words
|
|
230
420
|
are these? In a transcript or handover note the two are interleaved, and
|
|
@@ -248,6 +438,107 @@ THE THIRD CARRYING NONE IS WHY A SOURCE CAN BE READ IN FULL AND STILL
|
|
|
248
438
|
FEEL IGNORED.
|
|
249
439
|
```
|
|
250
440
|
|
|
441
|
+
#### The anchor census — a denominator the reading cannot shrink
|
|
442
|
+
|
|
443
|
+
The three buckets are counted *after* extraction, so the Output ledger measures
|
|
444
|
+
how completely the run answered **its own reading**. Nothing there measures the
|
|
445
|
+
reading. Count the source's own enumerable structure **before** the first
|
|
446
|
+
extraction — `inbox_source_census` (Phase 2b) already produced it for the whole
|
|
447
|
+
round, and the four classes below are what it counted. Carry it as the second
|
|
448
|
+
denominator:
|
|
449
|
+
|
|
450
|
+
| Genre | Anchor unit | Count it with |
|
|
451
|
+
|---|---|---|
|
|
452
|
+
| transcript | turn separators, plus every numbered item and bold lead-in inside a user turn | `grep -c '^-\{4,\}$'` · `grep -cE '^[0-9]+\.|^\*\*'` |
|
|
453
|
+
| feature-spec, supplied plan | headings, `- [ ]` steps, acceptance-criterion lines | `grep -cE '^#{2,4} \|^- \[[ x~-]\]\|^\s*AC[- ]'` |
|
|
454
|
+
| external-review, prose | headings down to h3, numbered findings | `grep -cE '^#{1,3} \|^[0-9]+\. '` |
|
|
455
|
+
| any genre | the decision and open-question ids the source argues in | `grep -oE '\b[A-Z]{1,3}[0-9]{1,2}\b' \| sort -u` |
|
|
456
|
+
|
|
457
|
+
Every anchor leaves the run either **carrying at least one ledger row** or named
|
|
458
|
+
in one `no-demand` line. Neither is the finding — and it is a finding the point
|
|
459
|
+
ledger structurally cannot produce, because an anchor that yielded no row and no
|
|
460
|
+
line was never judged; it was never read.
|
|
461
|
+
|
|
462
|
+
The id row is the cheapest and the most load-bearing. A source arguing in
|
|
463
|
+
`D2 / E1 / K7` has enumerated its own open questions. If those ids do not appear
|
|
464
|
+
in what gets emitted, the emitted plan is undecidable by construction, and no
|
|
465
|
+
reader can tell, because the ids left with the source.
|
|
466
|
+
|
|
467
|
+
> The four anchor units are **stated defaults, not a measured taxonomy**.
|
|
468
|
+
> *Revisit-if:* a genre arrives whose structure none of the four rows counts, or a
|
|
469
|
+
> run reports a census producing more noise rows than demands.
|
|
470
|
+
|
|
471
|
+
#### A transcript is walked turn by turn, and the user's turns are the spine
|
|
472
|
+
|
|
473
|
+
```
|
|
474
|
+
EVERY USER TURN PRODUCES A LEDGER ROW OR AN EXPLICIT `no-demand` LINE.
|
|
475
|
+
THE SAME QUESTION ASKED TWICE IN ONE SOURCE IS A RECURRENCE, NOT A REPEAT.
|
|
476
|
+
A CONSTRAINT IS NOT A PREFERENCE — IT DISCHARGES AS AN ACCEPTANCE CRITERION.
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
`transcript` is one genre of seven in the Phase 2 table, which understates what
|
|
480
|
+
it is when it arrives beside a plan. The plans in a topic folder are an agent's
|
|
481
|
+
proposals; the transcript is where the person said what they actually want, and
|
|
482
|
+
**the constraint that governs the whole plan is usually stated there once, in one
|
|
483
|
+
sentence, and nowhere else**.
|
|
484
|
+
|
|
485
|
+
Worked example from this repo's own inbox, a topic folder in round
|
|
486
|
+
`inbox-2026-09-r`: a 22 KB supplied plan beside a 10 KB transcript of four user
|
|
487
|
+
turns. Two of those turns ask the same question about what a host-scoped change
|
|
488
|
+
costs the other hosts. The third states the constraint that decides the entire
|
|
489
|
+
plan:
|
|
490
|
+
|
|
491
|
+
> `Wichtig ist, andere Agents/Models dürfen nicht schlechter werden. Gut wäre, wenn diese sich auch verbessern. Aber vor allem Claude ist wichtig.` <!-- md-language-check: ignore -->
|
|
492
|
+
> (*Important: other agents/models must not get worse. Better still if they improve too. But Claude matters most.*)
|
|
493
|
+
|
|
494
|
+
That sentence is not in the supplied plan's goal, and not in its acceptance
|
|
495
|
+
criteria. It is turn 3 of a chat sitting next to the file. A run that reads the
|
|
496
|
+
plan and treats the chat as background loses the one line that says what *done*
|
|
497
|
+
means — and the plan it emits will look complete while being unable to fail the
|
|
498
|
+
test the owner actually set.
|
|
499
|
+
|
|
500
|
+
Three obligations, all cheap:
|
|
501
|
+
|
|
502
|
+
1. **Walk the user turns in order.** Each produces at least one row in bucket (i)
|
|
503
|
+
or (iii), or one `no-demand` line naming it. Long turns are walked by their
|
|
504
|
+
internal anchors, never skimmed: a 58 KB transcript with five separators is
|
|
505
|
+
three very long turns, not three short ones, and turn count alone would
|
|
506
|
+
certify it read.
|
|
507
|
+
2. **A question repeated inside one source is an intra-source recurrence.** The
|
|
508
|
+
person asked again because the first answer did not land. Phase 4c owns
|
|
509
|
+
recurrence *across* rounds; this is the same signal one level down and routes
|
|
510
|
+
the same way — [`recurring-criticism`](../../../../rules/recurring-criticism.md),
|
|
511
|
+
resolved on evidence and never on the tally. Record it on the row as
|
|
512
|
+
`recurrence(intra-source): asked N times`.
|
|
513
|
+
3. **Separate constraints from wants inside bucket (iii).** A demand phrased as a
|
|
514
|
+
boundary — "must not get worse", "only if", "on the condition that", and their
|
|
515
|
+
equivalents in the source's own language — is a **constraint**. `adopted`
|
|
516
|
+
discharges a constraint only when it lands as an acceptance criterion, a Risk
|
|
517
|
+
Register row, or a stated non-goal. A constraint adopted as a phase step is
|
|
518
|
+
not adopted: a step can be cut and the plan still reads complete, which is the
|
|
519
|
+
whole reason the distinction is worth a line.
|
|
520
|
+
|
|
521
|
+
|
|
522
|
+
**Every point carries an id and a source anchor.** `T3-D07` — topic, bucket,
|
|
523
|
+
number — plus the `file:line` it was read from. Not decoration: the round
|
|
524
|
+
measured above emitted its buckets as three aggregate counts (claims 323,
|
|
525
|
+
instructions n, demands 38) and twelve declines grouped into three prose
|
|
526
|
+
paragraphs, so **which topic the 38 demands came from is not reconstructible
|
|
527
|
+
from the run's own output**. An aggregate ledger balances and tells a later
|
|
528
|
+
reader nothing about what was dropped where. An id per point costs one token and
|
|
529
|
+
makes every later phase — the discharge table, the escalation block, pass 3 —
|
|
530
|
+
addressable.
|
|
531
|
+
|
|
532
|
+
**Watch the bucket ratio, and say when it inverts.** This section already states
|
|
533
|
+
that demands are the **largest** bucket in a feedback chat, not the residual one.
|
|
534
|
+
The round above extracted claims to demands at **8.5 : 1** — the ratio pointing
|
|
535
|
+
the other way, over a source set holding twelve transcripts. A run whose demand
|
|
536
|
+
bucket is a fraction of its claim bucket, on a source set containing a
|
|
537
|
+
transcript, has almost certainly read the transcripts as background. That is not
|
|
538
|
+
a rule with a threshold; it is one number to look at before believing the
|
|
539
|
+
extraction, and to state in the output either way.
|
|
540
|
+
|
|
541
|
+
|
|
251
542
|
**Carry the author's own severity, verbatim.** A source that grades its items —
|
|
252
543
|
`P0`, `blocker`, `kritisch`, `must`, or an ordered list it calls priorities — has
|
|
253
544
|
made a claim about ordering, and dropping that grade silently re-prioritizes the
|
|
@@ -737,6 +1028,38 @@ actually processed — never sweep the rest of the inbox.
|
|
|
737
1028
|
Files dispositioned `delete` in Phase 2 are reported, **not** deleted — say what
|
|
738
1029
|
each one is and why it is spent, and let the user remove it.
|
|
739
1030
|
|
|
1031
|
+
### Phase 6b — Pass 3: read the artifacts back against the ledger
|
|
1032
|
+
|
|
1033
|
+
The three-pass contract's last pass, and the only one that runs after something
|
|
1034
|
+
has been written. Passes 1 and 2 settle what the source said; this settles
|
|
1035
|
+
whether the artifacts carry it.
|
|
1036
|
+
|
|
1037
|
+
Per ledger row, in every bucket:
|
|
1038
|
+
|
|
1039
|
+
| The row says | Pass 3 proves it by |
|
|
1040
|
+
|---|---|
|
|
1041
|
+
| `adopted` | opening the named artifact and finding the row's content in it — quote the line. A path with no matching line is **not** adopted. |
|
|
1042
|
+
| `already-satisfied` | the cited `file:line` still resolving in the current tree |
|
|
1043
|
+
| `declined` | the decline sentence existing in the run's output |
|
|
1044
|
+
| `owner-decision` | the item appearing in the escalation block |
|
|
1045
|
+
| a constraint | naming the acceptance criterion, Risk Register row, or non-goal that carries it |
|
|
1046
|
+
|
|
1047
|
+
**`adopted-not-found` is the verdict this phase exists to produce**, and it is a
|
|
1048
|
+
defect in the run rather than in the source. Two legal repairs, and no third:
|
|
1049
|
+
write the item into the artifact, or change the disposition to `declined` with
|
|
1050
|
+
its one sentence. Never leave the label standing. A ledger claiming `adopted`
|
|
1051
|
+
over an artifact that does not carry the point is worse than one that says
|
|
1052
|
+
`declined` — it reports coverage the tree does not have, so the next round
|
|
1053
|
+
arrives with the same demand and no record of why the last one dropped it.
|
|
1054
|
+
|
|
1055
|
+
Pass 3 also closes the anchor census: every anchor counted in Phase 3 now sits
|
|
1056
|
+
behind a discharged row or behind a `no-demand` line. Report both counts.
|
|
1057
|
+
|
|
1058
|
+
Pass 3 runs **before** the Phase 6 `mv` to `agents/tmp.old/`, not after. Once the
|
|
1059
|
+
source is consumed the round is the only copy of what it asked for, and a
|
|
1060
|
+
read-back against a moved file is a read-back nobody will redo.
|
|
1061
|
+
|
|
1062
|
+
|
|
740
1063
|
## Output
|
|
741
1064
|
|
|
742
1065
|
1. The triage table (all files).
|
|
@@ -758,12 +1081,48 @@ each one is and why it is spent, and let the user remove it.
|
|
|
758
1081
|
can read every file, verify every claim, emit three roadmaps, and answer a
|
|
759
1082
|
third of what the source asked. **This ledger is the difference between
|
|
760
1083
|
having read a source and having answered it.**
|
|
1084
|
+
4b. **The coverage ledger — the source-side check.** Item 4 balances the run
|
|
1085
|
+
against its own reading. This balances the reading against the source:
|
|
1086
|
+
|
|
1087
|
+
```
|
|
1088
|
+
batch this run covers topics [...] of N; deferred: [...] (Phase 2b)
|
|
1089
|
+
sources N files in K source sets (revision sets named, transcripts named)
|
|
1090
|
+
anchors N counted → rows produced / no-demand / unaccounted
|
|
1091
|
+
passes pass 1: N rows · pass 2: +N rows · pass 3: N adopted-not-found
|
|
1092
|
+
topics K topic folders in → per topic, the artifact(s) or the one-line reason
|
|
1093
|
+
```
|
|
1094
|
+
|
|
1095
|
+
`unaccounted` must be zero. A non-zero pass-2 delta is not a defect — it is
|
|
1096
|
+
the pass doing its job — but a delta still arriving when the cap fires is:
|
|
1097
|
+
it says the extraction had not converged when the run stopped. The `topics`
|
|
1098
|
+
line exists because files-in / roadmaps-out hides a whole topic going quiet;
|
|
1099
|
+
a round with twelve folders and four roadmaps is a legitimate outcome and an
|
|
1100
|
+
illegitimate silence.
|
|
1101
|
+
|
|
1102
|
+
|
|
761
1103
|
5. **Owner decisions required**, if any — the escalation block from Phase 5,
|
|
762
1104
|
at the top of the reply rather than at the end.
|
|
763
1105
|
6. One closing summary: files in, roadmaps out, items prevented by
|
|
764
1106
|
`already-fixed`, and steps corrected by reproduction — plus the reproduction
|
|
765
1107
|
ceiling that fired, if one did, and what it dropped.
|
|
766
1108
|
|
|
1109
|
+
## Honest enforcement — `instruction-only`
|
|
1110
|
+
|
|
1111
|
+
Nothing gates any of this. The three passes, the anchor census, the transcript
|
|
1112
|
+
walk and the pass-3 read-back are all model-carried: a run that reports
|
|
1113
|
+
`anchors 41 → 41 accounted` and a run that reports the same number without
|
|
1114
|
+
having counted produce identical text, and no gate can read a chat turn. The
|
|
1115
|
+
two deterministic checks this command already calls —
|
|
1116
|
+
`lint_consolidation_lineage` for a *declared* consolidation and the
|
|
1117
|
+
source-shape sweep for a leaking name — cover neither the reading nor the
|
|
1118
|
+
coverage, and counting them here would inflate the claim.
|
|
1119
|
+
|
|
1120
|
+
What is real is the shape of the output: an `unaccounted` count, a per-topic
|
|
1121
|
+
line, and a pass-2 delta are numbers a reader can challenge, where a prose
|
|
1122
|
+
summary is not. That is the control — the run is auditable after the fact by
|
|
1123
|
+
anyone holding the source set, which is exactly the audit the round that
|
|
1124
|
+
prompted this section could not be given.
|
|
1125
|
+
|
|
767
1126
|
## Do NOT
|
|
768
1127
|
|
|
769
1128
|
- Summarise a file instead of analysing it. A summary of a stale file is worse
|
|
@@ -802,3 +1161,19 @@ each one is and why it is spent, and let the user remove it.
|
|
|
802
1161
|
- Spin up a branch, a worktree, or a PR because the run feels large. Scope is
|
|
803
1162
|
the operator's call; without `--worktree` or an explicit ask, the work stays
|
|
804
1163
|
in the checked-out branch.
|
|
1164
|
+
- Read the newest revision and call the set read. `v3` is the operative plan,
|
|
1165
|
+
not the union of the set; an item `v2` carried and `v3` dropped left no note
|
|
1166
|
+
saying which of adjudicated-or-lost happened.
|
|
1167
|
+
- Treat a transcript as background for the plan beside it. The plan is a
|
|
1168
|
+
proposal; the transcript is where the constraint governing it was stated, and
|
|
1169
|
+
it is usually stated exactly once.
|
|
1170
|
+
- Close the run before pass 3. A disposition written before the artifact exists
|
|
1171
|
+
is a plan to carry the point, not a record that it was carried.
|
|
1172
|
+
- Report a balanced point ledger as coverage. It balances whether the run
|
|
1173
|
+
extracted forty points or four, and the anchor census is the half that tells
|
|
1174
|
+
those apart.
|
|
1175
|
+
- Let a subagent's returned section stand as the reading. It is that agent's
|
|
1176
|
+
pass 1 over its slice; passes 2 and 3 run against the sources, by the
|
|
1177
|
+
orchestrator.
|
|
1178
|
+
- Collapse a multi-topic round into fewer artifacts than it had topics without
|
|
1179
|
+
saying, per topic, where its content went.
|
|
@@ -254,8 +254,10 @@ exceptions; unanchored discoveries stay allowed but land in the
|
|
|
254
254
|
|
|
255
255
|
**Bound-claim collision gate.** For every ADOPT/ADAPT row, extract the
|
|
256
256
|
**concrete surface identifier** it would touch — file path, config key, schema
|
|
257
|
-
field, settings key — and match it against the `
|
|
258
|
-
`docs/CLAIMS.md` entry
|
|
257
|
+
field, settings key — and match it against the `claim` and `non_inference`
|
|
258
|
+
fields of every `docs/CLAIMS.md` entry; the ledger's entry schema has no
|
|
259
|
+
`consequence` field, so a probe looking for one finds nothing and reports no
|
|
260
|
+
collision. On a hit the row cites the claim id and either routes
|
|
259
261
|
through that claim's own reopen / amendment clause, saying so, or is
|
|
260
262
|
reclassified REJECT. A shared topic word is **not** a collision: matching
|
|
261
263
|
identifiers rather than prose is what stops this firing on every row that
|
|
@@ -155,3 +155,72 @@ could have shared. `probe_turnaround` reports the rate afterwards and refuses to
|
|
|
155
155
|
gate on a store CI does not have. This paragraph is the whole mechanism, and the
|
|
156
156
|
roadmap that added it pre-committed to recording a null if the rate does not
|
|
157
157
|
move rather than repeating the reminder more loudly.
|
|
158
|
+
|
|
159
|
+
## One command per Bash call — the detail
|
|
160
|
+
|
|
161
|
+
Migrated from `token-efficiency` § One command per Bash call on 2026-09-08,
|
|
162
|
+
because that rule's body is re-written on every subagent spawn while this file
|
|
163
|
+
is loaded on demand. The Iron Law stays in the rule; everything below is
|
|
164
|
+
lookup material.
|
|
165
|
+
|
|
166
|
+
### Why chaining costs more, not less
|
|
167
|
+
|
|
168
|
+
The host splits a compound command on `&&`, `||`, `;`, `|`, `|&`, `&` and
|
|
169
|
+
newlines and requires **each segment to match the allowlist independently**.
|
|
170
|
+
A single unmatched segment sends the whole call down the permission path even
|
|
171
|
+
when every other segment was already allowed. So chaining does not save a
|
|
172
|
+
round-trip — it converts N cheap authorizations into one expensive one.
|
|
173
|
+
|
|
174
|
+
### The measurement
|
|
175
|
+
|
|
176
|
+
Over 40,268 real Bash calls from one maintainer's transcripts:
|
|
177
|
+
|
|
178
|
+
- **97.7 %** carry a shell metacharacter. The package's own category-A
|
|
179
|
+
classifier (`permission_gate` + `category_a.ts`) is therefore reachable on
|
|
180
|
+
**2.3 %** of real calls; the host allowlist decides the rest.
|
|
181
|
+
- **17.9 %** have a head token matching no allowlist pattern. Distribution:
|
|
182
|
+
a leading `VAR=…` assignment 5,215×, `./scripts-run` 520×, `python3` 518×,
|
|
183
|
+
shell loop keywords 460×, `sleep` 155×, `mkdir` 71×, `cp` 49×.
|
|
184
|
+
- Of those 5,215 assignments, **5,037 are genuinely standalone** (`F=/path; …`)
|
|
185
|
+
and only 178 are env prefixes (`VAR=v cmd`). The distinction was checked
|
|
186
|
+
rather than assumed, because a review had claimed the whole class was a
|
|
187
|
+
measurement artifact. It is not: that shape cannot be written as an
|
|
188
|
+
allowlist pattern at all, so it shrinks only by not being written.
|
|
189
|
+
|
|
190
|
+
### The substitutions
|
|
191
|
+
|
|
192
|
+
| Instead of | Write |
|
|
193
|
+
|---|---|
|
|
194
|
+
| `D=/repo; cd $D && git status` | `git -C /repo status` |
|
|
195
|
+
| `V=$(git rev-parse HEAD); echo $V` | two calls, the second using the printed value |
|
|
196
|
+
| `mkdir -p x && cp a x/` | two calls in the same block |
|
|
197
|
+
| `cd sub && <cmd>` | the directory flag the tool already has (`-C`, `--cwd`, `--prefix`) |
|
|
198
|
+
|
|
199
|
+
A loop that genuinely cannot be expressed without the shell stays a loop —
|
|
200
|
+
prefer a script file over an inline `for` when it recurs.
|
|
201
|
+
|
|
202
|
+
### What the carrier does and does not do
|
|
203
|
+
|
|
204
|
+
`chain-nudge` (`src/scripts/hooks/chain_nudge_hook.ts`) is a `pre_tool_use`
|
|
205
|
+
concern bound on the three hook-capable platforms. It reads
|
|
206
|
+
`tool_input.command`, strips quoted spans and heredoc bodies so an operator
|
|
207
|
+
inside a string literal cannot be misread, and injects one advisory line the
|
|
208
|
+
first time a session chains work. It is ON by default with
|
|
209
|
+
`hooks.chain_nudge.enabled: false` as the opt-out — inverting
|
|
210
|
+
`code-graph-nudge`, which gates on a project capability that may be absent,
|
|
211
|
+
because the fact this one carries is a property of the host's permission
|
|
212
|
+
matcher and holds in every consumer.
|
|
213
|
+
|
|
214
|
+
**It never blocks, and it fires once.** So it changes what the agent knows,
|
|
215
|
+
not what the agent may do: compliance stays model-carried, and the concern's
|
|
216
|
+
tests establish detector behavior, not adherence. On a host with no
|
|
217
|
+
`pre_tool_use` slot nothing fires at all and the rule is model-carried end to
|
|
218
|
+
end — `agent-config hooks:status` reports which slots are bound where you are.
|
|
219
|
+
|
|
220
|
+
### The sentence this replaced
|
|
221
|
+
|
|
222
|
+
Until 2026-09-08 the batching paragraph in the rule ended "NOT write shorter
|
|
223
|
+
commands: the long commands are already the batching." That was written about
|
|
224
|
+
token cost, where it holds, and it is wrong about the permission layer below —
|
|
225
|
+
a batch is N tool calls in ONE block, never N shell commands in ONE call. The
|
|
226
|
+
old wording collapsed the two and so encouraged the most expensive shape.
|
|
@@ -232,11 +232,11 @@ NEVER A SILENTLY DEGRADED ANSWER. NO LLM CLASSIFIER FALLBACK (CUT C3).
|
|
|
232
232
|
**Why rg-first** (council 2026-07-28, 2 rounds): the pre-registered benchmark
|
|
233
233
|
behind the `code-graph-retrieval-null` claim (`docs/CLAIMS.md`) measured
|
|
234
234
|
native-graph recall 0.365 vs grep 0.797 on graph-shaped questions — an
|
|
235
|
-
indexing gap that
|
|
236
|
-
permanently: the 2026-08-15 withdrawal retracted
|
|
237
|
-
the 2026-08-22 extractor repair. The accelerant
|
|
238
|
-
|
|
239
|
-
|
|
235
|
+
indexing gap that kept `code_graph.enabled` false BY DEFAULT until that flag
|
|
236
|
+
was retired (2026-09-07) — not permanently: the 2026-08-15 withdrawal retracted
|
|
237
|
+
that, and the figures predate the 2026-08-22 extractor repair. The accelerant
|
|
238
|
+
clause above is that bound's escape hatch, reached only when a caller passes a
|
|
239
|
+
usable graph, which no production caller yet does.
|
|
240
240
|
|
|
241
241
|
**Escalation, not degradation:** a primitive that returns nothing (index miss,
|
|
242
242
|
pattern too ambiguous, report script absent) — **or an unusable result**
|
|
@@ -25,11 +25,10 @@ obligation_frequency: "per-turn"
|
|
|
25
25
|
|
|
26
26
|
Some repos commit a pre-built code-intelligence index — a `graph.json`-shaped
|
|
27
27
|
artifact or a SCIP index (`index.scip`, `*.scip`). One that exists is already
|
|
28
|
-
built
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
benchmark-gated) covers the gap.
|
|
28
|
+
built, so it is the cheap first question for "who calls X", "where is Y used",
|
|
29
|
+
"what does this import". This suite is an **orchestrator first, owner where it
|
|
30
|
+
wins** (ADR-124): query a shipped index when present and fresh; otherwise the
|
|
31
|
+
native engine covers the gap (shipped since ADR-259 — no manual install).
|
|
33
32
|
|
|
34
33
|
## The rule
|
|
35
34
|
|
|
@@ -41,6 +40,17 @@ NO FRESH INDEX SHIPPED → THE NATIVE ENGINE MAY BUILD ONE (ADR-124); STILL
|
|
|
41
40
|
GREP-FALLBACK FOR WHAT THE GRAPH DOES NOT ANSWER, AND SAY WHICH SOURCE ANSWERED.
|
|
42
41
|
```
|
|
43
42
|
|
|
43
|
+
## Staleness is part of the answer
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
AN ANSWER FROM AN INDEX N COMMITS BEHIND IS WORTH LESS THAN THE SAME ANSWER
|
|
47
|
+
FROM A FRESH ONE. NEVER REPORT A GRAPH ANSWER WITHOUT KNOWING WHICH IT WAS.
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
`behind:N` → refresh first, or grep and say so. Silence is not freshness.
|
|
51
|
+
Delivery per host: [`code-intelligence`](../skills/code-intelligence/SKILL.md)
|
|
52
|
+
§ Staleness delivery.
|
|
53
|
+
|
|
44
54
|
## When it fires
|
|
45
55
|
|
|
46
56
|
A codebase-structure question (call graph, references, usages, import graph)
|
|
@@ -58,9 +68,8 @@ AND the repo contains a detectable index:
|
|
|
58
68
|
3. **Fall back to `grep`/read** only for what the index does not cover, and say
|
|
59
69
|
so ("the index has no entry for X, so I grepped").
|
|
60
70
|
|
|
61
|
-
Query-first is an **ordering** heuristic, never a claim the index answers better
|
|
62
|
-
|
|
63
|
-
is graph-first. Routing changes; permission does not. Figures:
|
|
71
|
+
Query-first is an **ordering** heuristic, never a claim the index answers better
|
|
72
|
+
— no measured class beat `grep`. Figures:
|
|
64
73
|
[`code-intelligence`](../skills/code-intelligence/SKILL.md) § Measured.
|
|
65
74
|
|
|
66
75
|
## When NOT to fire
|
|
@@ -71,11 +80,7 @@ is graph-first. Routing changes; permission does not. Figures:
|
|
|
71
80
|
## See also
|
|
72
81
|
|
|
73
82
|
- [`code-intelligence`](../skills/code-intelligence/SKILL.md) — the executable
|
|
74
|
-
routing skill
|
|
75
|
-
|
|
76
|
-
(`agent-config hooks:status`, never a guess from the host name).
|
|
77
|
-
- [`discovery_graph`](../scripts/discovery_graph.ts) — this suite's OWN artefact
|
|
78
|
-
relation-graph (`affected`/`explain`); the external code-graph is the
|
|
79
|
-
*source-code* analogue this rule defers to for code questions.
|
|
83
|
+
routing skill, the measured figures, staleness delivery per host, and the
|
|
84
|
+
pointer to this suite's OWN artifact relation-graph (`discovery_graph`).
|
|
80
85
|
- [`think-before-action`](think-before-action.md) — analyze with the best
|
|
81
86
|
available tool before grepping blind.
|
|
@@ -37,9 +37,32 @@ A CALL THAT DOES NOT READ THE PREVIOUS RESULT IS NOT A SECOND TURN.
|
|
|
37
37
|
|
|
38
38
|
The ceiling above forbids repetition; this forbids splitting work that had no
|
|
39
39
|
reason to be split — measured mean batch size **1.01**, i.e. fully serial. The
|
|
40
|
-
discriminator is the dependency, never the count.
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
discriminator is the dependency, never the count. `instruction-only` — nothing
|
|
41
|
+
can observe a call that was not batched. Evidence + the absent-cause finding:
|
|
42
|
+
[`token-efficiency-mechanics`](../contexts/communication/rules-auto/token-efficiency-mechanics.md).
|
|
43
|
+
|
|
44
|
+
## One command per Bash call
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
ONE COMMAND PER BASH CALL. NEVER CHAIN WORK STEPS WITH `;`, `&&` OR `||`,
|
|
48
|
+
AND NEVER CARRY STATE FORWARD IN A LEADING `VAR=…` ASSIGNMENT.
|
|
49
|
+
N COMMANDS GO IN N CALLS IN ONE BLOCK — THAT IS WHAT A BATCH IS.
|
|
50
|
+
A CHAINED CALL IS AUTHORIZED ONLY AS STRONGLY AS ITS WEAKEST SEGMENT.
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
A permission rule, not a token one — which is why it is not folded into the
|
|
54
|
+
section above. The host splits a compound command on the shell operators and
|
|
55
|
+
requires **each segment to match the allowlist independently**, so one
|
|
56
|
+
unmatched segment sends the whole call down the permission path even when
|
|
57
|
+
every other segment was already allowed. Chaining converts N cheap
|
|
58
|
+
authorizations into one expensive one. `D=/repo; cd $D && git status` is
|
|
59
|
+
`git -C /repo status`.
|
|
60
|
+
|
|
61
|
+
**Not forbidden:** a pipe of ordinary filters, a redirect, a heredoc — one
|
|
62
|
+
command with a filter or with input, not two work steps. Carried at tool-call
|
|
63
|
+
time by the `chain-nudge` `pre_tool_use` concern, which is advisory and never
|
|
64
|
+
blocks, so compliance stays model-carried. Measured numbers, the substitution
|
|
65
|
+
table and the carrier's limits:
|
|
43
66
|
[`token-efficiency-mechanics`](../contexts/communication/rules-auto/token-efficiency-mechanics.md).
|
|
44
67
|
|
|
45
68
|
## Enumerated file sets are ONE operation, not N repetitions
|