@event4u/agent-config 14.20.0 → 14.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/.augment-plugin/marketplace.json +3 -3
  2. package/.augment-plugin/plugin.json +1 -1
  3. package/.claude-plugin/marketplace.json +1 -1
  4. package/CHANGELOG.md +243 -0
  5. package/README.md +1 -1
  6. package/agents/templates/.ai-council.yml.example +10 -0
  7. package/dist/agent-src/commands/analyze/inbox.md +1 -1
  8. package/dist/agent-src/commands/analyze/{reference-repo.md → repo.md} +247 -32
  9. package/dist/agent-src/commands/analyze/roadmap-repos.md +129 -0
  10. package/dist/agent-src/commands/analyze.md +12 -7
  11. package/dist/agent-src/commands/feature/plan.md +55 -16
  12. package/dist/agent-src/commands/feature/refactor.md +8 -3
  13. package/dist/agent-src/commands/humanize.md +48 -4
  14. package/dist/agent-src/contexts/execution/contract-decision-sheet.md +22 -1
  15. package/dist/agent-src/contexts/execution/host-capability-manifest.md +4 -1
  16. package/dist/agent-src/contexts/execution/roadmap-process-loop.md +35 -2
  17. package/dist/agent-src/contexts/execution/terminal-states.md +4 -1
  18. package/dist/agent-src/rules/evaluator-independence.md +4 -4
  19. package/dist/agent-src/rules/external-reference-deep-dive.md +2 -2
  20. package/dist/agent-src/skills/competitive-positioning/SKILL.md +2 -2
  21. package/dist/agent-src/skills/humanizer/references/anti-aiisms.md +27 -11
  22. package/dist/agent-src/skills/learning-to-rule-or-skill/SKILL.md +1 -1
  23. package/dist/agent-src/skills/markitdown/SKILL.md +1 -1
  24. package/dist/agent-src/skills/repomix-packer/SKILL.md +1 -1
  25. package/dist/agent-src/skills/technical-specification/SKILL.md +4 -0
  26. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  27. package/dist/agent-src/templates/features.md +5 -0
  28. package/dist/agent-src/templates/roadmaps.md +15 -0
  29. package/dist/cli-delegate/{chunk-KPBWFOPZ.js → chunk-2FTMENJL.js} +194 -37
  30. package/dist/cli-delegate/{chunk-PI2GU3DP.js → chunk-2TAQ2K4V.js} +4 -1
  31. package/dist/cli-delegate/{chunk-C6IPZRDA.js → chunk-643Z7FIC.js} +1 -1
  32. package/dist/cli-delegate/{chunk-NUMQHLS5.js → chunk-J3RFNKG4.js} +21 -2
  33. package/dist/cli-delegate/cmd_conformance.js +17 -3
  34. package/dist/cli-delegate/cmd_doctor.js +3 -3
  35. package/dist/cli-delegate/cmd_export.js +2 -2
  36. package/dist/cli-delegate/cmd_handoff.js +1 -1
  37. package/dist/cli-delegate/cmd_prune.js +2 -2
  38. package/dist/cli-delegate/cmd_settings_migrate.js +2 -2
  39. package/dist/cli-delegate/cmd_sync.js +2 -2
  40. package/dist/cli-delegate/cmd_uninstall.js +2 -2
  41. package/dist/cli-delegate/cmd_validate.js +2 -2
  42. package/dist/discovery/deprecation-report.md +1 -1
  43. package/dist/discovery/discovery-manifest.json +56 -25
  44. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  45. package/dist/discovery/discovery-manifest.summary.md +3 -3
  46. package/dist/discovery/dormancy-report.md +1 -1
  47. package/dist/discovery/orphan-report.md +1 -1
  48. package/dist/discovery/packs.json +7 -6
  49. package/dist/discovery/trust-report.md +2 -2
  50. package/dist/discovery/workspaces.json +6 -5
  51. package/dist/hooks/dispatch.js +479 -241
  52. package/dist/install/install.mjs +4 -1
  53. package/dist/mcp/registry-manifest.json +2 -2
  54. package/dist/mcp/server.json +2 -2
  55. package/dist/mcp/server.mjs +313 -63
  56. package/dist/scripts/ai_council/content_ceiling.js +63 -0
  57. package/dist/scripts/ai_council/seat_policy.js +106 -0
  58. package/dist/scripts/ai_council/transport_resolver.js +21 -0
  59. package/llms.txt +14 -14
  60. package/package.json +1 -1
  61. package/src/config/gate-violation-baselines.json +3 -3
  62. package/src/config/release-gate-locality.yml +4 -3
  63. package/src/scripts/_lib/blocked_by_marker.ts +189 -0
  64. package/src/scripts/_lib/host_capability.ts +38 -1
  65. package/src/scripts/_lib/release_highlights.ts +19 -211
  66. package/src/scripts/_lib/release_material.ts +27 -77
  67. package/src/scripts/_lib/structured_ask.ts +117 -0
  68. package/src/scripts/_lib/tty_prompt.ts +76 -0
  69. package/src/scripts/ai_council/api_transport.ts +163 -0
  70. package/src/scripts/ai_council/clients.ts +58 -63
  71. package/src/scripts/ai_council/config.ts +13 -0
  72. package/src/scripts/ai_council/content_ceiling.ts +79 -0
  73. package/src/scripts/ai_council/jury_aggregate.ts +178 -0
  74. package/src/scripts/ai_council/seat_policy.ts +137 -0
  75. package/src/scripts/ai_council/status_surface.ts +79 -0
  76. package/src/scripts/ai_council/transport_resolver.ts +59 -1
  77. package/src/scripts/ai_tells_rules.ts +446 -5
  78. package/src/scripts/ask_block_census.ts +499 -0
  79. package/src/scripts/bench_humanizer_eval.ts +264 -40
  80. package/src/scripts/bench_prose_tells_fp.ts +198 -0
  81. package/src/scripts/check_branch_work_committed.ts +234 -0
  82. package/src/scripts/check_pack_size.ts +1 -1
  83. package/src/scripts/check_release_highlights.ts +0 -157
  84. package/src/scripts/council_cli.ts +18 -27
  85. package/src/scripts/detect_ai_tells.ts +142 -20
  86. package/src/scripts/harvest_reference_tokens.ts +698 -0
  87. package/src/scripts/hook_manifest.json +1 -1
  88. package/src/scripts/hook_manifest.yaml +31 -1
  89. package/src/scripts/hooks/concern_registry.ts +2 -0
  90. package/src/scripts/hooks/delegation_nudge_hook.ts +45 -1
  91. package/src/scripts/hooks/one_question_per_ask_hook.ts +191 -0
  92. package/src/scripts/install-hooks.sh +52 -0
  93. package/src/scripts/lint_roadmap_blockers.ts +51 -1
  94. package/src/scripts/migrate_command_suggestions.ts +1 -1
  95. package/src/scripts/probe_unblocked_ask.ts +135 -2
  96. package/src/scripts/release.ts +26 -71
  97. package/src/scripts/release_drill.ts +6 -10
  98. package/src/scripts/release_env.ts +1 -0
  99. package/src/scripts/release_publication.ts +34 -29
  100. package/src/scripts/self_review_gate.ts +409 -15
@@ -1,13 +1,20 @@
1
1
  ---
2
2
  model_tier: high
3
- name: analyze-reference-repo
3
+ name: analyze-repo
4
4
  pack: analysis-workbench
5
5
  visibility: internal
6
- sub: reference-repo
6
+ sub: repo
7
7
  cluster: analyze
8
+ replaces: [analyze-reference-repo, analyze:reference-repo]
8
9
  skills: [project-analyzer, learning-to-rule-or-skill]
9
10
  description: Analyze an external reference repository (competitor, inspiration, peer) and produce a structured comparison + adoption plan for this project.
10
- argument-hint: "<repo-url | owner/repo | archive-url> [--focus=<area>] [--deep] [--no-roadmap]"
11
+ argument-hint: "<repo-url|owner/repo|archive> [--mode=plan|execute] [--loops=N] [--focus=<area>] [--deep] [--refresh] [--no-roadmap]"
12
+ limits:
13
+ mode_default: plan
14
+ max_iterations: 3
15
+ hard_ceiling: 5
16
+ no_gain_stop: 2
17
+ target_metric: required
11
18
  suggestion:
12
19
  eligible: false
13
20
  rationale: "Cluster sub-command — reached via its cluster head's routing or its explicit /cluster:sub name; not independently suggested (surface-consolidation)."
@@ -17,7 +24,7 @@ packs:
17
24
  - meta
18
25
  ---
19
26
 
20
- # analyze-reference-repo
27
+ # analyze-repo
21
28
 
22
29
  Analyze a **different** repository (a competitor, a reference implementation, or
23
30
  a project the user admires) and produce a structured document that anchors on
@@ -35,26 +42,83 @@ The user provides a repository URL — a full GitHub URL
35
42
 
36
43
  Optional arguments:
37
44
 
45
+ - `--mode=plan|execute` — `plan` is the **default** (§ Enforced limits).
46
+ - `--loops=N` — refinement-loop budget. **Default: 3**; hard ceiling 5.
38
47
  - `--focus=<area>` — restrict analysis to one axis (e.g. `installer`,
39
48
  `skills`, `mcp`, `governance`, `ci`). Default: full-surface.
49
+ - `--refresh` — re-resolve the reference's head revision (§ 2a). Without it a
50
+ re-run reads the revision already pinned in the local manifest.
40
51
  - `--deep` — bounded deep-verification tier (§ 2b). Read-only clone at a pinned
41
52
  SHA, never executed. Requires a non-empty anchor table.
42
53
  - `--no-roadmap` — skip the roadmap-draft step.
43
54
 
55
+ ## Enforced limits
56
+
57
+ The frontmatter `limits:` block is the machine-readable pin
58
+ (`tests/scripts/analyze_repo_limits.test.ts` fails when flow and pin drift);
59
+ the steps below are the enforcement — each limit is a step the run MUST
60
+ execute, not advice.
61
+
62
+ ### Execution mode — plan-only default (`mode_default: plan`)
63
+
64
+ `--mode=plan` is the **default**: run §§ 1-6 — pin, fetch, extract, probe,
65
+ compare, classify, converge, write the local artifacts — then present the
66
+ result and STOP. No roadmap landing, no ledger rows, no tracked write of any
67
+ kind. `--mode=execute` must be **explicitly present in the invocation** to
68
+ reach §§ 7-8; treat its absence as plan mode even when conversation momentum
69
+ suggests otherwise. Execute mode does not remove the per-write confirmations in
70
+ §§ 7-8 — it only makes them reachable.
71
+
72
+ ### Pre-registered target metric — required before loop 1 (`target_metric: required`)
73
+
74
+ Before loop 1 may run, the analysis document MUST carry a `Target metric` line
75
+ naming the metric of § 5c, its **measured baseline** taken from the seed pass,
76
+ and the predicted direction. No baseline → REFUSE to enter loop 1 with:
77
+ `target metric not pre-registered — record the seed-pass baseline first`. The
78
+ metric named before loop 1 is the metric every loop is scored against; loops
79
+ never move the goalposts.
80
+
81
+ ### Loop budget (`max_iterations: 3`, `hard_ceiling: 5`)
82
+
83
+ `--loops=N` caps the refinement loops. **Default: 3** — one loop per lens
84
+ (§ 5b), which is what makes three the budget rather than a round number.
85
+ Hard ceiling: 5 — a larger `--loops` value is clamped to 5 with a warning.
86
+
87
+ **Halt-on-spin tripwire (`no_gain_stop: 2`), checked after every loop and
88
+ overriding the budget:**
89
+
90
+ - **Two consecutive zero-delta loops → STOP** before the next lens runs, and
91
+ say which two loops produced no delta and on which metric. Spinning without
92
+ gain is the failure the metric exists to catch.
93
+ - A verdict table still contested at the ceiling stops the run with a
94
+ maintainer question (§ 5b) — never silently.
95
+ - A single zero-delta loop **never** cancels the remaining lenses. It is a
96
+ signal about that lens, not a prediction about the next one.
97
+
98
+ ### Read ceiling per loop
99
+
100
+ Loop *n* cannot read deeper than the seed pass without a local clone, so
101
+ `--deep` (§ 2b) becomes the **default whenever the loop runs**. The three-part
102
+ read ceiling of § 2b applies per loop, and the loop that hits it logs one
103
+ read-ceiling line naming the bound that fired.
104
+
44
105
  ## Steps
45
106
 
46
- ### 1. Confirm scope
107
+ ### 1. Resolve scope from the invocation — do not ask
47
108
 
48
- Before touching anything, ask:
109
+ Scope comes from the arguments, never from a prompt. A bare repository argument
110
+ means **full scope**; `--focus=<area>` means focused. **Ask nothing before the
111
+ first fetch.** The four-option menu this step used to open with cost one prompt
112
+ per repository in a batch, which is a prompt the invocation had already
113
+ answered.
49
114
 
50
- > Found reference: `<owner/repo>`.
51
- >
52
- > 1. Full comparison — all axes (default)
53
- > 2. Focused — one axis (I'll ask which)
54
- > 3. Quick scan — README + top-level layout only
55
- > 4. Cancel
115
+ The one question that survives is an **unresolvable repository identity** — the
116
+ argument matches no repository, or matches more than one. That is a genuine
117
+ ambiguity the invocation did not settle, and it halts before any fetch.
56
118
 
57
- Wait for the user's choice.
119
+ Everything the menu's "Cancel" option protected is protected elsewhere: the
120
+ write-acts of §§ 7-8 keep their own confirmations, and plan mode (§ Enforced
121
+ limits) is the default, so a run that is never confirmed writes nothing tracked.
58
122
 
59
123
  ### 1b. Anchor table first
60
124
 
@@ -81,6 +145,26 @@ Use `web-fetch` for rendered files, GitHub REST (`/repos/{o}/{r}/contents/{p}`)
81
145
  for listings. **Max 40 fetches** — if more is needed, ask which subtree to
82
146
  expand.
83
147
 
148
+ ### 2a. Pin the upstream revision — once, before any reasoning
149
+
150
+ The **seed pass** resolves the reference's head revision exactly once and
151
+ records it in the local manifest (§ 6). Every loop of § 5b reads **that same
152
+ revision**. Only `--refresh` re-resolves it.
153
+
154
+ Why once: a loop that re-resolves is comparing two different repositories and
155
+ calling the difference a finding. Convergence over a moving target is not
156
+ convergence, and a delta produced by an upstream commit that landed between
157
+ loop 1 and loop 2 is upstream's news, not this analysis's.
158
+
159
+ Record in the iteration record, once per pass: `revision: <sha>` — the **same**
160
+ value on every pass of a run. A pass whose recorded revision differs from the
161
+ seed pass's is a defect in the run, not a finding about the reference.
162
+
163
+ Because loop *n* cannot read deeper than the seed pass without a local clone,
164
+ `--deep` (§ 2b) is the default whenever the loop runs. Each loop that hits the
165
+ § 2b three-part read ceiling logs **one** read-ceiling line naming the bound
166
+ that fired and the loop it fired in.
167
+
84
168
  ### 2b. Deep verification tier — `--deep`, opt-in
85
169
 
86
170
  Forty top-level fetches cannot reach a fact buried in an implementation file, so
@@ -179,38 +263,111 @@ mentions a ledger word — a check that mostly fires wrongly gets waved through.
179
263
  A **checklist obligation**, not a CI gate: `check_claims` guards the ledger's
180
264
  integrity, never a proposal against it.
181
265
 
182
- ### 5b. Converge the verdict table
266
+ ### 5b. Three loops, three different questions
267
+
268
+ One pass is a draft, not an analysis — but three passes asking the same
269
+ question are three rewordings, which costs three times the fetches and produces
270
+ prose churn. So the loops are **not** repetitions of one critique. Each has its
271
+ own lens, and the lens is what makes the loop worth its cost:
272
+
273
+ | Loop | Lens | The question it asks, and only it |
274
+ |---|---|---|
275
+ | 1 | **Coverage** | What was missed? What was wrongly marked absent? Which rows rest on a weak anchor — no `file:line`, or one that no longer resolves? |
276
+ | 2 | **Adversary** | Was the *form* copied instead of the principle? Is this only *different* rather than *better*? Does this package already solve it elsewhere? What does it cost in tokens, surface and maintenance? |
277
+ | 3 | **Convergence** | Resolve contradictions between the first two. Fold duplicates. Cut the speculative. Bind every remaining line to evidence on **both** sides. |
278
+
279
+ Each loop takes as input **both** the previous analysis **and** the previous
280
+ roadmap draft — a finding that changed the analysis but not the roadmap is a
281
+ finding the run has not finished acting on.
282
+
283
+ Each loop appends its own **delta block** to `## Iteration record`, naming its
284
+ lens, with one row per change and a reason per row:
285
+
286
+ ```markdown
287
+ ### Loop {n} — {Coverage | Adversary | Convergence} · revision: {sha}
288
+
289
+ | Change | Row | From → To | Reason |
290
+ |---|---|---|---|
291
+ | added / removed / flipped / folded | … | … | … |
292
+ ```
183
293
 
184
- One pass is a draft, not an analysis. Critique the verdict table at least
185
- **twice**: pass 2 applies solution-minimalism and the § 5 bound-claim gate to
186
- pass 1's ADOPT rows, using the § 3b probe findings as input. Record every flip
187
- with its reason in `## Iteration record`. **DONE** = a pass produces **zero**
188
- verdict changes. Cap at four passes; a table still flipping at four is itself
189
- the finding — mark it `contested — needs maintainer judgement`, never stop
294
+ **A loop whose delta block has no added, removed, flipped or folded entry is
295
+ recorded as a zero-delta loop, never omitted.** An omitted block is
296
+ indistinguishable from a loop that never ran, and the halt rule below counts
297
+ zero-delta loops — so omitting one silently disarms the tripwire.
298
+
299
+ A verdict table still contested at the ceiling is itself the finding — mark it
300
+ `contested — needs maintainer judgement` and stop with the question, never
190
301
  silently.
191
302
 
303
+ ### 5c. The target metric is a decision-quality measure
304
+
305
+ The metric is:
306
+
307
+ > the count of ADOPT/ADAPT rows carrying a concrete `file:line` on **both** the
308
+ > reference side and this package's side.
309
+
310
+ Not the number of rows, not the length of the document, not the count of
311
+ findings. An output-volume metric rewards a loop for saying more, which is
312
+ precisely the churn the three lenses exist to prevent; this metric only moves
313
+ when a verdict became *decidable* — someone can now go and look at both ends.
314
+
315
+ Its baseline is measured on the seed pass and pre-registered before loop 1
316
+ (§ Enforced limits). The halt rules that read it:
317
+
318
+ - **Two consecutive zero-delta loops → STOP** before the next lens runs, naming
319
+ the two loops and the metric. Spin, not convergence.
320
+ - **A single zero-delta loop never cancels the remaining lenses.** Loop 1
321
+ finding nothing to add on Coverage says nothing about whether the Adversary
322
+ lens will find something to remove — the lenses ask different questions, so
323
+ one lens's silence is not evidence about the next.
324
+ - A contested table stops the run with a maintainer question (§ 5b).
325
+
192
326
  A contested table is a **published finding, not an adoption proposal**: the
193
327
  reference surface holds elements this repo cannot mechanically classify, and no
194
328
  automation converts that into an ADOPT decision. Convergence is an analyst
195
329
  obligation with a recorded trail — **never an LLM-as-judge gate**, never a
196
330
  script.
197
331
 
198
- ### 6. Write the analysis document
332
+ ### 6. Write the analysis document — under the opaque id, in the local area
333
+
334
+ **Target: `agents/.harvest-local/repo/<opaque-id>/analysis.md`.** Every pass and
335
+ loop artifact of a run lives under that one directory, and the run writes
336
+ nothing under `agents/evidence/analysis/`.
337
+
338
+ The old target was `agents/evidence/analysis/compare-<slug>.md` with
339
+ `<slug>` = `<owner>-<repo>`, which put the reference's identity into a path.
340
+ `.gitignore` covers `compare-*.md` under the evidence directory but nothing
341
+ else there, so any other filename in that directory would have been unprotected
342
+ by construction — the protection was a glob, not a boundary.
343
+ `agents/.harvest-local/` is a whole gitignored directory, so the boundary is the
344
+ directory rather than a pattern one rename defeats.
345
+
346
+ **The opaque id.** Derived by
347
+ `./scripts-run src/scripts/harvest_reference_tokens` from the canonical
348
+ repository identity **and** the pinned revision of § 2a: `sha256(identity +
349
+ "@" + revision)`, first 16 hex characters. Two consequences that are the point
350
+ of including the revision: the id is **stable** across two runs at the same
351
+ revision, so a resumed or repeated run lands in the same directory; and it
352
+ **differs** across revisions, so one repository at two historical pins is two
353
+ pieces of evidence rather than one overwriting the other.
354
+
355
+ **The plaintext lives in exactly one place** — `identity` in the local
356
+ manifest, `agents/.harvest-local/manifest.jsonl`, inside the same gitignored
357
+ directory. Nothing else in the run resolves an opaque id back to a name.
199
358
 
200
- Target: `agents/evidence/analysis/compare-<slug>.md` (create the directory if
201
- missing, with `.gitkeep` — same convention as `project-analyzer`). Slug rule:
202
- `<owner>-<repo>` lowercased, non-alphanumeric → `-`, collapse runs. Structure:
359
+ Structure:
203
360
 
204
361
  ```markdown
205
362
  # Reference analysis: {owner}/{repo}
206
363
 
207
364
  > One-sentence framing of why this reference matters.
208
365
 
209
- - **Source:** https://github.com/{owner}/{repo}
366
+ - **Source:** `opaque:{opaque-id}` — resolvable only via the local manifest
210
367
  - **Fetched commit:** {sha} ({date})
211
368
  - **Own-tree SHA:** {sha}
212
369
  - **Focus:** {full | area} · **Depth:** {surface | deep}
213
- - **Analyst:** agent via `/analyze-reference-repo`
370
+ - **Analyst:** agent via `/analyze-repo`
214
371
 
215
372
  ## Anchor table
216
373
 
@@ -231,9 +388,31 @@ missing, with `.gitkeep` — same convention as `project-analyzer`). Slug rule:
231
388
  | Artifact | Our consumer (file:line) | Discovered? | Validates? | Exact failing axes or error |
232
389
  |---|---|---|---|---|
233
390
 
391
+ ## Target metric
392
+
393
+ - **Metric:** ADOPT/ADAPT rows with a `file:line` on both sides (§ 5c)
394
+ - **Seed-pass baseline:** {n} · **Predicted direction:** up
395
+
234
396
  ## Iteration record
235
397
 
236
- | Pass | Row | From → To | Reason |
398
+ `revision: {sha}` — the § 2a pin, identical on every pass below.
399
+
400
+ One delta block per loop, in order, each naming its lens. A zero-delta loop
401
+ keeps its block and records the zero (§ 5b).
402
+
403
+ ### Loop 1 — Coverage · revision: {sha}
404
+
405
+ | Change | Row | From → To | Reason |
406
+ |---|---|---|---|
407
+
408
+ ### Loop 2 — Adversary · revision: {sha}
409
+
410
+ | Change | Row | From → To | Reason |
411
+ |---|---|---|---|
412
+
413
+ ### Loop 3 — Convergence · revision: {sha}
414
+
415
+ | Change | Row | From → To | Reason |
237
416
  |---|---|---|---|
238
417
 
239
418
  ## Findings
@@ -270,6 +449,9 @@ omit the section entirely when every row extends something that exists.}
270
449
  does not fit — a seed that skipped this line is not ready to hand over}
271
450
 
272
451
  ## Open questions for the maintainer
452
+ {Each line is a question to ask the maintainer directly, one at a time, when
453
+ this report is handed over — the section records what is owed, it does not
454
+ discharge it.}
273
455
  ```
274
456
 
275
457
  The `## Seeds` section is the handoff shape
@@ -282,19 +464,52 @@ it makes the four-surface overlap scan that
282
464
  requires visible at handoff time, when the analysis is still open, instead of
283
465
  re-derived later by whoever picks the seed up.
284
466
 
285
- ### 7. Offer next steps
467
+ ### 7. Offer next steps — execute mode only
286
468
 
287
- After writing the file, present:
469
+ **Plan mode stops here** (§ Enforced limits). `--mode=execute` makes this step
470
+ reachable; it does not make it automatic.
288
471
 
289
- > Analysis written to `agents/evidence/analysis/compare-{slug}.md`.
472
+ > Analysis written to `agents/.harvest-local/repo/{opaque-id}/analysis.md`.
290
473
  >
291
- > 1. Draft roadmap from ADOPT/ADAPT — `agents/roadmaps/adopt-{slug}.md`
474
+ > 1. Draft roadmap from ADOPT/ADAPT — `agents/roadmaps/road-to-{defect}.md`
292
475
  > 2. Merge findings into an existing roadmap — say which
293
476
  > 3. Stop here
294
477
  > 4. Deep-dive on one axis — say which
295
478
 
296
479
  Never create the roadmap without explicit confirmation.
297
480
 
481
+ #### The landed roadmap is named after the defect, never after the source
482
+
483
+ A tracked filename is a published string. `adopt-{owner}-{repo}.md` publishes
484
+ the reference's identity in the one surface no `.gitignore` can retract, and it
485
+ also names the wrong thing: the roadmap exists because **this package has a
486
+ gap**, not because some other project exists.
487
+
488
+ - **Filename:** derived from the capability gap —
489
+ `agents/roadmaps/road-to-<the-thing-we-lack>.md`. It contains neither the
490
+ owner nor the repository name. If the only name you can think of is the
491
+ reference's, the finding is not yet understood well enough to land.
492
+ - **Header:** carries a provenance block with an **encrypted token**
493
+ (`ENC1:` via `src/scripts/_lib/link_crypto.ts`), never the plaintext URL —
494
+ the form
495
+ [`source-confidentiality`](../../../../rules/source-confidentiality.md)
496
+ requires of a tracked roadmap that cites a source. Sources are referenced as
497
+ *Source A / B / C* in the prose.
498
+ - **Verified by:** `./scripts-run src/scripts/check_no_external_sources`, which
499
+ is the deterministic backstop rather than the discipline itself.
500
+
501
+ #### Never hand a subagent a plaintext URL
502
+
503
+ Under the harvester (`/analyze:roadmap-repos`) the orchestrator passes the
504
+ subagent **the opaque id and nothing else**. The subagent reads the URL from the
505
+ local manifest itself, so the plaintext never appears in a dispatch argument.
506
+
507
+ The cost is one indirection, and it is taken **on precaution**: whether a given
508
+ host retains a subagent's arguments in a transcript or audit log is
509
+ host-dependent and was not verifiable from this tree. That is stated rather than
510
+ asserted away — the indirection is cheap enough not to need a proven threat, and
511
+ claiming a proven one would be a claim this package cannot support.
512
+
298
513
  ### 8. Close the loop — offer the ledger rows
299
514
 
300
515
  **Only after a roadmap draft is accepted** (option 1 or 2 above). This step
@@ -313,7 +528,7 @@ One row per **anchored ADOPT or ADAPT** finding, and nothing else:
313
528
  |---|---|
314
529
  | `harvest_id` | a kebab-case slug for the mechanism |
315
530
  | `stated_in` | the roadmap file the user just accepted |
316
- | `source_ref` | the reference's `<url>@<sha>` — the § 2 pin, already recorded in the document header |
531
+ | `source_ref` | `opaque:<id>` or an `ENC1:` token — never the plaintext URL; the § 2a pin is inside the id |
317
532
  | `evidence_locator` | the reference-side `file:line` from that row of the comparison matrix |
318
533
  | `harvested_at` | today |
319
534
  | `verdict` | `adopt` or `adapt` |
@@ -0,0 +1,129 @@
1
+ ---
2
+ model_tier: medium
3
+ name: analyze-roadmap-repos
4
+ pack: analysis-workbench
5
+ visibility: internal
6
+ sub: roadmap-repos
7
+ cluster: analyze
8
+ type: orchestrator
9
+ replaces: []
10
+ skills: [subagent-orchestration]
11
+ description: Walk the roadmap estate's encrypted reference tokens and feed each unique repository through analyze-repo, one subagent at a time, without producing one roadmap per repository.
12
+ argument-hint: "[--limit=N] [--resume] [--refresh] [--mode=plan|execute]"
13
+ suggestion:
14
+ eligible: false
15
+ rationale: "Cluster sub-command — reached via its cluster head's routing or its explicit /cluster:sub name; not independently suggested (surface-consolidation)."
16
+ workspaces:
17
+ - agent-config-maintainer
18
+ packs:
19
+ - meta
20
+ ---
21
+
22
+ # analyze-roadmap-repos
23
+
24
+ The thin harvester in front of [`analyze-repo`](repo.md). It walks the roadmap
25
+ estate's encrypted reference tokens, resolves each to a repository identity, and
26
+ feeds the unique ones through the analysis command one at a time.
27
+
28
+ **This command contains no analysis instruction and never will.** It resolves,
29
+ dispatches, and folds. Every judgement about a reference — what to fetch, what
30
+ to compare, what to adopt, how to converge — belongs to `analyze-repo`, which
31
+ owns the loop contract and its limits. A second copy of that reasoning here
32
+ would be a second implementation to keep in step with the first, which is the
33
+ condition step 1.1 of its roadmap removed.
34
+
35
+ ## Steps
36
+
37
+ ### 1. Discovery — run the script, read the manifest
38
+
39
+ ```bash
40
+ ./scripts-run src/scripts/harvest_reference_tokens --dry-run # census only
41
+ ./scripts-run src/scripts/harvest_reference_tokens --resume --limit=N # write the manifest
42
+ ```
43
+
44
+ The script is the only discovery mechanism: it extracts the `ENC1:` tokens
45
+ across the five estate levels, decrypts them, classifies each resolved URL,
46
+ canonicalizes the repositories, deduplicates on identity plus pinned revision,
47
+ and writes `agents/.harvest-local/manifest.jsonl`.
48
+
49
+ It **refuses without a link-encryption key** rather than reporting a short
50
+ census — a classification of zero repositories that actually means "nobody could
51
+ look" is the failure mode this whole pass exists to avoid.
52
+
53
+ Read the manifest. Do not re-derive any of it here.
54
+
55
+ ### 2. Dispatch — one subagent per repository, sequential
56
+
57
+ For each manifest entry with status `pending`, in manifest order, up to the
58
+ batch limit:
59
+
60
+ - Spawn **one subagent** and have it run `/analyze:repo` for that entry.
61
+ - Pass the subagent **the opaque id only** — never a resolved URL. The subagent
62
+ reads the URL from `agents/.harvest-local/manifest.jsonl` itself. One
63
+ indirection, taken on precaution (`analyze-repo` § 7).
64
+ - **Sequential, never a fan-out.** Over a hundred identities at four passes each
65
+ cannot share one session, and every external fetch is spent deliberately. The
66
+ manifest is the only shared state between subagents.
67
+ - Write the entry's status back as the run progresses: `running`, then `done` or
68
+ `failed`. A batch interrupted mid-flight resumes from those statuses.
69
+
70
+ Default batch limit is **small**. A harvester that walks the whole estate in one
71
+ invocation spends a hundred repositories' worth of fetches on a decision nobody
72
+ took.
73
+
74
+ ### 3. Ownership fold — one gap, one roadmap
75
+
76
+ After the batch, and never during it, run the fold pass of
77
+ [`analyze-repo`](repo.md) § 7 across the batch's findings as a set. Consult
78
+ `src/scripts/roadmap_context.ts` and the run's own candidate registry, then pick
79
+ exactly one disposition per repository:
80
+
81
+ | Disposition | When |
82
+ |---|---|
83
+ | no action | the finding is REJECT or ALREADY throughout |
84
+ | already planned | an active roadmap already owns the gap |
85
+ | extend an existing roadmap | the gap belongs to an owner that exists |
86
+ | create a follow-up | the gap belongs under an owner but is out of its scope |
87
+ | create new | no owner exists |
88
+ | contested | two owners claim it — stop and ask |
89
+
90
+ **Three repositories showing the same gap strengthen the evidence on one owning
91
+ roadmap. They never create three.** That is the whole reason this command exists
92
+ rather than a loop that invokes `analyze-repo` and keeps whatever it returns.
93
+
94
+ ### 4. Landing — local-only
95
+
96
+ The batch's consolidated result is written to `agents/.harvest-local/` and
97
+ nowhere else. **No per-run consolidate roadmap takes an active top-level estate
98
+ slot** — decided 2026-09-06 under the maintainer's standing delegation, recorded
99
+ in `road-to-bounded-reference-harvest-loop` § Blockers. A recurring process that
100
+ takes a slot per run converts the estate ratchet's allowance into a standing
101
+ exemption, which removes the pressure the ratchet exists to apply.
102
+
103
+ Accepted consequence, stated rather than hidden: **no batch is visible in the
104
+ roadmap dashboard.** Any roadmap the fold pass does land is an ordinary estate
105
+ entry landed for a named capability gap, and is subject to the estate gate like
106
+ any other.
107
+
108
+ ## Safety
109
+
110
+ - Read-only on every reference. The no-execute invariant of `analyze-repo`
111
+ § Safety binds every subagent this command spawns.
112
+ - No plaintext repository URL is ever passed as a dispatch argument.
113
+ - Nothing tracked is written by this command itself.
114
+ - Hard-Floor actions stay this-turn gated. A batch authorizes fetches, never a
115
+ commit, a push or a merge.
116
+
117
+ ## When **not** to use
118
+
119
+ - One known reference → [`analyze-repo`](repo.md) directly. The harvester's only
120
+ job is the estate walk.
121
+ - Analyzing this repository → `/project-analyze`.
122
+ - A dropped local artifact → [`/analyze:inbox`](inbox.md).
123
+
124
+ ## Related
125
+
126
+ - Command: [`analyze-repo`](repo.md) — the analysis engine this dispatches to.
127
+ - Script: `src/scripts/harvest_reference_tokens.ts` — discovery, the only one.
128
+ - Rule: [`source-confidentiality`](../../../../rules/source-confidentiality.md)
129
+ — why the identities stay in the gitignored area.
@@ -2,13 +2,13 @@
2
2
  model_tier: medium
3
3
  name: analyze
4
4
  disable-model-invocation: true
5
- argument-hint: "[postmortem|premortem|decision|near-miss|incident|reference-repo|inbox] [subject]"
5
+ argument-hint: "[postmortem|premortem|decision|near-miss|incident|repo|roadmap-repos|inbox] [subject]"
6
6
  pack: analysis-workbench
7
7
  intent: "Analysis dispatcher — classify input by keywords, propose a weighted framework path, let the user pick"
8
- routes_to: [analyze-postmortem, analyze-premortem, analyze-decision, analyze-near-miss, analyze-incident, analyze-reference-repo, analyze-inbox, analyze-conformance]
8
+ routes_to: [analyze-postmortem, analyze-premortem, analyze-decision, analyze-near-miss, analyze-incident, analyze-repo, analyze-roadmap-repos, analyze-inbox, analyze-conformance]
9
9
  replaces: []
10
10
  visibility: advanced
11
- description: Analysis orchestrator — confidence-weighted suggester that routes to postmortem, premortem, decision-review, near-miss, incident, reference-repo, or inbox-artifact analysis.
11
+ description: Analysis orchestrator — confidence-weighted suggester that routes to postmortem, premortem, decision-review, near-miss, incident, repo, or inbox-artifact analysis.
12
12
  cluster: analyze
13
13
  type: orchestrator
14
14
  suggestion:
@@ -37,7 +37,8 @@ to the chosen sub-command. Never auto-selects silently.
37
37
  | `/analyze:decision` | `analyze/decision/command.md` | Audit a past architectural decision (did it hold?) |
38
38
  | `/analyze:near-miss` | `analyze/near-miss/command.md` | Post-mortem for a near-miss (same flow, lighter severity framing) |
39
39
  | `/analyze:incident` | `analyze/incident/command.md` | Full incident flow: commander → RCA → post-mortem → memory candidate |
40
- | `/analyze:reference-repo` | `analyze/reference-repo/command.md` | Deep-dive an external reference repo (competitor, inspiration, peer) → structured comparison + adoption plan |
40
+ | `/analyze:repo` | `analyze/repo/command.md` | Deep-dive an external reference repo (competitor, inspiration, peer) → structured comparison + adoption plan |
41
+ | `/analyze:roadmap-repos` | `analyze/roadmap-repos/command.md` | Walk the estate's encrypted reference tokens and feed each unique repo through `repo`, one subagent at a time |
41
42
  | `/analyze:inbox` | `analyze/inbox/command.md` | Deep-dive a LOCAL artifact dropped in `agents/tmp/` (review, prompt, spec, transcript) → claim verification + step reproduction against the current tree + artefact mapping + roadmap |
42
43
  | `/analyze:conformance` | `analyze/conformance/command.md` | Audit recent local sessions for rule violations → deterministic scan + subagent passes, root-caused per class, and a roadmap for what is mechanisable |
43
44
 
@@ -63,7 +64,7 @@ match:
63
64
  | "pre-mortem", "what could go wrong", "imagine failure", "vor dem Start" | `premortem` |
64
65
  | "decision review", "ADR", "did this hold up", "rückblick Architektur" | `decision` |
65
66
  | "production is down", "active incident", "Vorfall", "Prod ist down" | `incident` |
66
- | external repo URL / `owner/repo`, "how does X do this", "compare with that repo", "competitor" | `reference-repo` |
67
+ | external repo URL / `owner/repo`, "how does X do this", "compare with that repo", "competitor" | `repo` |
67
68
 
68
69
  Assign a confidence level (high / medium / low) per framework based on
69
70
  signal count. A framework with zero signals gets `low`.
@@ -81,7 +82,7 @@ escape:
81
82
  > 3. [low] Pre-mortem (`/analyze:premortem`) — imagined-failure analysis before committing
82
83
  > 4. [low] Decision review (`/analyze:decision`) — did a past architectural decision hold up?
83
84
  > 5. [low] Incident (`/analyze:incident`) — full live-incident coordination + RCA + post-mortem
84
- > 6. [low] Reference repo (`/analyze:reference-repo`) — deep-dive an external repo → comparison + adoption plan
85
+ > 6. [low] Reference repo (`/analyze:repo`) — deep-dive an external repo → comparison + adoption plan
85
86
  > 7. Describe in your own words — I'll re-classify
86
87
 
87
88
  **Empfehlung:** 1
@@ -113,7 +114,11 @@ and ask which one was intended. One question, no guessing.
113
114
  this turn.
114
115
  - **Do NOT commit, push, or open a PR** unless a sub-command
115
116
  explicitly authorizes it.
116
- - **Do NOT chain sub-commands.** One `/analyze <sub>` per turn.
117
+ - **Do NOT chain sub-commands.** One `/analyze <sub>` per turn. **Exactly one
118
+ exception:** `roadmap-repos` invokes `repo` once per repository, each in its
119
+ own subagent, sequentially — never in the orchestrator's own turn and never as
120
+ a fan-out. It is the only sub-command permitted to invoke another, and it may
121
+ invoke only `repo`.
117
122
  - **Memory loop applies** — every sub-command that produces an
118
123
  analysis output MUST draft a memory candidate via
119
124
  `/memory propose` per