@event4u/agent-config 9.7.0 → 9.8.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 (185) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +144 -0
  3. package/README.md +5 -5
  4. package/dist/agent-src/commands/commit/in-chunks.md +8 -0
  5. package/dist/agent-src/commands/commit.md +17 -0
  6. package/dist/agent-src/commands/pr/create.md +4 -0
  7. package/dist/agent-src/contexts/override-system.md +75 -5
  8. package/dist/agent-src/rules/context-hygiene.md +2 -0
  9. package/dist/agent-src/rules/doc-screenshot-hygiene.md +97 -0
  10. package/dist/agent-src/rules/domain-safety-pii.md +1 -0
  11. package/dist/agent-src/rules/external-code-graph-interop.md +13 -3
  12. package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +2 -0
  13. package/dist/agent-src/rules/git-history-discipline.md +2 -0
  14. package/dist/agent-src/rules/language-and-tone.md +2 -0
  15. package/dist/agent-src/rules/lethal-trifecta-guard.md +3 -0
  16. package/dist/agent-src/rules/media-governance-routing.md +2 -0
  17. package/dist/agent-src/rules/minimal-safe-diff.md +2 -0
  18. package/dist/agent-src/rules/no-roadmap-references.md +3 -0
  19. package/dist/agent-src/rules/non-destructive-by-default.md +20 -0
  20. package/dist/agent-src/rules/onboarding-gate.md +2 -0
  21. package/dist/agent-src/rules/output-discipline.md +2 -0
  22. package/dist/agent-src/rules/persona-governance.md +2 -0
  23. package/dist/agent-src/rules/preservation-guard.md +3 -0
  24. package/dist/agent-src/rules/roadmap-progress-sync.md +2 -0
  25. package/dist/agent-src/rules/secret-vcs-guard.md +106 -0
  26. package/dist/agent-src/rules/security-sensitive-stop.md +1 -1
  27. package/dist/agent-src/rules/skill-quality.md +2 -0
  28. package/dist/agent-src/rules/source-confidentiality.md +2 -0
  29. package/dist/agent-src/rules/source-of-truth.md +2 -0
  30. package/dist/agent-src/rules/telegraph-speak.md +2 -0
  31. package/dist/agent-src/rules/token-optimizer-maintenance.md +2 -0
  32. package/dist/agent-src/rules/tool-safety.md +1 -0
  33. package/dist/agent-src/rules/verify-before-complete.md +2 -0
  34. package/dist/agent-src/skills/adr-create/SKILL.md +17 -1
  35. package/dist/agent-src/skills/code-intelligence/SKILL.md +94 -0
  36. package/dist/agent-src/skills/gated-reach/SKILL.md +185 -0
  37. package/dist/agent-src/skills/gated-reach/evals/triggers.json +72 -0
  38. package/dist/agent-src/skills/image-analyser/SKILL.md +14 -12
  39. package/dist/agent-src/skills/image-editing/SKILL.md +1 -0
  40. package/dist/agent-src/skills/readme-writing/SKILL.md +6 -1
  41. package/dist/agent-src/skills/screenshot-hygiene/SKILL.md +171 -0
  42. package/dist/agent-src/skills/secrets-management/SKILL.md +44 -1
  43. package/dist/agent-src/skills/subagent-orchestration/prompts/adversarial-verification-council.md +29 -0
  44. package/dist/agent-src/skills/subagent-orchestration/prompts/do-and-judge-two-stage.md +29 -0
  45. package/dist/agent-src/skills/subagent-orchestration/prompts/do-and-judge.md +29 -0
  46. package/dist/agent-src/skills/subagent-orchestration/prompts/do-competitively.md +29 -0
  47. package/dist/agent-src/skills/subagent-orchestration/prompts/do-in-parallel.md +29 -0
  48. package/dist/agent-src/skills/subagent-orchestration/prompts/do-in-steps.md +29 -0
  49. package/dist/agent-src/skills/subagent-orchestration/prompts/do-in-worktrees.md +29 -0
  50. package/dist/agent-src/skills/subagent-orchestration/prompts/judge-with-debate.md +29 -0
  51. package/dist/agent-src/skills/verify-repair-loop/SKILL.md +4 -0
  52. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  53. package/dist/agent-src/templates/github-workflows/secret-scan.yml +65 -0
  54. package/dist/cli/configRoot.js +112 -0
  55. package/dist/cli/configRoot.js.map +1 -0
  56. package/dist/cli/configRoot.test.js +97 -0
  57. package/dist/cli/configRoot.test.js.map +1 -0
  58. package/dist/cli/help.js +4 -1
  59. package/dist/cli/help.js.map +1 -1
  60. package/dist/cli/main.js +19 -2
  61. package/dist/cli/main.js.map +1 -1
  62. package/dist/cli/registry.js +1 -0
  63. package/dist/cli/registry.js.map +1 -1
  64. package/dist/discovery/deprecation-report.md +1 -1
  65. package/dist/discovery/discovery-manifest.json +161 -44
  66. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  67. package/dist/discovery/discovery-manifest.summary.md +4 -4
  68. package/dist/discovery/orphan-report.md +1 -1
  69. package/dist/discovery/packs.json +13 -8
  70. package/dist/discovery/trust-report.md +11 -11
  71. package/dist/discovery/workspaces.json +11 -6
  72. package/dist/install/install.mjs +16 -0
  73. package/dist/mcp/registry-manifest.json +3 -3
  74. package/dist/router.json +1 -1
  75. package/dist/server/app.js +10 -0
  76. package/dist/server/app.js.map +1 -1
  77. package/dist/server/routes/ping.js +18 -0
  78. package/dist/server/routes/ping.js.map +1 -1
  79. package/dist/server/schemas/settings.js +8 -0
  80. package/dist/server/schemas/settings.js.map +1 -1
  81. package/dist/server/serverInfo.js +6 -2
  82. package/dist/server/serverInfo.js.map +1 -1
  83. package/dist/server/token.js +11 -4
  84. package/dist/server/token.js.map +1 -1
  85. package/dist/server/writeRoot.js +15 -1
  86. package/dist/server/writeRoot.js.map +1 -1
  87. package/dist/shared/capabilities.js +33 -0
  88. package/dist/shared/capabilities.js.map +1 -0
  89. package/dist/shared/capabilities.test.js +39 -0
  90. package/dist/shared/capabilities.test.js.map +1 -0
  91. package/dist/ui/assets/{index-BiEZiZ31.js → index-CrmZ34Rg.js} +16 -16
  92. package/dist/ui/assets/index-CrmZ34Rg.js.map +1 -0
  93. package/dist/ui/index.html +14 -5
  94. package/docs/CLAIMS.md +62 -37
  95. package/docs/architecture.md +2 -2
  96. package/docs/benchmark.md +137 -0
  97. package/docs/catalog.md +8 -3
  98. package/docs/comparison.yaml +44 -2
  99. package/docs/contracts/local-server-ports.md +53 -0
  100. package/docs/contracts/no-runtime-boundary.md +1 -1
  101. package/docs/contracts/subagent-boundary.md +15 -0
  102. package/docs/customization.md +14 -3
  103. package/docs/decisions/ADR-016-installer-architecture.md +2 -0
  104. package/docs/decisions/ADR-088-no-external-runtime-federation.md +1 -1
  105. package/docs/decisions/ADR-094-agent-memory-layer-removal.md +1 -1
  106. package/docs/decisions/ADR-109-subagent-v1-contract.md +2 -0
  107. package/docs/decisions/ADR-110-discipline-profile-resolution-locus.md +2 -0
  108. package/docs/decisions/ADR-113-ci-native-release-label-trigger.md +11 -3
  109. package/docs/decisions/ADR-124-embedded-engine-doctrine.md +255 -0
  110. package/docs/decisions/ADR-125-doc-screenshot-anonymization.md +131 -0
  111. package/docs/decisions/ADR-126-internet-reach-operator-tooling.md +254 -0
  112. package/docs/decisions/ADR-127-enforcement-claims-must-resolve.md +150 -0
  113. package/docs/decisions/ADR-128-executable-evidence-and-measured-escalation.md +201 -0
  114. package/docs/decisions/INDEX.md +21 -0
  115. package/docs/decisions/engine-reclassification-2026-07.md +104 -0
  116. package/docs/distribution/awesome-list-submission.md +1 -1
  117. package/docs/distribution/registries.md +36 -27
  118. package/docs/enforcement-by-host.md +7 -0
  119. package/docs/featured-skills.md +2 -2
  120. package/docs/getting-started-by-role.md +1 -1
  121. package/docs/getting-started.md +1 -1
  122. package/docs/governance-advantage.md +1 -1
  123. package/docs/guides/gated-platform-reads.md +221 -0
  124. package/docs/positioning-evidence.md +1 -1
  125. package/docs/proof.md +92 -16
  126. package/docs/threat-model.md +1 -0
  127. package/package.json +5 -2
  128. package/src/config/agent-settings.template.yml +43 -0
  129. package/src/config/reach-channels.yml +217 -0
  130. package/src/config/reach-prescriptions-intake.yml +200 -0
  131. package/src/scripts/_dispatch.bash +15 -0
  132. package/src/scripts/_lib/exec_evidence.ts +251 -0
  133. package/src/scripts/_lib/fixtures/secret-detector/negatives.txt +10 -0
  134. package/src/scripts/_lib/fixtures/secret-detector/positives.txt +11 -0
  135. package/src/scripts/_lib/kernel_rules.ts +46 -0
  136. package/src/scripts/_lib/reddit_thread_parse.ts +598 -0
  137. package/src/scripts/_lib/risk_paths.ts +160 -0
  138. package/src/scripts/_lib/secret_detector.test.ts +103 -0
  139. package/src/scripts/_lib/secret_detector.ts +319 -0
  140. package/src/scripts/_lib/tool_probe.ts +359 -0
  141. package/src/scripts/adr/regenerate_index.ts +81 -6
  142. package/src/scripts/audit_adr_coverage.ts +33 -0
  143. package/src/scripts/build_proof.ts +162 -0
  144. package/src/scripts/check_adr_frontmatter.ts +195 -0
  145. package/src/scripts/check_artefact_count_messaging.ts +4 -0
  146. package/src/scripts/check_backstop_debt.ts +200 -0
  147. package/src/scripts/check_claims.ts +188 -8
  148. package/src/scripts/check_comparison.ts +12 -0
  149. package/src/scripts/check_enforcement_coverage.ts +592 -0
  150. package/src/scripts/check_kernel_rule_bundle.ts +16 -12
  151. package/src/scripts/check_reach_channels.ts +407 -0
  152. package/src/scripts/check_reach_staleness.ts +364 -0
  153. package/src/scripts/check_secret_leak.test.ts +47 -0
  154. package/src/scripts/check_secret_leak.ts +290 -0
  155. package/src/scripts/code_graph/build.ts +0 -0
  156. package/src/scripts/code_graph/cli.ts +207 -0
  157. package/src/scripts/code_graph/detect.ts +134 -0
  158. package/src/scripts/code_graph/extract.ts +386 -0
  159. package/src/scripts/code_graph/loader.ts +123 -0
  160. package/src/scripts/code_graph/query.ts +176 -0
  161. package/src/scripts/code_graph/sanitize.ts +30 -0
  162. package/src/scripts/code_graph/types.ts +83 -0
  163. package/src/scripts/code_graph/validate.ts +63 -0
  164. package/src/scripts/external_sources_denylist.json +3 -1
  165. package/src/scripts/generate_subagent_floor.ts +194 -0
  166. package/src/scripts/hook_manifest.yaml +13 -3
  167. package/src/scripts/hooks/code_graph_nudge_hook.ts +184 -0
  168. package/src/scripts/iron_law_sha.ts +3 -12
  169. package/src/scripts/lint_override_kernel_guard.ts +219 -0
  170. package/src/scripts/measure_rule_budget.ts +3 -12
  171. package/src/scripts/postinstall_gui.ts +129 -0
  172. package/src/scripts/reach_doctor.ts +1651 -0
  173. package/src/scripts/release.ts +24 -3
  174. package/src/scripts/risk_escalation_shadow.ts +160 -0
  175. package/src/scripts/schemas/agent-settings.schema.json +23 -0
  176. package/src/scripts/schemas/reach-channels.schema.json +134 -0
  177. package/src/scripts/schemas/reach-doctor-payload.schema.json +220 -0
  178. package/src/scripts/schemas/rule.schema.json +10 -0
  179. package/src/scripts/skill_linter.ts +55 -0
  180. package/src/scripts/validate_reach_prescriptions.ts +751 -0
  181. package/src/server/schemas/settings.ts +16 -0
  182. package/src/shared/capabilities.test.ts +43 -0
  183. package/src/shared/capabilities.ts +75 -0
  184. package/src/templates/minimal/agents-overrides-readme.md +20 -0
  185. package/dist/ui/assets/index-BiEZiZ31.js.map +0 -1
@@ -8,17 +8,26 @@
8
8
  <script>
9
9
  // Theme boot — set data-theme BEFORE first paint so there is no
10
10
  // flash of the wrong theme (road-to-setup-experience § Phase 4.2).
11
- // Persisted override in localStorage wins; otherwise follow the OS.
11
+ // Precedence: a host-supplied `?theme=light|dark` boot query wins
12
+ // (reciprocal-ecosystem embed contract — the host owns the theme),
13
+ // then a persisted localStorage override, then the OS preference.
12
14
  (function () {
15
+ var query = null;
16
+ try {
17
+ var q = new URLSearchParams(window.location.search).get('theme');
18
+ if (q === 'light' || q === 'dark') query = q;
19
+ } catch (e) { /* older engine */ }
13
20
  var stored = null;
14
21
  try { stored = localStorage.getItem('agent-config-theme'); } catch (e) { /* private mode */ }
15
- var theme = stored === 'light' || stored === 'dark'
16
- ? stored
17
- : (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
22
+ var theme = query
23
+ ? query
24
+ : stored === 'light' || stored === 'dark'
25
+ ? stored
26
+ : (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
18
27
  document.documentElement.setAttribute('data-theme', theme);
19
28
  })();
20
29
  </script>
21
- <script type="module" crossorigin src="/assets/index-BiEZiZ31.js"></script>
30
+ <script type="module" crossorigin src="/assets/index-CrmZ34Rg.js"></script>
22
31
  <link rel="stylesheet" crossorigin href="/assets/index-BPFMZWUs.css">
23
32
  </head>
24
33
  <body>
package/docs/CLAIMS.md CHANGED
@@ -32,11 +32,36 @@
32
32
  - last_verified: <YYYY-MM-DD>
33
33
  ```
34
34
 
35
- **Evidence-pointer grammar (v1):**
35
+ **Evidence-pointer grammar (v2):**
36
36
 
37
37
  - `path/to/file.md` or `path/to/file.md:42` — the repo file exists (line advisory).
38
38
  - `path/to/file.md#substring` — the file exists AND contains `substring`.
39
39
  - `https://… (YYYY-MM-DD)` — external cite carrying a dated stamp (not fetched in CI).
40
+ - `exec:<command> -> <exit-code>` — the command **re-runs** and its exit code
41
+ must match. The only form that can tell a live claim from a stale one.
42
+
43
+ **Why the fourth form exists.** The first three are existence checks. A claim
44
+ reading "the suite is green" whose pointer resolves to a report nobody
45
+ regenerated stays `backed` indefinitely — the pointer resolves, the claim is
46
+ false. `exec:` re-derives the claim and lets the exit code carry the verdict.
47
+
48
+ **Where `exec:` runs, and where it does not.** Re-execution happens in CI only.
49
+ Locally the gate is read-only and reports `UNVERIFIED — re-execution is CI-only,
50
+ skipped locally`; it never runs a command in a consumer's checkout. The static
51
+ half — is the pointer well-formed, is the command allowlisted — is checked
52
+ everywhere, because a bad pointer is a defect in the ledger rather than a
53
+ property of the machine.
54
+
55
+ **What `exec:` cannot cover.** Only claims whose exit code *is* the verdict. A
56
+ figure resting on a paid model run, a stochastic benchmark, or a prose contract
57
+ cannot use this form; those stay on a pointer and are listed as
58
+ unfalsifiable-by-machine in [`proof.md`](proof.md) rather than quietly omitted.
59
+
60
+ The allowlist is a set of argv prefix tuples in
61
+ [`src/scripts/_lib/exec_evidence.ts`](../src/scripts/_lib/exec_evidence.ts) —
62
+ never a regex over a command string, because a regex over shell text is the
63
+ classic bypass. Every argument after the matched prefix is re-checked for shell
64
+ metacharacters and repo escape, including the right-hand side of `--flag=value`.
40
65
 
41
66
  ---
42
67
 
@@ -52,7 +77,7 @@
52
77
  ### claim: shipped-artifacts-hidden-instruction-scanned
53
78
  - claim: Every artifact the package ships — source AND the condensed projection that reaches consumers — is machine-scanned in CI for hidden-Unicode, mixed-script-confusable, and instruction-smuggling payloads (the rules-file-backdoor class); a finding blocks the release before `npm publish`, not just the merge.
54
79
  - kind: qual
55
- - evidence: .github/workflows/publish-npm.yml#lint_agent_security
80
+ - evidence: exec:lint_agent_security -> 0
56
81
  - status: backed
57
82
  - last_verified: 2026-07-09
58
83
 
@@ -87,21 +112,21 @@
87
112
  ### claim: eval-coverage-ratcheted
88
113
  - claim: Behavioural-eval coverage is measured per tier and CI-ratcheted so it can only rise; the current coverage and its gap are published, never implied as "264 evaluated skills".
89
114
  - kind: qual
90
- - evidence: src/scripts/skill_eval_coverage.ts#checkRatchet
115
+ - evidence: exec:skill_eval_coverage --check -> 0
91
116
  - status: backed
92
117
  - last_verified: 2026-07-08
93
118
 
94
119
  ### claim: domain-soundness-scoped
95
120
  - claim: The non-coding domain skills (finance/founder/ops/content) are forged on TS/PHP and labeled unvalidated until they pass a sourced domain-truth fixture; no public prose implies proven domain correctness, and the validated count is CI-ratcheted.
96
121
  - kind: qual
97
- - evidence: src/scripts/domain_soundness_status.ts#checkRatchet
122
+ - evidence: exec:domain_soundness_status --check -> 0
98
123
  - status: backed
99
124
  - last_verified: 2026-07-08
100
125
 
101
126
  ### claim: domain-soundness-validated-count
102
127
  - claim: The validated non-coding domain-skill count is pinned and CI-ratcheted at a maintainer-set floor (9 of 20 default-surface skills carry a sourced `evals/domain-truth.json` fixture at pin time, 2026-07-11 — 5 deterministic, keys from cited formulas; 4 rubric, criteria matching a named external practice); the floor only rises via a maintainer `--write-floor` after a new sourced fixture lands.
103
128
  - kind: quant
104
- - evidence: internal/evals/domain-soundness-floor.json#validated
129
+ - evidence: exec:domain_soundness_status -> 0
105
130
  - status: backed
106
131
  - last_verified: 2026-07-11
107
132
 
@@ -119,17 +144,10 @@
119
144
  - status: backed
120
145
  - last_verified: 2026-07-09
121
146
 
122
- ### claim: second-brain-retrieval-precision
123
- - claim: Removing the perfect-retrieval assumption, the substrate's REAL keyword retrieval recalls the needed decision into the top-5 under keyword-overlapping confusers (precision@5 9/9) and the model disambiguates it from the co-injected confusers — retrieval-on 27/27 vs no-memory 5/27 and vs equal-count placebo 5/27 (claude-haiku-4-5, 9 tasks x 3 seeds, sign test p=0.008 both). Named limit: retrieval RECALLS but does not RANK (mean tie-set 3.3, ties broken by store order, not relevance) — the discrimination gap that motivates the SQLite-FTS5 activation path (ADR-116) at larger scale.
124
- - kind: quant
125
- - evidence: internal/bench/reports/second-brain-retrieval.json
126
- - status: backed
127
- - last_verified: 2026-07-09
128
-
129
147
  ### claim: lexical-ranking-lift
130
- - claim: A hand-rolled, dependency-free BM25 + trigram lexical index resolves the "recalls but does not rank" gap: on the retrieval-precision corpus (9 keyword-overlapping-confuser tasks) it drives the mean top tie-set from 3.333 (the `_score` bucket scorer) to 1.0 — every needed decision uniquely top-ranked — with precision@1 and precision@5 unchanged at 1.0. Method: deterministic, model-free re-ranking of the SAME retrieved entry set; both scorers measured over the identical store via `measure_lexical_ranking.ts`.
148
+ - claim: A hand-rolled, dependency-free BM25 + trigram lexical index resolves the "recalls but does not rank" gap: on the retrieval-precision corpus (9 keyword-overlapping-confuser tasks) it drives the mean top tie-set from 3.333 (the `_score` bucket scorer) to 1.0 — every needed decision uniquely top-ranked — with precision@1 and precision@5 unchanged at 1.0. Method: deterministic, model-free re-ranking of the SAME retrieved entry set; both scorers measured over the identical store via `measure_lexical_ranking.ts`. Cross-artefact note (2026-07-25): this baseline (3.333) is the value in THIS claim's own artefact and is cited correctly, but the retrieval-precision artefact records 4.111 for the same scorer on the same corpus — two bench scripts disagree. The lift direction (ties collapse to 1.0) holds under either baseline; the discrepancy itself is unresolved and recorded rather than smoothed.
131
149
  - kind: quant
132
- - evidence: internal/bench/reports/lexical-ranking.json
150
+ - evidence: exec:measure_lexical_ranking -> 0
133
151
  - status: backed
134
152
  - last_verified: 2026-07-09
135
153
 
@@ -140,47 +158,47 @@
140
158
  - status: backed
141
159
  - last_verified: 2026-07-12
142
160
 
143
- ---
144
-
145
- ## Unbacked inventory (documented debt — not yet markered in prose)
161
+ ### claim: ledger-exec-verifiability
162
+ - claim: NONE of the backed ledger claims are machine-re-verifiable today — every evidence pointer is checked for existence (file present, substring present, URL carries a date), never for truth, so a claim pointing at a stale artefact stays backed indefinitely. A measured minority COULD carry a re-executing `exec:` form, clearing the >= 10 pp threshold that was pre-registered before the count was taken, which is why that form is scheduled rather than assumed. The rest cannot: paid or stochastic benchmark runs no CI job can re-derive, and prose contracts. Exact counts live in the evidence file and are NOT restated here on purpose — this entry hard-coded its denominator twice and drifted within a day both times (25 when the ledger held 26, then 26 when it held 27) while CI stayed green, because the pointer resolved. `check_claims` now compares the stored denominator against the live ledger and fails on divergence. A number a human retypes on every ledger edit will drift; the fix was to stop retyping it.
163
+ - kind: quant
164
+ - evidence: internal/reports/exec-evidence-feasibility.json#"exec_feasible"
165
+ - status: backed
166
+ - last_verified: 2026-07-25
146
167
 
147
- These are real README claims that need a durable binding before they may carry a
148
- `<!-- claim: -->` marker. Counts are drift-prone: binding them requires a
149
- count-source mechanism (a generated number the prose must match). That
150
- mechanism now exists (road-to-truth-and-reference-hygiene Phase 1):
151
- `update_counts.ts` generates every prose count from source, and
152
- `check_artefact_count_messaging.ts` fails CI on any count-shaped prose
153
- mention that drifts or is internally inconsistent — so the three count
154
- claims below are `backed`. Remaining entries are listed so the debt is
155
- visible, not hidden.
168
+ ### claim: enforcement-coverage-resolved
169
+ - claim: 14 of 107 governed rules (13.1%) carry a backstop that fails a CI build. The number is RESOLVED, not declared — a `validator:` counts only when the script exists AND a GITHUB WORKFLOW reaches it (transitively, so a sub-check under a wired umbrella counts), and a hook registered `fail_closed: false` resolves to `observer`, never `validator`. The figure was 14 before this correction too, and it was wrong: the resolver treated `taskfiles/` and `.github/workflows/` as one corpus, so "named in a taskfile" counted as blocking — while NO workflow invokes `task ci`, `ci-strict`, or `ci-fast`. Nine of the thirteen validators only ran when a human typed the command. Split into `validator` (CI runs it) and `validator-local` (only a taskfile does), the honest figure was 5 of 107; wiring the nine into `rule-backstops.yml` returned it to 14, this time meaning what the headline says. `local_only` is now 0 and is ratcheted, so a gate cannot drop back out silently. Wiring them also surfaced that FIVE were already failing invisibly — 37 findings, baselined in `rule-backstop-debt.json` and ratcheted against growth. 86 rules declare nothing and count as uncovered, not excluded.
170
+ - kind: quant
171
+ - evidence: exec:check_enforcement_coverage --check -> 0
172
+ - status: backed
173
+ - last_verified: 2026-07-25
156
174
 
157
175
  ### claim: skill-count
158
- - claim: 278 skills.
176
+ - claim: 281 skills.
159
177
  - kind: quant
160
- - evidence: src/scripts/check_artefact_count_messaging.ts#Artefact-count messaging gate
178
+ - evidence: exec:check_artefact_count_messaging -> 0
161
179
  - status: backed
162
180
  - last_verified: 2026-07-08
163
181
 
164
182
  ### claim: command-count
165
183
  - claim: 190 commands.
166
184
  - kind: quant
167
- - evidence: src/scripts/check_artefact_count_messaging.ts#Artefact-count messaging gate
185
+ - evidence: exec:check_artefact_count_messaging -> 0
168
186
  - status: backed
169
187
  - last_verified: 2026-07-08
170
188
 
171
189
  ### claim: rule-count
172
- - claim: 105 governed rules.
190
+ - claim: 107 governed rules.
173
191
  - kind: quant
174
- - evidence: src/scripts/check_artefact_count_messaging.ts#Artefact-count messaging gate
192
+ - evidence: exec:check_artefact_count_messaging -> 0
175
193
  - status: backed
176
194
  - last_verified: 2026-07-08
177
195
 
178
196
  ### claim: host-agent-count
179
- - claim: Compiled into 7+ host agents (Claude Code, Cursor, Augment, Cline, Windsurf, Copilot, Gemini).
197
+ - claim: 23 host agents are detected and inventoried; 20 receive a written config surface (18 projection + 1 plugin + 1 bundle target) and 3 are export-only (aider, zed, jetbrains). The count is enforced, not asserted — `knownToolIds()` is pinned at 23 by a test whose assertion literal IS the number, and `src/config/surface-matrix.yml` is held in set-equality with the installer's own user-scope path map by `lint_surface_matrix`, so a host added to one and not the other fails the build. This entry stood `unbacked` while naming its own unblocking condition ("once `surface-matrix.yml` exists, bind the count to that file and flip"); the condition was met and nothing fired, so the shipped figure stayed "7+" — understating real coverage by 3x.
180
198
  - kind: quant
181
- - evidence: stays unbacked pending a machine-readable projection-targets list — the concrete binding artifact is `src/config/surface-matrix.yml` (authored by road-to-install-path-convergence Phase 2, per the 2026-07-07 install-path council); once it exists, bind the count to that file and flip. Triaged 2026-07-08 (truth-and-reference-hygiene P3): do NOT bind to prose host tables (`docs/enforcement-by-host.md`) — a substring pointer cannot verify a count.
182
- - status: unbacked
183
- - last_verified:
199
+ - evidence: exec:vitest run tests/install/toolDetection.test.ts -> 0
200
+ - status: backed
201
+ - last_verified: 2026-07-25
184
202
 
185
203
  ### claim: orchestration-dispatch-net-win
186
204
  - claim: On the ordered-refactor + competitive-impl families (`orch-02`, `orch-03`), contract-governed subagent dispatch nets ≥15% token-or-wall reduction at non-regressed quality vs single-agent execution.
@@ -225,11 +243,11 @@ visible, not hidden.
225
243
  - last_verified: 2026-07-12
226
244
 
227
245
  ### claim: retrieval-substrate-live-pass
228
- - claim: On the live end-to-end retrieval benchmark (9 tasks × 3 arms × 3 seeds on claude-haiku, fixture store with keyword-overlapping confusers), the memory retrieval substrate scored precision@5 = 100% (9/9) with 100% poisoned-entry rejection, and the retrieval-on arm passed 27/27 model-scored tasks vs 2/27 with retrieval off and 4/27 with a placebo injection. Known limit stays published: mean tie-set 4.1 means top-k ties break by store order, not relevance (the ADR-116/FTS5 signal).
246
+ - claim: On the live end-to-end retrieval benchmark (9 tasks × 3 arms × 3 seeds on claude-haiku, fixture store with keyword-overlapping confusers), the memory retrieval substrate scored precision@5 = 100% (9/9) with 100% poisoned-entry rejection, and the retrieval-on arm passed 27/27 model-scored tasks vs 2/27 with retrieval off and 4/27 with a placebo injection. Known limit stays published: mean tie-set 4.111 means top-k ties break by store order, not relevance (the ADR-116/FTS5 signal). SOLE RECORD for this artefact as of 2026-07-25: a second entry (`second-brain-retrieval-precision`) described the same measurement from the precision angle and had drifted to 5/27, 5/27 and tie-set 3.3 — figures absent from the shared artefact. Two entries over one artefact is what allowed them to disagree while both resolved, so the pair was folded into this one.
229
247
  - kind: quant
230
248
  - evidence: internal/bench/reports/second-brain-retrieval.json#retrieval-on
231
249
  - status: backed
232
- - last_verified: 2026-07-12
250
+ - last_verified: 2026-07-25
233
251
 
234
252
  ### claim: wedge-hollow-detection
235
253
  - claim: On the A3 orchestration eval (deterministic verify, measured token deltas), the production-validator subagent returned the correct verdict on both fixtures — NOT READY with the exact `file:line` citation on a planted hollow implementation, READY with zero spurious findings on the clean control — while consuming ~45k fewer tokens than the inline-host baseline on each task. Scope: two planted fixtures on a Claude Code host, not a broad hit-rate.
@@ -259,3 +277,10 @@ visible, not hidden.
259
277
  - status: unbacked
260
278
  - last_verified: 2026-07-21
261
279
  - resolution: HONEST-NULL (resolved, not pending). Registered cross-vendor run 2026-07-21 on the curated judge-survivable corpus (internal/bench/adversarial-council/): on the judge-passed residual, the 2-vendor skeptic panel (anthropic+openai) matched the single skeptic exactly (residual recall 0.6 = 0.6, zero lift — the second vendor's residual catches were a strict subset of the first), at a 100% false-positive rate on the controversial-but-correct controls under the adversarial-skeptic posture. Both recall thresholds missed → honest-null → Mode 9 surface stays default-off permanently (like recursive-verification). Reproducible artifact: internal/bench/adversarial-council/runs/. Note: an initial run via `council_cli run` was REJECTED as a measurement artifact (that transport imposes multi-round peer-review + prose output, defeating the independent-skeptic + JSON-scoring protocol) — the valid run uses direct independent per-vendor client calls.
280
+
281
+ ### claim: gated-platform-reads
282
+ - claim: A credential-free prescription layer reads content the host's own web tools cannot fetch at all — Reddit thread text (Atom feeds) AND comment ranking plus reply nesting (server-rendered HTML), and a single named tweet (the platform's own oEmbed endpoint). Measured 2026-07-25 from a residential network against a pre-registered 6-task-per-channel set with a native control and thresholds frozen before the run: reddit tier 1 6/6, reddit tier 2 6/6, twitter-oembed 6/6, native 0/6 on both Reddit tiers. Zero credentials, zero resident processes, zero auto-installs. Scope bounds that travel WITH the claim: (a) the twitter gap is narrower than 6/6 suggests — native also passed 2 of those 6 via third-party mirrors, so the channel earns its place only on tweets nothing mirrors; (b) reddit tier 2 is on an announced closing path and ships with a kill-switch keyed on an OBSERVED login wall; (c) youtube-transcripts is PARKED, not shipped — its backend is human-installed by contract and was never exercised; (d) residential network is load-bearing, and CI is explicitly not a bench environment.
283
+ - kind: quant
284
+ - evidence: docs/benchmark.md#ship-gated-reach
285
+ - status: backed
286
+ - last_verified: 2026-07-25
@@ -146,8 +146,8 @@ note, package-internal path-swap, description budget, and the
146
146
 
147
147
  | Layer | Count | Purpose |
148
148
  |---|---|---|
149
- | **Skills** | 278 | On-demand expertise — stack analysis (Laravel · Symfony · Zend / Laminas · Next.js · React · Node), testing, Docker, API design, security, observability, … |
150
- | **Rules** | 105 | Always-active constraints — coding standards, scope control, verification, language-and-tone, agent-authority |
149
+ | **Skills** | 281 | On-demand expertise — stack analysis (Laravel · Symfony · Zend / Laminas · Next.js · React · Node), testing, Docker, API design, security, observability, … |
150
+ | **Rules** | 107 | Always-active constraints — coding standards, scope control, verification, language-and-tone, agent-authority |
151
151
  | **Commands** | 190 | Slash-command workflows — `/commit`, `/create-pr`, `/fix ci`, `/optimize skills`, `/feature plan`, `/work`, `/implement-ticket`, `/condense`, … |
152
152
  | **Guidelines** | 101 | Reference material cited by skills — PHP patterns, Eloquent, Playwright, agent-infra, … |
153
153
  | **Templates** | 7 | Scaffolds for features, roadmaps, contexts, skills, overrides |
package/docs/benchmark.md CHANGED
@@ -646,3 +646,140 @@ defect-finding *quality/lift* claim binds; team mode stays documented as
646
646
  judge-survivable-subtlety corpus that breaks the recall ceiling, or (b) a new
647
647
  model generation. The worker-via-bundle delegate (roadmap Phase 3 Step 4) stays
648
648
  deferred — it re-opened only on a measured review lift, which did not occur.
649
+
650
+ ## Internet-reach prescriptions vs host-native web tools (2026-07-24) — HONEST NULL (capability), cost signal unregistered {#honest-null-reach}
651
+
652
+ **Question (pre-registered before the run):** does a reach-prescription layer —
653
+ `gh api` for repository metadata, a local feed parser, a keyless discussion-search
654
+ API, `curl` + local HTML→text — beat the host's own web-search / web-fetch tools
655
+ on credential-free dev-research tasks, and at what token cost? The layer was
656
+ prototyped in gitignored scratch first, so both arms were real at scoring time.
657
+
658
+ **Design.** 12 tasks × 2 arms (`native` = host web tools only; `reach` = the
659
+ prototype prescriptions), 4 parallel subagents, arms judged independently on
660
+ pre-declared acceptance evidence — no arm-vs-arm comparison at scoring time.
661
+ Thresholds, verdict bands and the run protocol were committed **before** the run
662
+ (`internal/bench/reach-vs-native/README.md`); the report is
663
+ `internal/bench/reach-vs-native/VERDICT.md`, raw rows in `results.csv`.
664
+
665
+ **Result — capability: NULL.** The native arm passed **12/12**. Under the
666
+ pre-registered rule (reach wins only where native fails; **ties are native
667
+ wins**) the reach arm scored **0 outright wins of 12** → band **`stop`**. Two
668
+ reach failures were prescription defects (a 400-char excerpt cap; a `jq`
669
+ projection dropping the release body), and repairing them **cannot** move the
670
+ band: the native arm passed those tasks too, so a repaired reach arm scores a
671
+ tie. Zero native failures ⇒ zero possible reach wins.
672
+
673
+ **Consequence: no router skill shipped.** The `internet-reach` router was
674
+ cancelled pre-authoring by its own Phase-0 gate. What did ship is the
675
+ verdict-independent operator tooling — a schema-validated channel registry, a
676
+ five-state probe engine with stale-shim detection, a read-only `reach:doctor`,
677
+ and a CI gate that fails on any unpinned install prescription.
678
+
679
+ **Honest bound.** The credential-free constraint (needed for reproducibility)
680
+ structurally excluded the two cases where a reach advantage was hypothesized:
681
+ video subtitles (backend absent → `untested`) and authenticated / rate-limited
682
+ platform access (impossible in a keyless set). The null therefore reads narrowly:
683
+ *on public, credential-free dev-research tasks, a reach prescription layer buys
684
+ no capability the host does not already have.* It says nothing about gated-platform
685
+ access. Testing that needs a credentialed task set with its own pre-registration.
686
+
687
+ **Unregistered observation — cost, not capability.** On all 8 tasks both arms
688
+ solved, the reach arm was cheaper: **3,070 vs 6,730 tokens (0.46×)**, largest
689
+ gaps on repository metadata (0.26×) and discussion search (0.31×). The native
690
+ arm's overhead was *discovery*: it repeatedly had to find the machine-readable
691
+ endpoint the prescription already knows. This is recorded **outside** the
692
+ decision — S0b was authored as a ≤1.5× guardrail, never a win condition, and
693
+ promoting it to one after seeing the data would be the post-hoc rigging the bands
694
+ exist to prevent. Acting on it requires a separate, cost-primary pre-registration
695
+ (equal-evidence tasks, token cost as the primary metric, a stated minimum saving
696
+ worth the maintenance burden).
697
+
698
+ ## Gated-platform reads (2026-07-25) — SHIP (3 channels), with a narrowed gap on one {#ship-gated-reach}
699
+
700
+ **Question (pre-registered before the run):** on platforms the host's own web tools
701
+ cannot reach at all, are credential-free prescriptions **reliable** enough to justify
702
+ their maintenance weight — measured **per channel**, never aggregated?
703
+
704
+ This is deliberately not the question the parent bench asked. The
705
+ [internet-reach null](#honest-null-reach) measured whether a prescription layer beats
706
+ native tools on credential-free dev research, answered **no** (0/12, band `stop`), and
707
+ named its own bound: *"It says nothing about gated-platform access. Testing that needs
708
+ a credentialed task set with its own pre-registration."* This run is that test —
709
+ except it turned out **no credentials are needed**, which is itself the finding that
710
+ made it worth running.
711
+
712
+ **The capability gap is established, not assumed.** Measured the same session, first
713
+ hand: `reddit.com` is refused at the domain level by the host's own tool (a
714
+ client-side refusal, not a 403 from Reddit); `x.com/<user>/status/<id>` answers **HTTP
715
+ 402**; a YouTube watch page answers 200 with metadata and no transcript.
716
+
717
+ **Design.** 6 tasks per channel with pre-declared acceptance evidence, each with a
718
+ **native-arm control**, thresholds frozen before the run (≥5/6 ship · 3–4/6 park ·
719
+ ≤2/6 drop), one documented repair per task allowed, verdicts never aggregated.
720
+ Pre-registration: `internal/bench/gated-reach/README.md`; rows and evidence:
721
+ `internal/bench/gated-reach/results.md`.
722
+
723
+ | Channel | reach | native | Verdict |
724
+ |---|---|---|---|
725
+ | `reddit` tier 1 — Atom text | **6/6** | 0/6 | **ship** |
726
+ | `reddit` tier 2 — ranking + thread structure | **6/6** | 0/6 | **ship** — time-bounded |
727
+ | `twitter-oembed` — single tweet | **6/6** | 2/6 | **ship** — narrowed gap, below |
728
+ | `youtube-transcripts` | not run | — | **park** — unexercised (backend absent by design) |
729
+
730
+ **Reddit is a real, unambiguous capability.** Post text, comment text with authors
731
+ (147 feed entries on the test thread, 135 author-bearing), and — via server-rendered
732
+ HTML — **comment scores and reply nesting** (134 comments across 7 depth levels,
733
+ scores cross-checked against the rendered page). Native scores 0/6 by construction:
734
+ there is no native path to a domain the host refuses. The rate limiting that makes
735
+ this fragile is solved with **no new code** — `curl --retry 8 --retry-max-time 110`
736
+ measured 5/5 against 2/6 without it, because curl treats 429 as retryable and backs
737
+ off exponentially when `--retry-delay` is omitted.
738
+
739
+ **Tier 2 ships with an expiry, not a promise.** Reddit announced a login requirement
740
+ for the server-rendered interface on 2026-06-30 and withdrew its earlier commitment to
741
+ keep it available. Logged-out access still worked on 2026-07-25. It therefore ships
742
+ with a kill-switch keyed on an **observed** login wall — never on the announcement —
743
+ and with tier 1 as the permanent fallback. Degradation is a documented output
744
+ (`login_wall: true`, "ranking unavailable"), because presenting unranked text as
745
+ ranked is the one failure mode here that produces wrong conclusions rather than a
746
+ missing answer.
747
+
748
+ **The control rule fired, and the Twitter story is narrower than its 6/6.** The first
749
+ task set used the most-quoted tweets in existence; native scored **5/6** on them — not
750
+ by reading `x.com`, but because a canonical tweet's text is reproduced everywhere.
751
+ Those five tasks were **removed and replaced** per the pre-registered control rule.
752
+ On five genuinely obscure tweets native dropped to **2/6**, and one of its two
753
+ "passes" came from the author's Threads and Mastodon cross-posts rather than Twitter.
754
+ Where it failed it failed usefully badly: on one tweet it produced a paraphrase and a
755
+ **confidently wrong month**, and it cannot distinguish a deleted tweet from a live one
756
+ (both answer 402). So the honest reading of Twitter's 6/6 is: *the channel is reliable,
757
+ and the gap it closes is narrow* — for any tweet discussed anywhere, native search
758
+ already recovers the content; the channel earns its place on the case where a specific
759
+ URL is in hand and nothing mirrors it.
760
+
761
+ **A bench limitation, published rather than engineered away.** The control rule says a
762
+ native pass means the task was mis-scoped, so the two native-passed Twitter tasks
763
+ should have been replaced again. They were not, and the reason is structural: every
764
+ tweet-sourcing channel available to a host that cannot read Twitter — HN links, Reddit
765
+ links, search — selects for tweets that *were* discussed publicly, which is exactly the
766
+ population native search recovers. Sourcing an undiscussed tweet requires the access
767
+ this bench exists because we lack. The 6/6 stands on the frozen threshold; the caveat
768
+ is recorded here so nobody later reads it as "six things only this channel can do".
769
+
770
+ **YouTube is parked, not scored.** `yt-dlp` is absent and the package never
771
+ auto-installs. Per the pre-registered unexercised rule, a channel that cannot be
772
+ exercised cannot reach ship and is not counted as a drop — an uninstalled tool is a
773
+ fact about this machine, not about the channel. What did ship for it is the readiness
774
+ check that closes the blind spot the parent bench left open: a passing `yt-dlp
775
+ --version` does **not** imply extraction works, because full YouTube support needs an
776
+ external JS runtime, so the doctor inspects the yt-dlp config semantically and reports
777
+ a distinct `not-ready` state with an idempotent fix command.
778
+
779
+ **Three prescription defects were found by executing the prescriptions verbatim** —
780
+ none would have been caught by review: a single HTML-entity decode pass leaves
781
+ `&mdash;` in tweet text; a missing `-f` makes a deleted tweet answer **exit 0 with
782
+ 3,663 bytes of error HTML** that a caller reads as success; and a dropped `-L` makes
783
+ the oEmbed endpoint answer 301 with an empty body, which looks like a dead service.
784
+ All three are fixed and documented as load-bearing in
785
+ [`docs/guides/gated-platform-reads.md`](guides/gated-platform-reads.md).
package/docs/catalog.md CHANGED
@@ -1,13 +1,13 @@
1
1
  # agent-config — Public Catalog
2
2
 
3
- Consumer-facing catalog of all **673 public artefacts** shipped by
3
+ Consumer-facing catalog of all **678 public artefacts** shipped by
4
4
  this package. Internal package-maintenance rules and deprecation shims
5
5
  are excluded.
6
6
 
7
7
  > **Regenerate:** `./scripts-run src/scripts/generate_index`
8
8
  > Auto-generated — do not edit manually.
9
9
 
10
- ## Skills (278)
10
+ ## Skills (281)
11
11
 
12
12
  > **Behavioural-eval coverage is measured, not implied.** A skill is
13
13
  > behaviourally evaluated only if it ships `evals/evals.json`; most do
@@ -61,6 +61,7 @@ are excluded.
61
61
  | skill | [`character-consistency`](../dist/agent-src/skills/character-consistency/SKILL.md) | official | Use when a character must stay visually identical across AI video scenes — locks identity tokens (silhouette, palette, wardrobe, prop) in JSON. Triggers 'character lock', 'same character'. |
62
62
  | skill | [`check-refs`](../dist/agent-src/skills/check-refs/SKILL.md) | official | Use when verifying cross-references between skills, rules, commands, guidelines, and context documents are not broken after edits, renames, or deletions. |
63
63
  | skill | [`churn-prevention`](../dist/agent-src/skills/churn-prevention/SKILL.md) | official | Use when designing churn defence — health-score signals, churn-cause split (involuntary / value / relationship / fit), early-warning loop. Triggers on 'why are accounts leaving'. |
64
+ | skill | [`code-intelligence`](../dist/agent-src/skills/code-intelligence/SKILL.md) | official | Route codebase-structure questions (who calls X, where used, what imports, change-impact) to a code-graph first, grep fallback. Triggers 'who calls', 'where is this used', 'call graph'. |
64
65
  | skill | [`code-refactoring`](../dist/agent-src/skills/code-refactoring/SKILL.md) | official | Use when the user says 'refactor this', 'rename class', or 'move method'. Safely refactors code in any language — finds all callers, updates downstream dependencies, verifies via quality tools. |
65
66
  | skill | [`code-review`](../dist/agent-src/skills/code-review/SKILL.md) | official | Use when the user says \"review this\", \"check my code\", or wants feedback on changes. Reviews for correctness, quality, security, and coding standards. |
66
67
  | skill | [`command-routing`](../dist/agent-src/skills/command-routing/SKILL.md) | official | Use when the user invokes a slash command like /create-pr, /commit, /fix-ci, or pastes command file content — routes to the right command with context inference and GitHub API patterns. |
@@ -124,6 +125,7 @@ are excluded.
124
125
  | skill | [`frontend-render-security`](../dist/agent-src/skills/frontend-render-security/SKILL.md) | official | Writing/reviewing client-side UI (React/Vue/vanilla) — insecure-render + client-trust gaps AI ships: XSS via innerHTML, client secrets, client-only auth, CORS wildcard, token in localStorage |
125
126
  | skill | [`fundraising-narrative`](../dist/agent-src/skills/fundraising-narrative/SKILL.md) | official | Use when shaping a capital-raise pitch — why-now / why-us / why-this framing, market-size reasoning, traction-story construction. Triggers on 'tighten the pitch', 'why-now is weak'. |
126
127
  | skill | [`funnel-analysis`](../dist/agent-src/skills/funnel-analysis/SKILL.md) | official | Use when diagnosing where a SaaS or product funnel leaks — visitor → signup → activation → paid → retained — channel-agnostic, conversion-rate-driven. |
128
+ | skill | [`gated-reach`](../dist/agent-src/skills/gated-reach/SKILL.md) | official | Read a Reddit thread or single tweet the host cannot fetch — 'what does this Reddit thread say', 'top comment on this post', 'what does this tweet say' — when reddit.com is refused or x.com 402s. |
127
129
  | skill | [`git-workflow`](../dist/agent-src/skills/git-workflow/SKILL.md) | official | Use when working with Git — branch naming, commit messages, PR creation, rebasing, or the code review process — even when the user says 'push this' or 'merge the branch' without naming Git. |
128
130
  | skill | [`github-ci`](../dist/agent-src/skills/github-ci/SKILL.md) | official | Use when working with GitHub Actions — workflow YAML, quality gates, test matrices, deployment triggers, reusable workflows — even when the user just says 'my CI is failing' or 'add a check'. |
129
131
  | skill | [`grafana`](../dist/agent-src/skills/grafana/SKILL.md) | official | Use when working with Grafana — dashboards, Loki LogQL queries, alerting rules, monitoring panels — even when the user just says 'build me a dashboard' or 'query the logs' without naming Grafana. |
@@ -256,6 +258,7 @@ are excluded.
256
258
  | skill | [`runway-cognition`](../dist/agent-src/skills/runway-cognition/SKILL.md) | official | Use when reasoning about cash runway — burn shape, fundraise triggers, layoff-vs-cut-vs-grow decisions. Triggers on 'how long do we have', 'should we raise', 'cut or grow'. |
257
259
  | skill | [`scenario-modeling`](../dist/agent-src/skills/scenario-modeling/SKILL.md) | official | Use when constructing base / upside / downside scenarios — three-statement modeling, sensitivity analysis, optionality reasoning. Triggers on 'model the scenarios', 'what if growth halves'. |
258
260
  | skill | [`scene-expander`](../dist/agent-src/skills/scene-expander/SKILL.md) | official | Use when expanding a one-line idea into the 12-block Cinematic Scene Blueprint — provider-agnostic, includes optional dialogue + ambient. Triggers 'expand this scene', 'blueprint for X'. |
261
+ | skill | [`screenshot-hygiene`](../dist/agent-src/skills/screenshot-hygiene/SKILL.md) | official | Use when creating and embedding a documentation screenshot — detect and redact sensitive data, human-gate data-bearing shots before ship. Triggers 'screenshot for docs', 'screenshot admin panel'. |
259
262
  | skill | [`script-writing`](../dist/agent-src/skills/script-writing/SKILL.md) | official | Use when adding or editing any script under `scripts/` — `--quiet`, `_lib/script_output`, silent Taskfile wiring, Iron-Law carve-outs; fires on 'add a check script for X'. |
260
263
  | skill | [`secrets-management`](../dist/agent-src/skills/secrets-management/SKILL.md) | official | Use when picking a secrets store, designing rotation, or wiring scanning gates — multi-cloud (Vault, AWS, Azure, GCP), CI, and Kubernetes — decision framework, provider deep-dives externalized. |
261
264
  | skill | [`security`](../dist/agent-src/skills/security/SKILL.md) | official | Use when applying security best practices — authentication, authorization, CSRF protection, input sanitization, rate limiting, or secure coding — stack-agnostic. |
@@ -306,7 +309,7 @@ are excluded.
306
309
  | skill | [`wireframe`](../dist/agent-src/skills/wireframe/SKILL.md) | official | Explore a flow or layout with 3+ disposable lo-fi greyscale wireframes on a named axis, before any hi-fi work. Use when the user wants to sketch directions or explore structure. |
307
310
  | skill | [`worktree-lifecycle`](../dist/agent-src/skills/worktree-lifecycle/SKILL.md) | official | Use when governing a worktree across its whole life — scope-lock declaration, merge-readiness status, scoped verification, and safe cleanup that refuses while unique unmerged commits exist. |
308
311
 
309
- ## Rules (104)
312
+ ## Rules (106)
310
313
 
311
314
  | kind | name | type | description |
312
315
  |---|---|---|---|
@@ -337,6 +340,7 @@ are excluded.
337
340
  | rule | [`design-fidelity`](../dist/agent-src/rules/design-fidelity.md) | auto | A provided prototype/mockup/design system is the spec — build 1:1; never swap fonts, controls, or layout unconfirmed |
338
341
  | rule | [`devcontainer-routing`](../dist/agent-src/rules/devcontainer-routing.md) | auto | Wiring DevContainers/Codespaces (devcontainer.json, features, ports) — route to the devcontainer skill |
339
342
  | rule | [`direct-answers`](../dist/agent-src/rules/direct-answers.md) | always | Always — direct, unembellished answers. No flattery, no invented facts (verify load-bearing claims, otherwise ask). Emojis only as functional markers. Brevity is the default. |
343
+ | rule | [`doc-screenshot-hygiene`](../dist/agent-src/rules/doc-screenshot-hygiene.md) | auto | Screenshots for docs — anonymize sensitive data before shipping; data-bearing shots are human-gated (published egress); terminal/CLI/IDE screenshots forbidden |
340
344
  | rule | [`docker-commands`](../dist/agent-src/rules/docker-commands.md) | auto | Running PHP inside Docker — artisan, composer, phpstan, rector, ecs, phpunit, tests, migrations, any CLI tool |
341
345
  | rule | [`domain-adoption-policy`](../dist/agent-src/rules/domain-adoption-policy.md) | auto | Adopting a new domain track (mobile, ML, IoT…) — demand/owner/CI gates BEFORE harvest |
342
346
  | rule | [`domain-safety-disclaimer`](../dist/agent-src/rules/domain-safety-disclaimer.md) | auto | Advisory content (legal, medical, financial, consulting) — matching 'not X advice' disclaimer; refuse diagnosis/dosage |
@@ -391,6 +395,7 @@ are excluded.
391
395
  | rule | [`rule-type-governance`](../dist/agent-src/rules/rule-type-governance.md) | auto | Creating/editing rules, or auditing rule types — decides when a rule should be always vs auto |
392
396
  | rule | [`runtime-safety`](../dist/agent-src/rules/runtime-safety.md) | auto | Skill declares execution metadata — enforce safety constraints for assisted/automated execution types |
393
397
  | rule | [`scope-control`](../dist/agent-src/rules/scope-control.md) | always | Scope control — no unsolicited architectural changes, refactors, or library replacements |
398
+ | rule | [`secret-vcs-guard`](../dist/agent-src/rules/secret-vcs-guard.md) | auto | About to write a credential into a tracked file or stage/commit one in any VCS (git/svn/hg) — STOP, show the match, ask, offer alternatives; never silently commit, never silently strip |
394
399
  | rule | [`security-sensitive-stop`](../dist/agent-src/rules/security-sensitive-stop.md) | auto | Security-sensitive paths (auth, billing, tenants, secrets, uploads, webhooks) — threat-model BEFORE editing |
395
400
  | rule | [`senior-engineering-discipline`](../dist/agent-src/rules/senior-engineering-discipline.md) | auto | Writing/generating code — generalize (no overfit or tautological tests), supply the invisible cross-cutting controls the prompt didn't name, never invent an API/field/package |
396
401
  | rule | [`size-enforcement`](../dist/agent-src/rules/size-enforcement.md) | manual | Creating or editing rules, skills, commands, guidelines, AGENTS.md, or copilot-instructions.md — enforce size and scope limits |
@@ -12,34 +12,76 @@
12
12
  # check_claims pointer resolver); every `checkable: true` row's `our_evidence`
13
13
  # resolves. build_proof renders these rows. check_no_external_sources guarantees
14
14
  # no named source leaks in.
15
+ #
16
+ # `failure_mode` (optional) — what this row's claim prevents, in adopter-facing
17
+ # voice. A populated row ALSO renders in the "What each one prevents" view on the
18
+ # proof page; an empty field is the honest signal that the row is comparative
19
+ # only. Membership in that view is therefore a data property, never a curated
20
+ # short-list that can drift from this table.
21
+ #
22
+ # THE PIN SHAPE IS REFUSED HERE, DELIBERATELY. A number in these rows is bound by
23
+ # a resolving pointer — never by a test asserting that a literal string appears in
24
+ # a doc. A comparable suite pinned a marketing figure with an
25
+ # `assertIn("<number> tokens", …)` test; its own published formula yields a value
26
+ # ~4x larger, and the pin turned the wrong number into a protected invariant that
27
+ # CI actively defended. A pointer can go stale and be re-derived; a pin makes
28
+ # staleness the passing condition.
15
29
 
16
30
  rows:
17
- - claim: "No runtime — no background daemon, no state database, no auto-write memory."
31
+ - claim: "No resident runtime — no background daemon, no state database or service, no auto-write memory; deterministic, rebuildable file indexes only."
18
32
  our_evidence: "docs/contracts/no-runtime-boundary.md#file-first"
19
- their_evidence: "Swarm-runtime tools in this category ship a background process and/or a state store by design; that is an architectural fact of the runtime approach, not a defect."
33
+ their_evidence: "Swarm-runtime tools in this category ship a background process and/or a resident state store by design; that is an architectural fact of the runtime approach, not a defect."
20
34
  checkable: true
35
+ failure_mode: >-
36
+ A background process keeps running after you stop using it, holds state you did not write, and has to be kept alive and upgraded.
21
37
 
22
38
  - claim: "Capability/benchmark results are published — including the runs where the package changed nothing."
23
39
  our_evidence: "docs/benchmark.md"
24
40
  their_evidence: "A category headline figure (e.g. an '84.8%' score) appears across marketing surfaces with no reproducible methodology published — so it cannot be verified either way."
25
41
  checkable: true
42
+ failure_mode: >-
43
+ You adopt on a headline number nobody can re-run, and never learn which of its measurements changed nothing.
26
44
 
27
45
  - claim: "Every public claim binds to machine-checked evidence."
28
46
  our_evidence: "docs/CLAIMS.md"
29
47
  their_evidence: "Marketing claims in this category are not bound to a machine-checked ledger a reader can reproduce."
30
48
  checkable: true
49
+ failure_mode: >-
50
+ A shipped number drifts from the artefact it came from and stays published, because nothing re-checks the claim against its source.
31
51
 
32
52
  - claim: "Skills publish their own known limits, each with a witness test."
33
53
  our_evidence: "tests/scripts/witness/check_refs_relative_gap.test.ts"
34
54
  their_evidence: "Published known-limitation surfaces backed by reproducing tests are not a standard artifact in this category."
35
55
  checkable: true
56
+ failure_mode: >-
57
+ A limitation is discovered by you, in your repo, at the moment it costs you something — instead of being stated up front and held by a test.
36
58
 
37
59
  - claim: "A 30-second single-file wedge exists — one read-only subagent, one command, verdict with file:line — and its promise is a scoped, published eval, not a feature list."
38
60
  our_evidence: "internal/bench/orchestration/pv-a3-results.md#token_delta_provenance: measured"
39
61
  their_evidence: "Category entry points typically install the full platform (profiles, packs, runtime) before the first felt win; single-artifact entries with a published eval behind the promise are not a standard artifact."
40
62
  checkable: true
63
+ failure_mode: >-
64
+ Evaluating the tool means installing the whole platform first, so the first thing you learn is the setup cost rather than whether it works.
41
65
 
42
66
  - claim: "The persona-identity question was tested and published as an honest null (identity swap ~zero effect, provider choice ~15x larger) instead of being shipped as theater."
43
67
  our_evidence: "internal/bench/reports/persona-placebo.json#honest-null"
44
68
  their_evidence: "Named-persona prompts are shipped as a feature across the category without a published A/B separating identity from method."
45
69
  checkable: true
70
+ failure_mode: >-
71
+ You pay tokens for prompt theater that was never measured against the method text it wraps.
72
+
73
+ - claim: "Every upstream-tool install prescription the package ships is version-pinned, intake-recorded, and enforced offline in CI — an unpinned version, a branch/archive install source, or a pipe-remote-to-shell instruction fails the build."
74
+ our_evidence: "src/scripts/validate_reach_prescriptions.ts"
75
+ their_evidence: "Capability layers in this category commonly install themselves and their upstream dependencies from a moving target (a branch archive or an unpinned package) via a piped remote installer; whether any given one pins is observable per repo, but a CI gate that fails the build on an unpinned prescription is not a standard artifact."
76
+ checkable: true
77
+ failure_mode: >-
78
+ An install instruction silently follows a moving target — an unpinned package or a piped remote script — so what lands in your repo is whatever the source held that day.
79
+
80
+ - claim: "Platform reads that the host's own web tools cannot perform at all (a refused domain, an HTTP 402) are shipped as credential-free prescriptions whose reliability was measured per channel against a native control, with the thresholds frozen before the run and the narrowing caveat published alongside the pass."
81
+ our_evidence: "docs/benchmark.md#ship-gated-reach"
82
+ their_evidence: "Reaching gated platforms is commonly solved in this category by asking for an API key or a session cookie, and the capability is asserted from a feature list rather than a per-channel reliability measurement with a native-arm control; publishing the case where the native tools already suffice, next to the pass, is not a standard artifact."
83
+ checkable: true
84
+ failure_mode: >-
85
+ You hand over a credential — or your account — for a read the tools could
86
+ already do, and you cannot tell which channels actually work because the
87
+ capability was claimed rather than measured.
@@ -0,0 +1,53 @@
1
+ # Contract: local server ports + host integration
2
+
3
+ > The loopback/port contract `src/server/port.ts` enforces, plus the
4
+ > host-integration surface (config root + embed) a host like agent-switch binds
5
+ > to. This file resolves the long-standing pointer in `src/server/port.ts`.
6
+
7
+ ## Port range
8
+
9
+ - The GUI/API server binds on **loopback `127.0.0.1` only**, on a free port in
10
+ **41000–41999** (per ADR-012). `src/server/port.ts` picks a free port by
11
+ actually binding (no is-free → bind race) and refuses any range that overlaps
12
+ the privileged ports `[0, 1024]` or strays outside this documented range —
13
+ both are anti-regression guards (`validateRange`).
14
+ - The chosen port is ephemeral per process; a host discovers the live port from
15
+ the server-info readout, never by assuming a fixed value.
16
+
17
+ ## Auth token
18
+
19
+ - `src/server/token.ts`: a 32-byte hex token, per-process, mode `0600`, replaced
20
+ on every boot. The SPA reads it once from `?token=` at boot, then strips it
21
+ from the URL; subsequent calls use the `Authorization: Bearer` header. There is
22
+ no cookie. A host must re-read the token after every respawn.
23
+
24
+ ## Host integration — config root
25
+
26
+ - `agent-config --config-root <path>` (flag) or `EVENT4U_CONFIG_HOME` (env) sets
27
+ AC's config home. Precedence: **flag > env > default**; absent → default
28
+ behavior is unchanged. This lets a host give AC a per-profile config root so
29
+ profile-scoped settings do not silently collide.
30
+
31
+ ## Host integration — embed
32
+
33
+ - `?embed=1` renders AC chrome-stripped (no standalone nav/brand, no theme
34
+ toggle — the host owns the theme); settings deep-links `#/settings` and
35
+ `#/settings/<section>` keep working.
36
+ - **Framing:** AC sends CSP `frame-ancestors 'none'` and is **never** iframe-able
37
+ — a host renders AC's URL in a **separate top-level window**, not a frame.
38
+ - `?theme=light|dark` feeds the pre-paint `data-theme` stamp (no flash).
39
+
40
+ ## Capability discovery
41
+
42
+ - `GET /api/v1/ping` and `agent-config --version --json` carry a `capabilities`
43
+ block: `{ configRoot: true, embed: { supported: true, version: 1, features:
44
+ ['theme', 'deepLink'] } }`. A host checks a capability, not a version number —
45
+ an older AC omits the block and the host degrades to a clear "not supported".
46
+
47
+ ## References
48
+
49
+ - Port range: ADR-012. Enforcement: `src/server/port.ts`.
50
+ - Token transport: `src/server/token.ts`.
51
+ - Capabilities source: `src/shared/capabilities.ts`.
52
+ - Host-side plans: `agents/roadmaps/road-to-ac-embeddable-gui.md`,
53
+ `agents/roadmaps/road-to-reciprocal-ecosystem.md`.
@@ -37,7 +37,7 @@ and violating the no-runtime principle).
37
37
  | Category | Why |
38
38
  |---|---|
39
39
  | **Background processes / daemons** | No spawned subprocesses that outlive the current agent turn |
40
- | **Cross-session persistent state stores** | No SQLite, pgvector, MCP memory servers, Redis, or any store that persists beyond the git working tree — agent-memory layer sunset applies here |
40
+ | **Cross-session persistent state stores** | No SQLite, pgvector, MCP memory servers, Redis, or any store that persists beyond the git working tree — agent-memory layer sunset applies here. **Carve-out (ADR-124 § 6): a gitignored, deterministic, rebuildable build/index artifact under `agents/runtime/state/` is a build output, not a state store** — it carries no authority, is reproducible from the working tree, and is never auto-written memory. State-store test: if deleting the artifact changes *what* the tool can answer rather than only *how fast* it answers, it is a state store and prohibited (a code-graph cache passes — deletion only slows recompute; a vector/embedding index fails — it enables query semantics absent from source, and stays Class C). |
41
41
  | **Event loops / polling** | No `while true; do …; done`, no `inotifywait`, no cron-inside-mission |
42
42
  | **Auto-PR / auto-push** | Hard-Floor (`non-destructive-by-default`): missions never push to remote or open PRs autonomously; those gates require explicit user confirmation every turn |
43
43
  | **Network egress from mission scripts** | Mission scripts may not initiate outbound HTTP calls; skills that need network access declare `allowed_tools` explicitly and go through the normal lethal-trifecta gate |