@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
package/docs/proof.md CHANGED
@@ -9,6 +9,25 @@ public claim binds to resolvable evidence; a skeptic can reproduce
9
9
  every check below on a fresh checkout. This page is itself generated
10
10
  from those sources and fails CI if it drifts.
11
11
 
12
+ ## What this prevents
13
+
14
+ Each row is a failure mode, not a feature — and each cites the ledger
15
+ claim that backs it. A row whose claim stopped resolving would fail this
16
+ page's own generator, so the table cannot outlive its evidence.
17
+
18
+ | Failure this prevents | How | Backed by |
19
+ |---|---|---|
20
+ | A rule says MUST, and nothing anywhere enforces it — so the rule reads as a guarantee while being honour-system. | Each rule declares `enforced_by:`, and the check **resolves** it: a validator reachable from no taskfile, workflow, or hook manifest counts as unwired, not as covered. Undeclared counts as uncovered. | [`enforcement-coverage-resolved`](CLAIMS.md) ⟳ |
21
+ | A shipped artefact carries a hidden-Unicode or instruction-smuggling payload, and reaches consumers because only the source tree was scanned. | Source **and** the condensed projection are scanned in CI; a finding blocks the release before publish, not merely the merge. | [`shipped-artifacts-hidden-instruction-scanned`](CLAIMS.md) ⟳ |
22
+ | A count in public prose drifts from the source, and the marketing number quietly stops being true. | Counts are generated from source and drift-checked; the build fails on a count-shaped prose mention that disagrees, or on two different numbers for the same artefact kind. | [`skill-count`](CLAIMS.md) ⟳ |
23
+ | A host-coverage claim understates or overstates what actually works — for months, on the one surface everybody reads. | The number is pinned by a test over real detection, and the test is re-run as the claim evidence. | [`host-agent-count`](CLAIMS.md) ⟳ |
24
+ | A non-coding domain skill implies proven correctness it never had, because it was forged on a different domain and never checked against one. | Domain skills are labelled unvalidated until they pass a sourced domain-truth fixture, and the validated count is ratcheted so it cannot quietly fall. | [`domain-soundness-scoped`](CLAIMS.md) ⟳ |
25
+ | Behavioural-eval coverage regresses as skills are added, and the suite looks healthy because only the absolute number is reported. | Coverage is measured per tier and ratcheted in CI, so it can only rise; the gap is published rather than implied away. | [`eval-coverage-ratcheted`](CLAIMS.md) ⟳ |
26
+
27
+ ⟳ — the claim carries `exec:` evidence: CI re-runs the command and
28
+ compares its exit code, so a stale row turns the build red rather than
29
+ ageing quietly into marketing.
30
+
12
31
  ## See it run (< 60s, real output)
13
32
 
14
33
  ![The trust surface running green — every "verify it yourself" command below, recorded from a real run](media/proof-demo.gif)
@@ -27,31 +46,68 @@ evidence pointer, or `task check-claims` fails the build.
27
46
  | Claim | Kind | Evidence | Resolves |
28
47
  |---|---|---|---|
29
48
  | The release process is documented as an inheritable runbook + succession doc, and the project's bus-factor (trailing-90-day distinct human reviewers) is tracked and reported truthfully — currently 1, not implied to be more. | qual | `docs/succession.md#trailing 90 days` | ✅ |
30
- | 190 commands. | quant | `src/scripts/check_artefact_count_messaging.ts#Artefact-count messaging gate` | ✅ |
49
+ | 190 commands. | quant | `exec:check_artefact_count_messaging -> 0` | ✅ |
31
50
  | A MEASURED-BUT-NOT-SHIPPED experiment — the thin rule projection reduced eager rule load 78,513 → 13,881 GPT-tokens (whole always-loaded projection 98,529 → 33,897, ~65.6%), but FAILED the quality gate (thin win-rate 36.2% vs required 48%) and does not ship; it un-defers only behind `discipline_profile: essential`. Shipped behavior does NOT include this reduction. Method: `agent-config benchmark` over the pinned token baseline; the baseline is the honest "what the user pays if everything loads eagerly", NOT a synthetic full-corpus strawman (council Q4); quality gate per the Phase-0 paired judge run. | quant | `internal/bench/reports/token-baseline.json#eager_rule_load` | ✅ |
32
51
  | The first cross-vendor parity pass (5 orchestration-corpus tasks × 2 vendors × 3 repeats, identical prompts via the council transport, $0.16) measured real per-host finding-count differences — claude-sonnet-4-5 surfaced ~2× the findings of gpt-4o on the multi-file analysis task (median 11 vs 5) while both vendors were identical on the planted hollow-implementation task (2 vs 2) and perfectly silent on the clean-code negative control (0 vs 0, no spurious findings). The per-task `finding_floor` values are calibrated from the cross-host lower envelope and the gate is armed. | quant | `internal/bench/reports/parity-count.json#min over hosts of median` | ✅ |
33
52
  | On a weak host (claude-haiku-4-5) the package produces a significant, placebo-controlled discipline lift on scope/downstream traps; on a strong host the same measurement is a published null — the package transplants discipline a weak model lacks, not model intelligence. | quant | `docs/benchmark.md#weak-host-specific` | ✅ |
34
- | 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. | qual | `src/scripts/domain_soundness_status.ts#checkRatchet` | ✅ |
35
- | 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. | quant | `internal/evals/domain-soundness-floor.json#validated` | ✅ |
53
+ | 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. | qual | `exec:domain_soundness_status --check -> 0` | ✅ |
54
+ | 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. | quant | `exec:domain_soundness_status -> 0` | ✅ |
36
55
  | On the READ-ONLY FAN-OUT slice family, tier-downshifted subagent dispatch (lite/haiku vs session-tier-proxy sonnet) nets a ≥30% USD-weighted token-cost reduction at held quality — measured 2026-07-08 (n=10 paired live dispatches, 20 telemetry lines): 10/10 exact-match on BOTH arms, 29.4% fewer raw tokens, 76.5% USD-weighted cost reduction at the 3x haiku↔sonnet price ratio. FAMILY-SCOPED — the mechanical-edit family is unmeasured and its downshift (incl. the deferred tier downgrades of existing units) stays gated. Negative control held: an open-ended synthesis/unknown slice never resolves below the session tier (inferSliceTier → medium/inherit, never lite). | quant | `internal/bench/routing-downshift/results-2026-07-08.md#FAMILY-SCOPED PROVE` | ✅ |
56
+ | 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. | quant | `exec:check_enforcement_coverage --check -> 0` | ✅ |
37
57
  | The lift-carrying essential cut (kernel + downstream-changes) keeps a significant weak-host discipline lift at a fraction of the full load's tokens, and the lift is FAMILY- and HOST-SCOPED — measured on three hosts: claude-haiku-4-5 (weak) shows the family-scoped lift (trapE 0.533→1.000, 7/7 discordant, corpus cost 1.71x); claude-sonnet-4-6 (strong) is a ceiling null; gpt-5-mini (non-Claude weak, codex prompt-prepend surface) FAILED replication with headroom (corpus Δ=+0.024 p=0.70, capability trend n.s. — no harm claimed, injection-surface confound documented). Therefore discipline_profile: auto enables the lift only where measured (vendor-granular unknown_defaults). Non-claims — the balanced router profile was removed after a NULL measurement (p=0.81, n=24); no full-tier recommendation exists; no cross-vendor lift is claimed. | quant | `docs/benchmark.md#REPLICATION FAILED` | ✅ |
38
- | 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". | qual | `src/scripts/skill_eval_coverage.ts#checkRatchet` | ✅ |
58
+ | 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". | qual | `exec:skill_eval_coverage --check -> 0` | ✅ |
59
+ | 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. | quant | `docs/benchmark.md#ship-gated-reach` | ✅ |
60
+ | 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. | quant | `exec:vitest run tests/install/toolDetection.test.ts -> 0` | ✅ |
39
61
  | On the fixture corpus (n = 20 before/after pairs, 16 length-controlled within ±25%), the humanizer pass removes every mechanically detected AI-writing tell (mean hard hits 0.9 → 0, cluster score 53.97 → 0 per 500 words, dash density 9.22 → 0), and a blind judge (claude-sonnet-4-5, deterministic per-pair A/B seed) preferred the humanized text in 16/16 length-controlled pairs. Scope note — the "before" fixtures were deliberately tell-seeded, so this measures seeded-tell removal on a self-constructed corpus, NOT real-draft improvement; real-world lift is unmeasured until step 4b has processed real ghostwriter drafts (see the road-to-humanizer-hardening live-usage blocker). | quant | `internal/bench/reports/humanizer-v1.md#prefers the humanized text` | ✅ |
40
- | 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`. | quant | `internal/bench/reports/lexical-ranking.json` | ✅ |
62
+ | 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. | quant | `internal/reports/exec-evidence-feasibility.json#"exec_feasible"` | ✅ |
63
+ | 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. | quant | `exec:measure_lexical_ranking -> 0` | ✅ |
41
64
  | The whole layer is compiled into host agents with zero runtime daemon. | qual | `docs/contracts/no-runtime-boundary.md#file-first, no-runtime suite` | ✅ |
42
65
  | On a 12-fixture option-decision corpus (3 arms × 2 providers, blind rubric judge claude-opus-4-8, pre-registered hypotheses), famous-figure identity framing added nothing beyond the underlying method text (method 5.04 vs figure 4.88, Δ=0.17, sign-test p=0.607), and provider diversity moved judged quality ~15× more than persona identity (provider Δ=2.58 vs identity Δ=0.17); the whole persona layer lifted only +0.08 over bare prompts. Honest null — persona panel-mode stays CUT, evidence-closed. | quant | `internal/bench/reports/persona-placebo.json#honest-null` | ✅ |
43
66
  | The only agent layer that publishes the runs where it changed nothing. Deliberately falsifiable — if a reader finds a comparable agent layer publishing its own honest-null benchmark runs, this line updates; that is the point. | comparative | `docs/benchmark.md#honest` | ✅ |
44
- | 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). | quant | `internal/bench/reports/second-brain-retrieval.json#retrieval-on` | ✅ |
45
- | 105 governed rules. | quant | `src/scripts/check_artefact_count_messaging.ts#Artefact-count messaging gate` | ✅ |
67
+ | 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. | quant | `internal/bench/reports/second-brain-retrieval.json#retrieval-on` | ✅ |
68
+ | 107 governed rules. | quant | `exec:check_artefact_count_messaging -> 0` | ✅ |
46
69
  | On a deterministic multi-session recall corpus, the memory substrate produces a measured, placebo-controlled recall lift — memory-on 27/27 vs no-memory 10/27 and vs equal-byte placebo 9/27 (claude-haiku-4-5, n=9 tasks x 3 seeds, sign test p=0.031 for BOTH pairings). Scoped honestly: this is the context-value upper bound (perfect retrieval on a one-fact-per-task corpus), not retrieval precision under a large store. | quant | `internal/bench/reports/second-brain-delta.json` | ✅ |
47
- | 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. | quant | `internal/bench/reports/second-brain-retrieval.json` | ✅ |
48
- | 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. | qual | `.github/workflows/publish-npm.yml#lint_agent_security` | ✅ |
49
- | 278 skills. | quant | `src/scripts/check_artefact_count_messaging.ts#Artefact-count messaging gate` | ✅ |
70
+ | 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. | qual | `exec:lint_agent_security -> 0` | ✅ |
71
+ | 281 skills. | quant | `exec:check_artefact_count_messaging -> 0` | ✅ |
50
72
  | Removes only its own keys from a shared host config (matched by JSON-pointer + SHA-256), never a neighbour tool's entries. | qual | `docs/contracts/install-layout.md#JSON-pointer` | ✅ |
51
73
  | On the pre-registered 12-fixture defect-finding corpus (three arms, deterministic file-level recall, codex reviewer gpt-5.5), the cross-model team-review arm produced NO recall lift over single-model self-review — all three arms recalled every planted defect (Δ = 0, H1 not met). Honest null, ceiling-limited (recall 1.00 everywhere: the seeded defects are too obvious to discriminate the arms on recall); the only non-null signal is a single self-review false positive on the controversial-but-correct control vs 0 for team/council. No cross-model quality/lift claim binds; team mode stays workflow-value-only. Re-open: a judge-survivable-subtlety corpus or a new model generation. | quant | `internal/bench/reports/defect-finding.json#honest_null` | ✅ |
52
74
  | 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. | quant | `internal/bench/orchestration/pv-a3-results.md#token_delta_provenance: measured` | ✅ |
53
75
 
54
- **24 backed claim(s)** — all evidence pointers resolve in CI.
76
+ **27 backed claim(s)** — all evidence pointers resolve in CI.
77
+
78
+ ### How many of those re-derive themselves
79
+
80
+ **10 of 27** backed claims carry `exec:` evidence —
81
+ CI re-runs the command and compares its exit code to the claim, so a
82
+ stale one turns the build red. The other
83
+ **17** rest on a pointer: CI checks that the artefact
84
+ exists and contains what it should, which cannot distinguish a live
85
+ claim from one whose producer nobody has run in months.
86
+
87
+ That residue is not an oversight, and it is listed rather than rounded
88
+ away. A claim can only re-derive itself when a deterministic command
89
+ carries the verdict in its exit code. These cannot, for the reasons
90
+ given:
91
+
92
+ | Claim | Why it cannot re-execute |
93
+ |---|---|
94
+ | The release process is documented as an inheritable runbook + succession doc, and the project's bus-factor (tr | prose or contract artefact — no exit code carries the verdict |
95
+ | A MEASURED-BUT-NOT-SHIPPED experiment — the thin rule projection reduced eager rule load 78,513 → 13,881 GPT-t | benchmark output — regenerating it needs paid or stochastic model calls no CI job can re-derive |
96
+ | The first cross-vendor parity pass (5 orchestration-corpus tasks × 2 vendors × 3 repeats, identical prompts vi | benchmark output — regenerating it needs paid or stochastic model calls no CI job can re-derive |
97
+ | On a weak host (claude-haiku-4-5) the package produces a significant, placebo-controlled discipline lift on sc | benchmark output — regenerating it needs paid or stochastic model calls no CI job can re-derive |
98
+ | On the READ-ONLY FAN-OUT slice family, tier-downshifted subagent dispatch (lite/haiku vs session-tier-proxy so | benchmark output — regenerating it needs paid or stochastic model calls no CI job can re-derive |
99
+ | The lift-carrying essential cut (kernel + downstream-changes) keeps a significant weak-host discipline lift at | benchmark output — regenerating it needs paid or stochastic model calls no CI job can re-derive |
100
+ | A credential-free prescription layer reads content the host's own web tools cannot fetch at all — Reddit threa | benchmark output — regenerating it needs paid or stochastic model calls no CI job can re-derive |
101
+ | On the fixture corpus (n = 20 before/after pairs, 16 length-controlled within ±25%), the humanizer pass remove | benchmark output — regenerating it needs paid or stochastic model calls no CI job can re-derive |
102
+ | NONE of the backed ledger claims are machine-re-verifiable today — every evidence pointer is checked for exist | prose or contract artefact — no exit code carries the verdict |
103
+ | The whole layer is compiled into host agents with zero runtime daemon. | prose or contract artefact — no exit code carries the verdict |
104
+ | On a 12-fixture option-decision corpus (3 arms × 2 providers, blind rubric judge claude-opus-4-8, pre-register | benchmark output — regenerating it needs paid or stochastic model calls no CI job can re-derive |
105
+ | The only agent layer that publishes the runs where it changed nothing. Deliberately falsifiable — if a reader | benchmark output — regenerating it needs paid or stochastic model calls no CI job can re-derive |
106
+ | On the live end-to-end retrieval benchmark (9 tasks × 3 arms × 3 seeds on claude-haiku, fixture store with key | benchmark output — regenerating it needs paid or stochastic model calls no CI job can re-derive |
107
+ | On a deterministic multi-session recall corpus, the memory substrate produces a measured, placebo-controlled r | benchmark output — regenerating it needs paid or stochastic model calls no CI job can re-derive |
108
+ | Removes only its own keys from a shared host config (matched by JSON-pointer + SHA-256), never a neighbour too | prose or contract artefact — no exit code carries the verdict |
109
+ | On the pre-registered 12-fixture defect-finding corpus (three arms, deterministic file-level recall, codex rev | benchmark output — regenerating it needs paid or stochastic model calls no CI job can re-derive |
110
+ | On the A3 orchestration eval (deterministic verify, measured token deltas), the production-validator subagent | benchmark output — regenerating it needs paid or stochastic model calls no CI job can re-derive |
55
111
 
56
112
  Artefact counts in public prose (skills, commands, governed rules,
57
113
  guidelines, personas) are **generated from source and CI-drift-checked**:
@@ -59,7 +115,7 @@ guidelines, personas) are **generated from source and CI-drift-checked**:
59
115
  fails the build on any count-shaped prose mention that drifts from the
60
116
  source count — or on two different numbers for the same artefact kind.
61
117
 
62
- We also publish our **debt**: 5 claim(s) are logged as
118
+ We also publish our **debt**: 4 claim(s) are logged as
63
119
  `unbacked` inventory in the ledger — not yet bound, and therefore not
64
120
  allowed to carry a marker in public prose. Hiding them would be the
65
121
  opposite of the point.
@@ -80,11 +136,11 @@ shipping theater; the full per-cell data is committed at
80
136
  `internal/bench/reports/persona-placebo.json`.
81
137
 
82
138
  **Behavioural-eval coverage — the honest baseline.** Skill *quality* is only
83
- as good as its measurement. Today **42 of 278** skills carry a behavioural
139
+ as good as its measurement. Today **42 of 281** skills carry a behavioural
84
140
  `evals.json`; the highest-traffic / highest-cost tiers (default-surface +
85
141
  `rich` + routers) are **fully covered (35 of 35)**, the long tail
86
- (7 of 243) is not. We publish that gap rather than imply
87
- "278 evaluated skills": coverage is measured per tier
142
+ (7 of 246) is not. We publish that gap rather than imply
143
+ "281 evaluated skills": coverage is measured per tier
88
144
  (`./scripts-run src/scripts/skill_eval_coverage`), **CI-ratcheted so it can
89
145
  only rise**, and the priority tiers carry a hard **tier floor**: every
90
146
  rich / default-surface / router skill MUST have a behavioural eval or an
@@ -151,12 +207,32 @@ that (`task check-comparison`), so this column can never lie.
151
207
 
152
208
  | Claim | Our evidence | The category | Checkable? |
153
209
  |---|---|---|---|
154
- | No runtime — no background daemon, no state database, no auto-write memory. | [`docs/contracts/no-runtime-boundary.md#file-first`](../docs/contracts/no-runtime-boundary.md) | 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. | ✅ |
210
+ | No resident runtime — no background daemon, no state database or service, no auto-write memory; deterministic, rebuildable file indexes only. | [`docs/contracts/no-runtime-boundary.md#file-first`](../docs/contracts/no-runtime-boundary.md) | 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. | ✅ |
155
211
  | Capability/benchmark results are published — including the runs where the package changed nothing. | [`docs/benchmark.md`](../docs/benchmark.md) | 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. | ✅ |
156
212
  | Every public claim binds to machine-checked evidence. | [`docs/CLAIMS.md`](../docs/CLAIMS.md) | Marketing claims in this category are not bound to a machine-checked ledger a reader can reproduce. | ✅ |
157
213
  | Skills publish their own known limits, each with a witness test. | [`tests/scripts/witness/check_refs_relative_gap.test.ts`](../tests/scripts/witness/check_refs_relative_gap.test.ts) | Published known-limitation surfaces backed by reproducing tests are not a standard artifact in this category. | ✅ |
158
214
  | 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. | [`internal/bench/orchestration/pv-a3-results.md#token_delta_provenance: measured`](../internal/bench/orchestration/pv-a3-results.md) | 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. | ✅ |
159
215
  | 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. | [`internal/bench/reports/persona-placebo.json#honest-null`](../internal/bench/reports/persona-placebo.json) | Named-persona prompts are shipped as a feature across the category without a published A/B separating identity from method. | ✅ |
216
+ | 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. | [`src/scripts/validate_reach_prescriptions.ts`](../src/scripts/validate_reach_prescriptions.ts) | 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. | ✅ |
217
+ | 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. | [`docs/benchmark.md#ship-gated-reach`](../docs/benchmark.md) | 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. | ✅ |
218
+
219
+ ### What each one prevents
220
+
221
+ The same rows, read as failure modes rather than as comparisons. Each names
222
+ something that goes wrong without the control and carries the identical
223
+ resolvable pointer — a projection of the table above, not a second list to
224
+ keep in sync.
225
+
226
+ | Without it | The control | Evidence |
227
+ |---|---|---|
228
+ | A background process keeps running after you stop using it, holds state you did not write, and has to be kept alive and upgraded. | No resident runtime — no background daemon, no state database or service, no auto-write memory; deterministic, rebuildable file indexes only. | [`docs/contracts/no-runtime-boundary.md#file-first`](../docs/contracts/no-runtime-boundary.md) |
229
+ | You adopt on a headline number nobody can re-run, and never learn which of its measurements changed nothing. | Capability/benchmark results are published — including the runs where the package changed nothing. | [`docs/benchmark.md`](../docs/benchmark.md) |
230
+ | A shipped number drifts from the artefact it came from and stays published, because nothing re-checks the claim against its source. | Every public claim binds to machine-checked evidence. | [`docs/CLAIMS.md`](../docs/CLAIMS.md) |
231
+ | 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. | Skills publish their own known limits, each with a witness test. | [`tests/scripts/witness/check_refs_relative_gap.test.ts`](../tests/scripts/witness/check_refs_relative_gap.test.ts) |
232
+ | Evaluating the tool means installing the whole platform first, so the first thing you learn is the setup cost rather than whether it works. | 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. | [`internal/bench/orchestration/pv-a3-results.md#token_delta_provenance: measured`](../internal/bench/orchestration/pv-a3-results.md) |
233
+ | You pay tokens for prompt theater that was never measured against the method text it wraps. | 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. | [`internal/bench/reports/persona-placebo.json#honest-null`](../internal/bench/reports/persona-placebo.json) |
234
+ | 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. | 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. | [`src/scripts/validate_reach_prescriptions.ts`](../src/scripts/validate_reach_prescriptions.ts) |
235
+ | You hand over a credential — or your account — for a read the tools could already do, and you cannot tell which channels actually work because the capability was claimed rather than measured. | 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. | [`docs/benchmark.md#ship-gated-reach`](../docs/benchmark.md) |
160
236
 
161
237
  ## 5. Verify it yourself
162
238
 
@@ -17,6 +17,7 @@ and holds no user data. Threats are about **artifact integrity** and
17
17
  | e | **Malicious metadata / frontmatter injection** — a PR embeds hostile YAML in a skill's frontmatter (e.g. injecting a trigger keyword that causes a dangerous skill to fire in unintended contexts, or adding `permissionMode: bypassPermissions`) | PR contributor adds `permissionMode: bypassPermissions` or a wildcard `allowed_tools: ["*"]` entry to an existing skill's frontmatter; or crafts a trigger keyword to hijack routing | `lint_skill_frontmatter_safety.py` — HIGH-severity block on `bypassPermissions`, wildcard `allowed_tools`, unsafe `execution.type: automated` without safety floor; `lint_hidden_unicode.py` — catches invisible chars inside frontmatter YAML values; PR review gate; `scripts/validate_frontmatter.py` schema validation | Schema validation does not verify trigger-keyword semantic safety (a plausible keyword that causes over-broad firing is not caught) | Extend `validate_frontmatter.py` to flag trigger keywords that match security-sensitive path prefixes (e.g. a skill triggering on `"auth"` when it has `execution.type: automated`) |
18
18
  | f | **Skill self-update — safety-floor rewrite** — an agent is social-engineered (via chat or a PR) into weakening a kernel rule, safety floor, or MCP/tool allowlist | A PR removes the Iron Law block from `non-destructive-by-default.md`; or a chat prompt instructs the agent to edit `security-sensitive-stop.md` to narrow its self-modification clause; or a PR modifies `scope-control` to remove the Hard Floor | `src/rules/security-sensitive-stop.md` — "self-modification via chat" clause: requests to weaken safety floors / kernel rules / MCP allowlists must route through `scope-control` gates; `src/rules/scope-control.md` — kernel-rule edits require own PR + ≥ 24 h soak; `dist/agent-src/` is read-only (source-of-truth rule); `scripts/check_condensation.py` detects Iron-Law section deletion or downgrade | No automated per-rule diff check that fires specifically when a kernel rule's Iron Law section is removed; relies on PR reviewer recognising the file class | Add a CI check (`scripts/check_kernel_rule_integrity.py` — P3+) that asserts Iron Law fenced-code blocks survive unchanged in all files listed in `docs/contracts/kernel-membership.md` |
19
19
  | g | **Subprocess spawn-env inheritance** — AC's own transport spawns an external CLI (the AI-council provider CLIs; consumer-runtime hooks spawn `git`) with the full parent `process.env`, so an attacker-influenced env var in the parent becomes RCE when the child (or a `git` it invokes internally) runs | A poisoned `GIT_EXTERNAL_DIFF` / `core.pager` / `GIT_SSH_COMMAND`, the `GIT_CONFIG_COUNT`/`_KEY_<n>`/`_VALUE_<n>` config-injection trio (sets `core.fsmonitor` → shell on every `git status`), a dynamic-loader `LD_PRELOAD` / `DYLD_INSERT_LIBRARIES` / `GCONV_PATH`, `GIT_ALTERNATE_OBJECT_DIRECTORIES` / `HOSTALIASES`, or a runtime hook `NODE_OPTIONS` / `BASH_ENV` / `PYTHONSTARTUP` present in the parent env executes attacker code inside the spawned process (CWE-426, CWE-88, CWE-427) | `src/scripts/_lib/spawn_env.ts::hardenedSpawnEnv()` scrubs the code-execution-injection env families (deny-by-family: loader `LD_*`/`DYLD_*`/`GCONV_PATH`, git `*_COMMAND` + the whole `GIT_CONFIG`/`GIT_CONFIG_*` family + `GIT_ALTERNATE_OBJECT_DIRECTORIES`/`HOSTALIASES`/`GIT_EXTERNAL_DIFF`/`GIT_SSH_COMMAND`/`GIT_PAGER`/`PAGER`, runtime hooks `NODE_OPTIONS`/`BASH_ENV`/`ENV`/`PYTHON*`/`PERL5*`/`RUBYOPT`, `IFS`) and preserves the rest; wired into ALL consumer-runtime spawns — `clients.ts::_runSubprocess`, `hooks/dispatch_hook.ts`, `roadmap_progress_hook.ts`, `hot_context_hook.ts`; falsifiable regression test in `tests/scripts/ai_council/spawn_env.test.ts` (ADR-123 + 2026-07-21 follow-up) | — (consumer-runtime surface fully hardened; maintainer/CI/install sites are env-controlled, not attacker-influenced) | Spawn sites classified in `docs/spawn-site-policy.md` (Consumer Runtime MUST harden / Maintainer / CI / install exempt with rationale); the deferred lint was rejected — the policy doc is the self-enforcing substitute |
20
+ | h | **Secret committed to version control** (CWE-798) — a credential (API key, token, private key, DB password) is written into a tracked file and committed/pushed, leaking it into history, clones, forks, and public scrapers; `git rm` does not un-leak it | An agent (or developer) pastes or generates a real credential into source, `.env`, config, or a fixture and commits it; once pushed to a public remote it is scraped within minutes | `src/rules/secret-vcs-guard.md` (agent-side write/commit-time block → ask → tiered alternative → rotate-first, VCS-agnostic); `src/scripts/_lib/secret_detector.ts` (regex rule pack + Shannon entropy + keyword detector); `src/scripts/check_secret_leak.ts` wired into `task ci` / `ci-strict` as the diff-scoped, non-bypassable CI net; `src/agent-src/templates/github-workflows/secret-scan.yml` (gitleaks) consumer template | The agent-side gate covers only what the agent writes and is one layer; developer-side / GUI commits need the CI net or host push-protection, which the consumer must enable | Ship + document the `secret-scan.yml` template; recommend enabling GitHub Secret Scanning + Push Protection; the optional TruffleHog step adds live-credential verification. Canonical reference: `secret-vcs-guard.md` + `skill:secrets-management` — do not re-describe here |
20
21
 
21
22
  ## Review cadence
22
23
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@event4u/agent-config",
3
- "version": "9.7.0",
3
+ "version": "9.8.0",
4
4
  "description": "Universal AI Agent OS — audited skills, governance rules, commands and templates for AI coding tools (Claude Code, Cursor, Windsurf, Copilot).",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -71,7 +71,8 @@
71
71
  "test:ts": "vitest run",
72
72
  "prepack": "npm run build && npm run build:discovery && npm run build:mcp-manifest && node src/scripts/prepack-check.mjs",
73
73
  "prepublishOnly": "./scripts-run src/scripts/check_release_includes_discovery",
74
- "prepare": "[ -d .git ] && bash src/scripts/install-hooks.sh || true"
74
+ "prepare": "[ -d .git ] && bash src/scripts/install-hooks.sh || true",
75
+ "postinstall": "node dist/scripts/postinstall_gui.js 2>/dev/null || true"
75
76
  },
76
77
  "publishConfig": {
77
78
  "access": "public",
@@ -103,7 +104,9 @@
103
104
  "js-yaml": "^4.1.0",
104
105
  "open": "^10.2.0",
105
106
  "preact": "^10.29.0",
107
+ "tree-sitter-wasms": "0.1.13",
106
108
  "tsx": "^4.22.3",
109
+ "web-tree-sitter": "0.24.7",
107
110
  "yaml": "^2.9.0",
108
111
  "zod": "^3.25.0",
109
112
  "zod-to-json-schema": "^3.25.0"
@@ -546,6 +546,39 @@ consistency:
546
546
  # reading of whichever source it happened to read).
547
547
  cross_source: "on"
548
548
 
549
+ # --- Documentation screenshots ---
550
+ #
551
+ # When the agent creates screenshots for documentation (e.g. generating a docs
552
+ # site) and embeds them, sensitive data visible on the screenshot MUST be
553
+ # anonymized / pixelated before it ships. Consumed by the `doc-screenshot-hygiene`
554
+ # rule and the `screenshot-hygiene` skill. Automated detection is a helper that
555
+ # flags + pre-redacts — never a clearance; the gate for a data-bearing screenshot
556
+ # is human confirmation (routing into `non-destructive-by-default`, since a
557
+ # shipped screenshot is an irreversible published egress).
558
+ screenshots:
559
+ # Public identity tokens that are SAFE to show unredacted — the maintainer's
560
+ # OWN public handles (e.g. a username shown in an admin panel) plus well-known
561
+ # fake-data tokens. This is NOT a general fake-data dictionary and NOT
562
+ # identity-resolution: everything not on this list is treated as sensitive by
563
+ # default. A public handle co-located with a real name does NOT whitelist the
564
+ # real name. Default: [] (nothing auto-allowed; every identity is human-decided).
565
+ identity_allowlist: []
566
+
567
+ # true | false (default: true)
568
+ # true = terminal / CLI / IDE screenshots are FORBIDDEN (highest leak vector:
569
+ # absolute local paths, env tokens). Use text code blocks with text
570
+ # redaction instead.
571
+ # false = allowed, but still subject to the data-bearing human gate.
572
+ forbid_terminal_capture: true
573
+
574
+ # on | off (default: on)
575
+ # on = a data-bearing screenshot embed is gated behind this-turn human
576
+ # confirmation; uncertain/unresolved regions → redact-or-refuse, never
577
+ # ship-and-hope. Illustrative / no-data screenshots (diagrams, logos,
578
+ # placeholder-only UI) may embed with a stated justification.
579
+ # off = no data-bearing gate (legacy; the anonymization taxonomy still applies).
580
+ data_bearing_gate: "on"
581
+
549
582
  code_style:
550
583
  # minimal | full (default: minimal)
551
584
  #
@@ -1007,6 +1040,16 @@ hooks:
1007
1040
  design_slop:
1008
1041
  enabled: false
1009
1042
 
1043
+ # PreToolUse code-graph nudge (ADR-124 Phase 4). Default-OFF. When enabled
1044
+ # AND a native code-graph engine has built a cache (or the repo ships a
1045
+ # graph.json / SCIP index), WARNS once per session (exit 2, never blocks) as
1046
+ # the agent is about to Grep/Glob or Read a source file: query the graph
1047
+ # first for "who calls / where used / impact" questions (or rebuild if the
1048
+ # index is stale, or build one if absent). Source G's strict block-first-read
1049
+ # mode is deliberately un-ported. Build the cache with `code_graph build`.
1050
+ code_graph:
1051
+ enabled: false
1052
+
1010
1053
  # --- Decision engine ---
1011
1054
  #
1012
1055
  # Controllable gates layered over the observability surface. Absent
@@ -0,0 +1,217 @@
1
+ # Reach channel registry — standalone operator tooling
2
+ # (road-to-internet-reach Phase 1).
3
+ #
4
+ # WHAT THIS FILE IS. A machine-checked answer to three operator questions:
5
+ # which external backend does a reach recipe need, is that backend healthy,
6
+ # and is its install command pinned. Schema:
7
+ # src/scripts/schemas/reach-channels.schema.json; gate:
8
+ # `task check-reach-channels`.
9
+ #
10
+ # WHAT THIS FILE IS NOT. Not a routing table, not a recommendation, not an
11
+ # agent-facing surface. The Phase 0 pre-registered benchmark returned
12
+ # `band: stop` (native arm 12/12, reach arm 0 outright wins), so no router
13
+ # skill ships and NO channel below is routed, preferred, or suggested to an
14
+ # agent. Reading a channel here as "the agent should use this" is a
15
+ # misreading of the verdict.
16
+ #
17
+ # BACKEND ORDER IS THE SWITCH. `backends:` is an ordered candidate list —
18
+ # each entry satisfies the channel on its own (an alternative, never a
19
+ # pipeline stage). Changing the preferred candidate is reordering this list,
20
+ # never editing code. Channel order carries no meaning.
21
+ #
22
+ # LIFECYCLE VOCABULARY IS BORROWED, NOT FORKED. `lifecycle:` uses the four
23
+ # values from docs/contracts/provider-lifecycle.md (`experimental | stable |
24
+ # deprecated | community`). `stable` here means the same thing it means
25
+ # there: a maintainer exercised it against a real run at least once.
26
+ #
27
+ # PINNING IS LOAD-BEARING. Every `install:` string is either an explicitly
28
+ # version-pinned command or an `os-baseline:` sentinel (see below). Moving
29
+ # targets — `latest`, `main`, `master`, `HEAD`, archive/tarball URLs — are
30
+ # rejected by the schema pattern, not by good intentions. The package never
31
+ # executes these strings: a human reads and runs them.
32
+ #
33
+ # OS BASELINES ARE NOT PACKAGE INSTALLS. `curl` and `node` are assumed
34
+ # present: they ship with the OS or the developer's base image. Their
35
+ # prescriptions therefore name the platform's own package manager and stay
36
+ # unpinned wherever a version pin is not meaningful, marked with the
37
+ # explicit `os-baseline:` sentinel so the absence of a pin is a declared
38
+ # decision rather than an oversight. Where a pin IS meaningful — Node's
39
+ # major line — a real versioned formula is used.
40
+ #
41
+ # `jq` IS DELIBERATELY NOT A BACKEND. JSON shaping happens inside the
42
+ # operator's own recipe, downstream of retrieval; it is not a candidate
43
+ # that satisfies a channel. If it ever becomes one, it inherits the same
44
+ # `os-baseline:` convention as curl.
45
+ #
46
+ # PIN PROVENANCE (looked up 2026-07-24, never invented):
47
+ # gh 2.96.0 — `gh --version` on the authoring machine, corroborated by
48
+ # https://api.github.com/repos/cli/cli/releases/latest
49
+ # (tag_name v2.96.0) and
50
+ # https://formulae.brew.sh/api/formula/gh.json (stable 2.96.0).
51
+ # yt-dlp 2026.7.4 — https://pypi.org/pypi/yt-dlp/json (.info.version).
52
+ # node@22 — https://formulae.brew.sh/api/formula/node@22.json
53
+ # (versioned formula exists; stable 22.23.1 at lookup time).
54
+ # asdf plugin `github-cli` — exists in the asdf plugin index
55
+ # (raw.githubusercontent.com/asdf-vm/asdf-plugins → plugins/github-cli).
56
+ # Homebrew has no versioned `gh` formula, so an exactly
57
+ # pinned macOS/Linux prescription goes through asdf.
58
+ # winget id `GitHub.cli` version 2.96.0 — present in the winget-pkgs manifest
59
+ # tree (api.github.com/repos/microsoft/winget-pkgs/contents/
60
+ # manifests/g/GitHub/cli lists 2.96.0).
61
+ #
62
+ # `last_verified:` MUST stay quoted — an unquoted ISO date parses as a
63
+ # timestamp, not a string, and fails the schema type check.
64
+ schema_version: reach-channels-v1
65
+
66
+ channels:
67
+ # Repository metadata: issues, PRs, releases, workflow runs, raw file reads.
68
+ # `free-key`: unauthenticated GitHub API access is rate-limited hard enough
69
+ # that a token is the practical floor. The token is operator-provisioned;
70
+ # nothing here reads, stores, or forwards it.
71
+ - id: github
72
+ description: Repository, issue, release and workflow metadata from the GitHub API.
73
+ tier: free-key
74
+ lifecycle: stable
75
+ override_key: reach.channels.github.backend
76
+ last_verified: "2026-07-24"
77
+ backends:
78
+ - id: gh
79
+ probe_cmd: gh
80
+ probe_args: ["--version"]
81
+ install:
82
+ darwin: asdf plugin add github-cli && asdf install github-cli 2.96.0
83
+ linux: asdf plugin add github-cli && asdf install github-cli 2.96.0
84
+ win32: winget install --id GitHub.cli --version 2.96.0
85
+ default: asdf plugin add github-cli && asdf install github-cli 2.96.0
86
+
87
+ # Video metadata and subtitle tracks. `yt-dlp` is NOT installed on the
88
+ # authoring machine, and that is expected: this file is validated offline
89
+ # against the schema only, so an absent backend cannot fail the gate. Its
90
+ # health is the probe layer's question, never the registry's.
91
+ # `experimental` for exactly that reason — the shape is right, no
92
+ # maintainer has exercised this backend against a real run.
93
+ - id: youtube
94
+ description: Video metadata and subtitle tracks for a public video URL.
95
+ tier: zero-config
96
+ lifecycle: experimental
97
+ override_key: reach.channels.youtube.backend
98
+ last_verified: "2026-07-24"
99
+ backends:
100
+ - id: yt-dlp
101
+ probe_cmd: yt-dlp
102
+ probe_args: ["--version"]
103
+ install:
104
+ darwin: pipx install yt-dlp==2026.7.4
105
+ linux: pipx install yt-dlp==2026.7.4
106
+ win32: py -m pipx install yt-dlp==2026.7.4
107
+ default: pipx install yt-dlp==2026.7.4
108
+
109
+ # Feed retrieval. Two independent candidates: fetch the feed with curl, or
110
+ # fetch-and-parse it in a Node one-liner. Either satisfies the channel.
111
+ - id: rss
112
+ description: Atom and RSS feed retrieval for a known feed URL.
113
+ tier: zero-config
114
+ lifecycle: stable
115
+ override_key: reach.channels.rss.backend
116
+ last_verified: "2026-07-24"
117
+ backends:
118
+ - id: curl
119
+ probe_cmd: curl
120
+ probe_args: ["--version"]
121
+ install:
122
+ darwin: "os-baseline: macOS ships curl (8.7.1 observed 2026-07-24) at /usr/bin/curl — no package install prescribed"
123
+ linux: "os-baseline: distro-provided curl package (apt / dnf / apk) — version tracks the distro, no pin meaningful"
124
+ win32: "os-baseline: Windows 10+ ships curl.exe in System32 — no package install prescribed"
125
+ default: "os-baseline: a system curl is assumed present; if absent, install it from the platform package manager — never a piped remote installer"
126
+ - id: node
127
+ probe_cmd: node
128
+ probe_args: ["--version"]
129
+ install:
130
+ darwin: brew install node@22
131
+ linux: "os-baseline: distro or NodeSource nodejs package — version tracks the chosen channel, no pin meaningful here"
132
+ win32: "os-baseline: winget package OpenJS.NodeJS.LTS — version tracks the LTS line, no pin meaningful here"
133
+ default: "os-baseline: any Node runtime at or above this package's engines floor (>=20.11.0) already on PATH"
134
+
135
+ # Single-page read. Same two candidates as `rss`: curl fetches the bytes;
136
+ # Node covers the case where the extraction step runs in-process.
137
+ - id: web-read
138
+ description: Single public web page fetch for a URL the operator already has.
139
+ tier: zero-config
140
+ lifecycle: stable
141
+ override_key: reach.channels.web-read.backend
142
+ last_verified: "2026-07-24"
143
+ backends:
144
+ - id: curl
145
+ probe_cmd: curl
146
+ probe_args: ["--version"]
147
+ install:
148
+ darwin: "os-baseline: macOS ships curl (8.7.1 observed 2026-07-24) at /usr/bin/curl — no package install prescribed"
149
+ linux: "os-baseline: distro-provided curl package (apt / dnf / apk) — version tracks the distro, no pin meaningful"
150
+ win32: "os-baseline: Windows 10+ ships curl.exe in System32 — no package install prescribed"
151
+ default: "os-baseline: a system curl is assumed present; if absent, install it from the platform package manager — never a piped remote installer"
152
+ - id: node
153
+ probe_cmd: node
154
+ probe_args: ["--version"]
155
+ install:
156
+ darwin: brew install node@22
157
+ linux: "os-baseline: distro or NodeSource nodejs package — version tracks the chosen channel, no pin meaningful here"
158
+ win32: "os-baseline: winget package OpenJS.NodeJS.LTS — version tracks the LTS line, no pin meaningful here"
159
+ default: "os-baseline: any Node runtime at or above this package's engines floor (>=20.11.0) already on PATH"
160
+
161
+ # Discussion search over the public Hacker News search API. Keyless, and
162
+ # the endpoint returns JSON directly — one candidate is enough.
163
+ - id: hackernews
164
+ description: Discussion and comment search over the public Hacker News search API.
165
+ tier: zero-config
166
+ lifecycle: stable
167
+ override_key: reach.channels.hackernews.backend
168
+ last_verified: "2026-07-24"
169
+ backends:
170
+ - id: curl
171
+ probe_cmd: curl
172
+ probe_args: ["--version"]
173
+ install:
174
+ darwin: "os-baseline: macOS ships curl (8.7.1 observed 2026-07-24) at /usr/bin/curl — no package install prescribed"
175
+ linux: "os-baseline: distro-provided curl package (apt / dnf / apk) — version tracks the distro, no pin meaningful"
176
+ win32: "os-baseline: Windows 10+ ships curl.exe in System32 — no package install prescribed"
177
+ default: "os-baseline: a system curl is assumed present; if absent, install it from the platform package manager — never a piped remote installer"
178
+
179
+ - id: reddit
180
+ description: Reddit discussion reading in two tiers — durable Atom text, and time-bounded ranked HTML.
181
+ tier: zero-config
182
+ lifecycle: experimental
183
+ override_key: reach.channels.reddit.backend
184
+ last_verified: "2026-07-25"
185
+ backends:
186
+ - id: curl
187
+ probe_cmd: curl
188
+ probe_args: ["--version"]
189
+ install:
190
+ darwin: "os-baseline: macOS ships curl (8.7.1 observed 2026-07-25) at /usr/bin/curl — no package install prescribed"
191
+ linux: "os-baseline: distro-provided curl package (apt / dnf / apk) — version tracks the distro, no pin meaningful"
192
+ win32: "os-baseline: Windows 10+ ships curl.exe in System32 — no package install prescribed"
193
+ default: "os-baseline: a system curl is assumed present; if absent, install it from the platform package manager — never a piped remote installer"
194
+ - id: node
195
+ probe_cmd: node
196
+ probe_args: ["--version"]
197
+ install:
198
+ darwin: brew install node@22
199
+ linux: "os-baseline: distro or NodeSource nodejs package — version tracks the chosen channel, no pin meaningful here"
200
+ win32: "os-baseline: winget package OpenJS.NodeJS.LTS — version tracks the LTS line, no pin meaningful here"
201
+ default: "os-baseline: any Node runtime at or above this package's engines floor (>=20.11.0) already on PATH"
202
+
203
+ - id: twitter-oembed
204
+ description: Single public tweet read through the platform's own oEmbed endpoint, credential-free.
205
+ tier: zero-config
206
+ lifecycle: experimental
207
+ override_key: reach.channels.twitter-oembed.backend
208
+ last_verified: "2026-07-25"
209
+ backends:
210
+ - id: curl
211
+ probe_cmd: curl
212
+ probe_args: ["--version"]
213
+ install:
214
+ darwin: "os-baseline: macOS ships curl (8.7.1 observed 2026-07-25) at /usr/bin/curl — no package install prescribed"
215
+ linux: "os-baseline: distro-provided curl package (apt / dnf / apk) — version tracks the distro, no pin meaningful"
216
+ win32: "os-baseline: Windows 10+ ships curl.exe in System32 — no package install prescribed"
217
+ default: "os-baseline: a system curl is assumed present; if absent, install it from the platform package manager — never a piped remote installer"