@event4u/agent-config 14.11.0 → 14.12.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 (350) hide show
  1. package/.augment-plugin/marketplace.json +3 -3
  2. package/.augment-plugin/plugin.json +1 -1
  3. package/.claude-plugin/marketplace.json +1 -1
  4. package/CHANGELOG.md +156 -538
  5. package/README.md +1 -1
  6. package/dist/agent-src/contexts/execution/evidence-discipline.md +26 -0
  7. package/dist/agent-src/skills/code-refactoring/SKILL.md +45 -1
  8. package/dist/agent-src/skills/code-review/SKILL.md +65 -6
  9. package/dist/agent-src/skills/command-writing/SKILL.md +35 -0
  10. package/dist/agent-src/skills/existing-ui-audit/SKILL.md +8 -1
  11. package/dist/agent-src/skills/project-analysis-core/SKILL.md +23 -0
  12. package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +29 -12
  13. package/dist/agent-src/skills/skill-writing/references/procedure.md +24 -2
  14. package/dist/agent-src/skills/storybook-workshop/SKILL.md +9 -0
  15. package/dist/agent-src/skills/ui-component-architect/SKILL.md +8 -0
  16. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  17. package/dist/cli-delegate/{chunk-L43NCYPB.js → chunk-JCW7ZLHK.js} +5 -0
  18. package/dist/cli-delegate/{chunk-236PNQZK.js → chunk-JJA2QEWA.js} +1 -1
  19. package/dist/cli-delegate/cmd_export.js +2 -2
  20. package/dist/cli-delegate/cmd_prune.js +2 -2
  21. package/dist/cli-delegate/cmd_settings_migrate.js +2 -2
  22. package/dist/cli-delegate/cmd_settings_set.js +1 -1
  23. package/dist/cli-delegate/cmd_sync.js +2 -2
  24. package/dist/cli-delegate/cmd_uninstall.js +2 -2
  25. package/dist/cli-delegate/cmd_validate.js +2 -2
  26. package/dist/discovery/deprecation-report.md +1 -1
  27. package/dist/discovery/discovery-manifest.json +10 -10
  28. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  29. package/dist/discovery/discovery-manifest.summary.md +1 -1
  30. package/dist/discovery/dormancy-report.md +1 -1
  31. package/dist/discovery/orphan-report.md +1 -1
  32. package/dist/discovery/packs.json +2 -2
  33. package/dist/discovery/trust-report.md +1 -1
  34. package/dist/discovery/workspaces.json +2 -2
  35. package/dist/hooks/dispatch.js +1081 -879
  36. package/dist/install/install.mjs +5 -0
  37. package/dist/mcp/registry-manifest.json +2 -2
  38. package/dist/mcp/server.json +2 -2
  39. package/dist/server/schemas/settings.js +3 -0
  40. package/docs/contracts/settings-classes.md +24 -4
  41. package/docs/guidelines/agent-infra/downstream-changes-mechanics.md +91 -0
  42. package/docs/guidelines/code-clarity.md +21 -0
  43. package/docs/guidelines/redundancy-taxonomy.md +180 -0
  44. package/package.json +6 -2
  45. package/src/config/agent-settings.template.yml +16 -0
  46. package/src/config/budgets.yml +19 -0
  47. package/src/config/ci-local-parity.yml +15 -0
  48. package/src/config/discovery/prompt-patterns.yml +56 -0
  49. package/src/config/estate-count-budget.json +8 -3
  50. package/src/config/gate-coverage.yml +191 -6
  51. package/src/config/gate-violation-baselines.json +3 -3
  52. package/src/config/pack-size-budget.json +39 -12
  53. package/src/config/preamble-payload-budget.json +97 -71
  54. package/src/config/routing-coverage-seed.json +29 -0
  55. package/src/config/suggestion-capture.json +28 -0
  56. package/src/config/surface-matrix.yml +21 -2
  57. package/src/config/web-launch-readiness.json +188 -0
  58. package/src/scripts/_lib/gate_baseline.ts +150 -1
  59. package/src/scripts/_lib/skill_estate.ts +115 -0
  60. package/src/scripts/ai_council/argument_exhaustion.ts +130 -0
  61. package/src/scripts/check_bundle_path_leakage.ts +162 -7
  62. package/src/scripts/check_command_examples.ts +557 -0
  63. package/src/scripts/check_estate_count.ts +122 -3
  64. package/src/scripts/check_preamble_payload_budget.ts +30 -3
  65. package/src/scripts/check_routing_coverage.ts +352 -0
  66. package/src/scripts/check_score_contract.ts +505 -0
  67. package/src/scripts/check_skill_admissions.ts +514 -0
  68. package/src/scripts/check_web_launch_readiness.ts +705 -0
  69. package/src/scripts/description_route_check.ts +494 -0
  70. package/src/scripts/hook_manifest.json +1 -1
  71. package/src/scripts/hook_manifest.yaml +29 -2
  72. package/src/scripts/hooks/concern_registry.ts +2 -0
  73. package/src/scripts/hooks/suggestion_capture_hook.ts +368 -0
  74. package/src/scripts/lint_budget_ownership.ts +54 -4
  75. package/src/scripts/lint_skill_trigger_corpus.ts +349 -0
  76. package/src/scripts/pack_install_smoke.ts +363 -0
  77. package/src/scripts/pr_conflict_census.ts +187 -0
  78. package/src/scripts/report_pack_delta.ts +204 -0
  79. package/src/scripts/select_analysis_mode.ts +112 -0
  80. package/src/scripts/sync_pr_branch.ts +40 -1
  81. package/src/server/schemas/settings.ts +5 -0
  82. package/dist/agent-src/skills/accessibility-auditor/evals/evals.json +0 -15
  83. package/dist/agent-src/skills/agent-security-review/evals/triggers.json +0 -52
  84. package/dist/agent-src/skills/ai-code-blindspots/evals/triggers.json +0 -52
  85. package/dist/agent-src/skills/alerting-doctrine/evals/triggers.json +0 -17
  86. package/dist/agent-src/skills/analysis-skill-router/evals/evals.json +0 -13
  87. package/dist/agent-src/skills/brand/evals/triggers.json +0 -17
  88. package/dist/agent-src/skills/brand-asset-generation/evals/triggers.json +0 -17
  89. package/dist/agent-src/skills/brand-audit/evals/triggers.json +0 -17
  90. package/dist/agent-src/skills/brand-identity/evals/triggers.json +0 -17
  91. package/dist/agent-src/skills/brand-strategy/evals/triggers.json +0 -17
  92. package/dist/agent-src/skills/brand-to-tokens/evals/triggers.json +0 -17
  93. package/dist/agent-src/skills/bug-analyzer/evals/evals.json +0 -13
  94. package/dist/agent-src/skills/canvas-design/evals/triggers.json +0 -17
  95. package/dist/agent-src/skills/character-consistency/evals/evals.json +0 -16
  96. package/dist/agent-src/skills/code-intelligence/evals/triggers.json +0 -52
  97. package/dist/agent-src/skills/code-review/evals/evals.json +0 -100
  98. package/dist/agent-src/skills/command-routing/evals/evals.json +0 -14
  99. package/dist/agent-src/skills/complexity-first-planning/evals/triggers.json +0 -17
  100. package/dist/agent-src/skills/contract-review/evals/triggers.json +0 -17
  101. package/dist/agent-src/skills/conventional-commits-writing/evals/evals.json +0 -15
  102. package/dist/agent-src/skills/corpus-grounding/evals/triggers.json +0 -17
  103. package/dist/agent-src/skills/dashboard-design/evals/evals.json +0 -16
  104. package/dist/agent-src/skills/dcf-modeling/evals/domain-truth.json +0 -29
  105. package/dist/agent-src/skills/dcf-modeling/evals/evals.json +0 -20
  106. package/dist/agent-src/skills/decision-record/evals/evals.json +0 -20
  107. package/dist/agent-src/skills/decision-record/evals/triggers.json +0 -87
  108. package/dist/agent-src/skills/design-intelligence/evals/evals.json +0 -14
  109. package/dist/agent-src/skills/design-intelligence/evals/triggers.json +0 -17
  110. package/dist/agent-src/skills/design-system-capture/evals/evals.json +0 -15
  111. package/dist/agent-src/skills/design-tokens/evals/triggers.json +0 -17
  112. package/dist/agent-src/skills/design-variations/evals/triggers.json +0 -17
  113. package/dist/agent-src/skills/developer-like-execution/evals/evals.json +0 -16
  114. package/dist/agent-src/skills/doc-coauthoring/evals/evals.json +0 -16
  115. package/dist/agent-src/skills/doc-coauthoring/evals/triggers.json +0 -17
  116. package/dist/agent-src/skills/docx-authoring/evals/triggers.json +0 -52
  117. package/dist/agent-src/skills/dpa-review/evals/triggers.json +0 -17
  118. package/dist/agent-src/skills/editorial-calendar/evals/domain-truth.json +0 -16
  119. package/dist/agent-src/skills/editorial-calendar/evals/evals.json +0 -16
  120. package/dist/agent-src/skills/eloquent/evals/triggers.json +0 -17
  121. package/dist/agent-src/skills/estimate-ticket/evals/evals.json +0 -16
  122. package/dist/agent-src/skills/estimate-ticket/evals/output-schema.yml +0 -20
  123. package/dist/agent-src/skills/estimate-ticket/evals/triggers.json +0 -19
  124. package/dist/agent-src/skills/evaluate-llm-feature/evals/triggers.json +0 -52
  125. package/dist/agent-src/skills/existing-ui-audit/evals/triggers.json +0 -47
  126. package/dist/agent-src/skills/experiment-loop/evals/output-schema.yml +0 -27
  127. package/dist/agent-src/skills/experiment-loop/evals/triggers.json +0 -17
  128. package/dist/agent-src/skills/fe-design/evals/triggers.json +0 -67
  129. package/dist/agent-src/skills/forecasting/evals/domain-truth.json +0 -29
  130. package/dist/agent-src/skills/forecasting/evals/evals.json +0 -20
  131. package/dist/agent-src/skills/forensics-report/evals/triggers.json +0 -17
  132. package/dist/agent-src/skills/frontend-render-security/evals/triggers.json +0 -52
  133. package/dist/agent-src/skills/fundraising-narrative/evals/domain-truth.json +0 -16
  134. package/dist/agent-src/skills/fundraising-narrative/evals/evals.json +0 -16
  135. package/dist/agent-src/skills/gated-reach/evals/triggers.json +0 -72
  136. package/dist/agent-src/skills/github-ci/evals/evals.json +0 -25
  137. package/dist/agent-src/skills/history-design/evals/triggers.json +0 -17
  138. package/dist/agent-src/skills/html-deck/evals/triggers.json +0 -17
  139. package/dist/agent-src/skills/humanizer/evals/strip_fixtures.json +0 -57
  140. package/dist/agent-src/skills/humanizer/evals/triggers.json +0 -17
  141. package/dist/agent-src/skills/iconography/evals/triggers.json +0 -17
  142. package/dist/agent-src/skills/image-analyser/evals/triggers.json +0 -17
  143. package/dist/agent-src/skills/image-creator/evals/triggers.json +0 -17
  144. package/dist/agent-src/skills/image-editing/evals/triggers.json +0 -17
  145. package/dist/agent-src/skills/image-generation/evals/triggers.json +0 -17
  146. package/dist/agent-src/skills/image-provider-routing/evals/triggers.json +0 -17
  147. package/dist/agent-src/skills/incident-commander/evals/domain-truth.json +0 -16
  148. package/dist/agent-src/skills/incident-commander/evals/evals.json +0 -20
  149. package/dist/agent-src/skills/js-library-packaging/evals/triggers.json +0 -17
  150. package/dist/agent-src/skills/judge-artifact-completeness/evals/triggers.json +0 -17
  151. package/dist/agent-src/skills/judge-injection-defense/evals/triggers.json +0 -17
  152. package/dist/agent-src/skills/judge-synthesis/evals/triggers.json +0 -17
  153. package/dist/agent-src/skills/launch-readiness/evals/evals.json +0 -21
  154. package/dist/agent-src/skills/learning-tutor/evals/triggers.json +0 -52
  155. package/dist/agent-src/skills/legal-intake-triage/evals/triggers.json +0 -17
  156. package/dist/agent-src/skills/legal-practice-profile/evals/triggers.json +0 -17
  157. package/dist/agent-src/skills/license-compliance-audit/evals/triggers.json +0 -52
  158. package/dist/agent-src/skills/license-compliance-borrow-check/evals/triggers.json +0 -52
  159. package/dist/agent-src/skills/license-compliance-credits/evals/triggers.json +0 -52
  160. package/dist/agent-src/skills/llm-provider-knowledge/evals/triggers.json +0 -20
  161. package/dist/agent-src/skills/logging-monitoring/evals/evals.json +0 -16
  162. package/dist/agent-src/skills/logo-generation/evals/triggers.json +0 -17
  163. package/dist/agent-src/skills/messaging-architecture/evals/domain-truth.json +0 -16
  164. package/dist/agent-src/skills/messaging-architecture/evals/evals.json +0 -16
  165. package/dist/agent-src/skills/monorepo-workspace/evals/triggers.json +0 -17
  166. package/dist/agent-src/skills/nda-triage/evals/triggers.json +0 -17
  167. package/dist/agent-src/skills/operational-readiness/evals/triggers.json +0 -17
  168. package/dist/agent-src/skills/pdf-tools/evals/triggers.json +0 -52
  169. package/dist/agent-src/skills/perf-feedback-craft/evals/evals.json +0 -16
  170. package/dist/agent-src/skills/persona-improvement/evals/triggers.json +0 -52
  171. package/dist/agent-src/skills/php-coder/evals/triggers.json +0 -17
  172. package/dist/agent-src/skills/prediction-pool-optimizer/evals/triggers.json +0 -21
  173. package/dist/agent-src/skills/prompt-engineering-image/evals/triggers.json +0 -17
  174. package/dist/agent-src/skills/prompt-engineering-patterns/evals/evals.json +0 -16
  175. package/dist/agent-src/skills/prompt-validator/evals/triggers.json +0 -17
  176. package/dist/agent-src/skills/quality-tools/evals/evals.json +0 -15
  177. package/dist/agent-src/skills/reasoning-orchestrator/evals/triggers.json +0 -17
  178. package/dist/agent-src/skills/refine-prompt/evals/evals.json +0 -16
  179. package/dist/agent-src/skills/refine-ticket/evals/evals.json +0 -16
  180. package/dist/agent-src/skills/refine-ticket/evals/output-schema.yml +0 -16
  181. package/dist/agent-src/skills/refine-ticket/evals/triggers.json +0 -17
  182. package/dist/agent-src/skills/release-comms/evals/evals.json +0 -16
  183. package/dist/agent-src/skills/rice-prioritization/evals/evals.json +0 -20
  184. package/dist/agent-src/skills/runway-cognition/evals/domain-truth.json +0 -29
  185. package/dist/agent-src/skills/runway-cognition/evals/evals.json +0 -20
  186. package/dist/agent-src/skills/scenario-modeling/evals/domain-truth.json +0 -29
  187. package/dist/agent-src/skills/scenario-modeling/evals/evals.json +0 -20
  188. package/dist/agent-src/skills/schema-review/evals/triggers.json +0 -17
  189. package/dist/agent-src/skills/screenshot-hygiene/evals/triggers.json +0 -52
  190. package/dist/agent-src/skills/security-maturity-assessment/evals/triggers.json +0 -52
  191. package/dist/agent-src/skills/server-hardening/evals/triggers.json +0 -17
  192. package/dist/agent-src/skills/skill-writing/evals/triggers.json +0 -17
  193. package/dist/agent-src/skills/spreadsheet-authoring/evals/triggers.json +0 -47
  194. package/dist/agent-src/skills/storybook-workshop/evals/triggers.json +0 -17
  195. package/dist/agent-src/skills/subagent-orchestration/evals/evals.json +0 -60
  196. package/dist/agent-src/skills/supply-chain-intake/evals/triggers.json +0 -52
  197. package/dist/agent-src/skills/systematic-debugging/evals/evals.json +0 -20
  198. package/dist/agent-src/skills/test-case-discovery/evals/triggers.json +0 -52
  199. package/dist/agent-src/skills/test-driven-development/evals/evals.json +0 -16
  200. package/dist/agent-src/skills/threat-modeling/evals/evals.json +0 -21
  201. package/dist/agent-src/skills/typography-system/evals/evals.json +0 -14
  202. package/dist/agent-src/skills/typography-system/evals/triggers.json +0 -17
  203. package/dist/agent-src/skills/unit-economics-modeling/evals/domain-truth.json +0 -40
  204. package/dist/agent-src/skills/unit-economics-modeling/evals/evals.json +0 -24
  205. package/dist/agent-src/skills/verify-completion-evidence/evals/evals.json +0 -16
  206. package/dist/agent-src/skills/verify-repair-loop/evals/output-schema.yml +0 -20
  207. package/dist/agent-src/skills/verify-repair-loop/evals/triggers.json +0 -17
  208. package/dist/agent-src/skills/vision-articulation/evals/evals.json +0 -16
  209. package/dist/agent-src/skills/voice-and-tone-design/evals/evals.json +0 -16
  210. package/dist/agent-src/skills/wireframe/evals/triggers.json +0 -17
  211. package/dist/agent-src/skills/workspace-link/evals/triggers.json +0 -17
  212. package/dist/agent-src/skills/worktree-lifecycle/evals/evals.json +0 -38
  213. package/dist/agent-src/skills/worktree-lifecycle/evals/triggers.json +0 -52
  214. package/dist/cli/agent-config.js.map +0 -1
  215. package/dist/cli/bash/runBash.js.map +0 -1
  216. package/dist/cli/commands/commands.js.map +0 -1
  217. package/dist/cli/commands/config.js.map +0 -1
  218. package/dist/cli/commands/doctorShell.js.map +0 -1
  219. package/dist/cli/commands/mcpServer.js.map +0 -1
  220. package/dist/cli/commands/packs.js.map +0 -1
  221. package/dist/cli/commands/profiles.js.map +0 -1
  222. package/dist/cli/commands/recordTriggerEval.js.map +0 -1
  223. package/dist/cli/commands/rtkDetect.js.map +0 -1
  224. package/dist/cli/commands/settings.js.map +0 -1
  225. package/dist/cli/commands/uiAudit.js.map +0 -1
  226. package/dist/cli/commands/uiRender.js.map +0 -1
  227. package/dist/cli/commands/uiServe.js.map +0 -1
  228. package/dist/cli/commands/versions.js.map +0 -1
  229. package/dist/cli/commands/workspaces.js.map +0 -1
  230. package/dist/cli/configRoot.js.map +0 -1
  231. package/dist/cli/discovery/loadManifest.js.map +0 -1
  232. package/dist/cli/firstRunNotice.js.map +0 -1
  233. package/dist/cli/help.js.map +0 -1
  234. package/dist/cli/initRouting.js.map +0 -1
  235. package/dist/cli/log/logger.js.map +0 -1
  236. package/dist/cli/main.js.map +0 -1
  237. package/dist/cli/mcp/content.js.map +0 -1
  238. package/dist/cli/mcp/dispatch.js.map +0 -1
  239. package/dist/cli/mcp/stdio.js.map +0 -1
  240. package/dist/cli/paths.js.map +0 -1
  241. package/dist/cli/python/knowledge_ingest.js.map +0 -1
  242. package/dist/cli/python/workspace_analytics.js.map +0 -1
  243. package/dist/cli/python/workspace_crypto.js.map +0 -1
  244. package/dist/cli/python/workspace_documents.js.map +0 -1
  245. package/dist/cli/python/workspace_drive.js.map +0 -1
  246. package/dist/cli/python/workspace_drive_health.js.map +0 -1
  247. package/dist/cli/python/workspace_explain.js.map +0 -1
  248. package/dist/cli/python/workspace_hosts.js.map +0 -1
  249. package/dist/cli/python/workspace_inbox.js.map +0 -1
  250. package/dist/cli/python/workspace_render.js.map +0 -1
  251. package/dist/cli/python/workspace_roles.js.map +0 -1
  252. package/dist/cli/python/workspace_secrets.js.map +0 -1
  253. package/dist/cli/python/workspace_sessions.js.map +0 -1
  254. package/dist/cli/python/workspace_skills.js.map +0 -1
  255. package/dist/cli/registry.js.map +0 -1
  256. package/dist/install/agentSwitchDetection.js.map +0 -1
  257. package/dist/install/agentSwitchProfile.js.map +0 -1
  258. package/dist/install/atomic.js.map +0 -1
  259. package/dist/install/claudePathsPlan.js.map +0 -1
  260. package/dist/install/conflict.js.map +0 -1
  261. package/dist/install/detect.js.map +0 -1
  262. package/dist/install/emit_host_rules_cli.js.map +0 -1
  263. package/dist/install/globalRuleLayers.js.map +0 -1
  264. package/dist/install/hostLayerFingerprint.js.map +0 -1
  265. package/dist/install/partitionEligibility.js.map +0 -1
  266. package/dist/install/paths.js.map +0 -1
  267. package/dist/install/plan.js.map +0 -1
  268. package/dist/install/preflight.js.map +0 -1
  269. package/dist/install/rtkDetection.js.map +0 -1
  270. package/dist/install/ruleInScope.js.map +0 -1
  271. package/dist/install/ruleLayerPartition.js.map +0 -1
  272. package/dist/install/rule_scope.js.map +0 -1
  273. package/dist/install/rule_scope_cli.js.map +0 -1
  274. package/dist/install/selectedTools.js.map +0 -1
  275. package/dist/install/toolDetection.js.map +0 -1
  276. package/dist/install/txlog.js.map +0 -1
  277. package/dist/install/types.js.map +0 -1
  278. package/dist/install/wizard-plan.js.map +0 -1
  279. package/dist/install/wizardDismissals.js.map +0 -1
  280. package/dist/scripts/_lib/agent_settings.js.map +0 -1
  281. package/dist/scripts/_lib/agent_src.js.map +0 -1
  282. package/dist/scripts/_lib/claude_builtin_names.js.map +0 -1
  283. package/dist/scripts/_lib/claude_plugin.js.map +0 -1
  284. package/dist/scripts/_lib/claude_settings_hooks.js.map +0 -1
  285. package/dist/scripts/_lib/compile_time_toggles.js.map +0 -1
  286. package/dist/scripts/_lib/environment_detector.js.map +0 -1
  287. package/dist/scripts/_lib/host_launch.js.map +0 -1
  288. package/dist/scripts/_lib/install_layout.js.map +0 -1
  289. package/dist/scripts/_lib/installed_lock.js.map +0 -1
  290. package/dist/scripts/_lib/lean_projection_mode.js.map +0 -1
  291. package/dist/scripts/_lib/model_tier.js.map +0 -1
  292. package/dist/scripts/_lib/prune_empty_dirs.js.map +0 -1
  293. package/dist/scripts/_lib/scoped_projection.js.map +0 -1
  294. package/dist/scripts/_lib/script_output.js.map +0 -1
  295. package/dist/scripts/_lib/spawn_env.js.map +0 -1
  296. package/dist/scripts/_lib/surface_tiers.js.map +0 -1
  297. package/dist/scripts/_lib/token_count.js.map +0 -1
  298. package/dist/scripts/_lib/trigger_eval_floors.js.map +0 -1
  299. package/dist/scripts/_lib/ui_surface.js.map +0 -1
  300. package/dist/scripts/_lib/user_global_paths.js.map +0 -1
  301. package/dist/scripts/ai_council/modes.js.map +0 -1
  302. package/dist/scripts/ai_council/transport_resolver.js.map +0 -1
  303. package/dist/scripts/condense.js.map +0 -1
  304. package/dist/scripts/project_thin_rules.js.map +0 -1
  305. package/dist/server/app.js.map +0 -1
  306. package/dist/server/io/atomicMultiWrite.js.map +0 -1
  307. package/dist/server/io/atomicWrite.js.map +0 -1
  308. package/dist/server/io/sharedWriteCheck.js.map +0 -1
  309. package/dist/server/io/substituteTemplate.js.map +0 -1
  310. package/dist/server/io/yamlIO.js.map +0 -1
  311. package/dist/server/nicknameResolver.js.map +0 -1
  312. package/dist/server/port.js.map +0 -1
  313. package/dist/server/routes/discovery.js.map +0 -1
  314. package/dist/server/routes/install.js.map +0 -1
  315. package/dist/server/routes/ping.js.map +0 -1
  316. package/dist/server/routes/schema.js.map +0 -1
  317. package/dist/server/routes/settings.js.map +0 -1
  318. package/dist/server/routes/settingsChanges.js.map +0 -1
  319. package/dist/server/routes/userMd.js.map +0 -1
  320. package/dist/server/routes/wizard.js.map +0 -1
  321. package/dist/server/routes/workspace.js.map +0 -1
  322. package/dist/server/schemas/settings.js.map +0 -1
  323. package/dist/server/serverInfo.js.map +0 -1
  324. package/dist/server/token.js.map +0 -1
  325. package/dist/server/writeRoot.js.map +0 -1
  326. package/dist/shared/capabilities.js.map +0 -1
  327. package/dist/shared/interactiveContext.js.map +0 -1
  328. package/dist/shared/nicknamePrefill.js.map +0 -1
  329. package/dist/shared/settingsAsks.js.map +0 -1
  330. package/dist/shared/settingsCarveOut.js.map +0 -1
  331. package/dist/shared/settingsClasses.js.map +0 -1
  332. package/dist/shared/settingsConsent.js.map +0 -1
  333. package/dist/shared/settingsSurface.js.map +0 -1
  334. package/dist/shared/skillRanking.js.map +0 -1
  335. package/dist/shared/userMd/formAdapter.js.map +0 -1
  336. package/dist/shared/userMd/schema.js.map +0 -1
  337. package/dist/shared/userMd/utils.js.map +0 -1
  338. package/dist/ui/assets/index-Cxgy63kz.js.map +0 -1
  339. package/src/scripts/_lib/adr_frontmatter.test.ts +0 -365
  340. package/src/scripts/_lib/adversarial_council_gate.test.ts +0 -112
  341. package/src/scripts/_lib/adversarial_reconcile.test.ts +0 -197
  342. package/src/scripts/_lib/auto_dispatch.corpus.test.ts +0 -150
  343. package/src/scripts/_lib/secret_detector.test.ts +0 -108
  344. package/src/scripts/_lib/secret_detector_adversarial.test.ts +0 -116
  345. package/src/scripts/_lib/ui_authority.test.ts +0 -251
  346. package/src/scripts/_lib/untrusted_content.test.ts +0 -175
  347. package/src/scripts/check_secret_leak.test.ts +0 -90
  348. package/src/scripts/design_slop_rules.test.ts +0 -246
  349. package/src/scripts/self_review_gate.test.ts +0 -296
  350. package/src/shared/capabilities.test.ts +0 -43
@@ -15505,6 +15505,11 @@ var settingsSchema = external_exports.object({
15505
15505
  enabled: external_exports.boolean().default(false).describe(
15506
15506
  "PreToolUse code-graph nudge (ADR-124 Phase 4). Default off. When on AND a native code-graph cache or a consumer-shipped graph.json/SCIP index is present, warns once per session (never blocks) as the agent is about to Grep/Glob or Read a source file \u2014 query the graph first for who-calls/where-used/impact questions (or rebuild if stale, build if absent). Source G\u2019s strict block-first-read mode is deliberately un-ported."
15507
15507
  )
15508
+ }).default({}),
15509
+ suggestion_capture: external_exports.object({
15510
+ enabled: external_exports.boolean().default(false).describe(
15511
+ 'Suggestion-block capture (road-to-suggestion-block-capture Phase 2). Default off. Two slots: `stop` reads `last_assistant_message` \u2014 a payload field, so no transcript file is read \u2014 and latches that the assistant turn carried a numbered-options block; `user_prompt_submit` CONSUMES that latch and classifies the answering turn as option_n / as_is / other / stale_block. Consume-once is the correctness guard: the latch is deleted on read, so a bare "1" three turns later meets no latch and classifies `other`, and a latch past its TTL or unparseable is `stale_block` rather than a guess. Writes COUNTS ONLY to agents/runtime/state/audit/suggestion-capture.jsonl \u2014 the record type has no field able to hold a prompt, an option label or a command name, and a test asserts the written key set against src/config/suggestion-capture.json. Off by default because this is an INSTRUMENT rather than a feature: it exists so a capture rate can be measured on a maintainer workspace over a fixed soak window, and there is nothing in it for a consumer to gain.'
15512
+ )
15508
15513
  }).default({})
15509
15514
  // `turn_end_gate` is deliberately ABSENT. The stop-slot turn-end gate is
15510
15515
  // always armed (2026-08-12) and has no settings surface: whether it
@@ -3,13 +3,13 @@
3
3
  "artefact_count": 623,
4
4
  "scanner_version": "de0a22b4ac4c"
5
5
  },
6
- "generated_at": "2026-08-24",
6
+ "generated_at": "2026-08-25",
7
7
  "package": {
8
8
  "description": "Governed skills, rules and commands for AI coding tools (Claude Code, Cursor, Windsurf, Copilot) \u2014 every claim machine-checked, including \"zero runtime daemon\".",
9
9
  "homepage": "https://event4u-app.github.io/agent-config",
10
10
  "name": "@event4u/agent-config",
11
11
  "repository": "https://github.com/event4u-app/agent-config",
12
- "version": "14.11.0"
12
+ "version": "14.12.0"
13
13
  },
14
14
  "registries": [
15
15
  {
@@ -9,12 +9,12 @@
9
9
  "transport": {
10
10
  "type": "stdio"
11
11
  },
12
- "version": "14.11.0"
12
+ "version": "14.12.0"
13
13
  }
14
14
  ],
15
15
  "repository": {
16
16
  "source": "github",
17
17
  "url": "https://github.com/event4u-app/agent-config"
18
18
  },
19
- "version": "14.11.0"
19
+ "version": "14.12.0"
20
20
  }
@@ -275,6 +275,9 @@ export const settingsSchema = z.object({
275
275
  code_graph: z.object({
276
276
  enabled: z.boolean().default(false).describe('PreToolUse code-graph nudge (ADR-124 Phase 4). Default off. When on AND a native code-graph cache or a consumer-shipped graph.json/SCIP index is present, warns once per session (never blocks) as the agent is about to Grep/Glob or Read a source file — query the graph first for who-calls/where-used/impact questions (or rebuild if stale, build if absent). Source G’s strict block-first-read mode is deliberately un-ported.'),
277
277
  }).default({}),
278
+ suggestion_capture: z.object({
279
+ enabled: z.boolean().default(false).describe('Suggestion-block capture (road-to-suggestion-block-capture Phase 2). Default off. Two slots: `stop` reads `last_assistant_message` — a payload field, so no transcript file is read — and latches that the assistant turn carried a numbered-options block; `user_prompt_submit` CONSUMES that latch and classifies the answering turn as option_n / as_is / other / stale_block. Consume-once is the correctness guard: the latch is deleted on read, so a bare "1" three turns later meets no latch and classifies `other`, and a latch past its TTL or unparseable is `stale_block` rather than a guess. Writes COUNTS ONLY to agents/runtime/state/audit/suggestion-capture.jsonl — the record type has no field able to hold a prompt, an option label or a command name, and a test asserts the written key set against src/config/suggestion-capture.json. Off by default because this is an INSTRUMENT rather than a feature: it exists so a capture rate can be measured on a maintainer workspace over a fixed soak window, and there is nothing in it for a consumer to gain.'),
280
+ }).default({}),
278
281
  // `turn_end_gate` is deliberately ABSENT. The stop-slot turn-end gate is
279
282
  // always armed (2026-08-12) and has no settings surface: whether it
280
283
  // fires is decided by each detector's own trigger conditions, not by a
@@ -242,8 +242,8 @@ dispatch runs, not WHETHER the layer exists, so they keep their own C rows.
242
242
  |---|---|
243
243
  | A — preference | 26 |
244
244
  | B — consent | 3 |
245
- | C — guarded | 108 |
246
- | **Total** | **137** |
245
+ | C — guarded | 109 |
246
+ | **Total** | **138** |
247
247
 
248
248
  The total was 140 until 2026-08-12, when five of the six keys no code path read were
249
249
  deleted, minus the one held open (§ The six unread keys, below): one A
@@ -257,6 +257,25 @@ It rose to 136 on 2026-08-20 when `road-to-gate-autonomy`'s
257
257
  first keys added to this contract since the deletions above, and both are C on
258
258
  test 1 (money).
259
259
 
260
+ It rose to 138 on 2026-08-24 when `road-to-suggestion-block-capture` Phase 2
261
+ added `hooks.suggestion_capture.enabled`. C on test 1 — it configures code that
262
+ runs at every turn end and every prompt — and the third `hooks.*` key here.
263
+
264
+ Its disposition is **`consent`**, and the first draft of this row said
265
+ `derivable`, which was wrong in the way the disposition axis exists to catch. The
266
+ `derivable` argument was that the sink's own line count answers whether the soak
267
+ window is running — true, and it answers the wrong question. What the key
268
+ authorises is *the package observing this operator's turns and writing a record
269
+ of them*, and no predicate computes whether someone consents to that. The
270
+ `derivable-surface` ratchet caught it immediately: it is shrink-only, so a new
271
+ `derivable` key reds by construction, and being unable to add one is the
272
+ mechanism working rather than an obstacle.
273
+
274
+ The distinction against its `design_pass` neighbour still holds and is the reason
275
+ this is not `policy` either: that concern can **block**, so arming it is a risk
276
+ preference. This one only observes and exits 0 on every path — the question is
277
+ not risk, it is permission.
278
+
260
279
  It rose to 137 on 2026-08-23 when `road-to-frontend-power` E1.1–E1.3 added
261
280
  `hooks.design_pass.enabled`. C on test 1 (it configures code that runs on every
262
281
  tool call and at every turn end), and the only hook key in this contract whose
@@ -314,9 +333,9 @@ the template, which is the drift this contract exists to prevent.
314
333
  |---|---|
315
334
  | derivable | 83 |
316
335
  | un-inferrable | 9 |
317
- | consent | 39 |
336
+ | consent | 40 |
318
337
  | policy | 6 |
319
- | **Total** | **137** |
338
+ | **Total** | **138** |
320
339
 
321
340
  First measured 2026-08-12 at 140 leaves (derivable 88 · consent 38 ·
322
341
  un-inferrable 9 · policy 5), from the table below rather than predicted — the
@@ -534,6 +553,7 @@ Rows follow template order, so a diff against the template reads straight down.
534
553
  | `hooks.ui_route_nudge.enabled` | C | `false` | configures code that runs on every tool call | derivable — the UI-surface predicate plus the hook's own two-nudges-per-session cap |
535
554
  | `hooks.design_pass.enabled` | C | `false` | C-test 1 — it configures code that runs on every tool call and at every turn end, and unlike its two `hooks.*` neighbours its stop pass can BLOCK rather than warn | policy — whether an operator accepts a gate that can refuse a turn is a risk preference, not a fact the tree can compute. The two neighbours are `derivable` because they only ever warn; the block is the discriminator. `road-to-frontend-power` transfers the default flip to the owner for the same reason |
536
555
  | `hooks.code_graph.enabled` | C | `false` | configures code that runs on every tool call | derivable — the index-detection probe the nudge already runs; no index means silence |
556
+ | `hooks.suggestion_capture.enabled` | C | `false` | configures code that runs at every turn end and every prompt | consent |
537
557
  | `decision_engine.surface_traces` | C | `false` | the decision engine’s own black box; the agent must not be able to close it | derivable — the engine's own active-gate state; there is nothing to surface when no gate fired |
538
558
  | `decision_engine.min_confidence` | C | `"off"` | the confidence gate | derivable — the confidence band the scoring engine already computes at the plan phase |
539
559
  | `decision_engine.block_on_risk` | C | `"off"` | the risk-class gate | derivable — the risk class the engine already computes at the implement phase; the Hard Floor covers the irreversible end unconditionally |
@@ -0,0 +1,91 @@
1
+ # Downstream-Changes Mechanics — closed-set evolution
2
+
3
+ > The procedure behind [`downstream-changes`](../../../src/rules/downstream-changes.md)
4
+ > for one change class its table does not reach: a **closed set** whose member
5
+ > list changed. Cited by `skill:code-review` (the propagation dimension) and
6
+ > `skill:code-refactoring` (the reference sweep).
7
+ >
8
+ > It lives here rather than in the rule for a measured reason. Project-scope
9
+ > rules are a gated bucket of the per-spawn standing payload, and that payload
10
+ > currently measures **at** its grace ceiling
11
+ > (`src/config/preamble-payload-budget.json`), so the rule cannot grow by a
12
+ > single line without reddening `check_preamble_payload_budget`. Guidelines are
13
+ > an excluded bucket — read on demand, not re-sent per spawn. The obligation is
14
+ > therefore carried by the two skills that fire at the moment it matters, and
15
+ > the rule keeps its current size until a reduction lands.
16
+
17
+ ## The Iron Law
18
+
19
+ ```
20
+ CHANGING A MEMBER OF A CLOSED SET IS NEVER DONE WHEN THE TYPE COMPILES.
21
+ EVERY CONSUMER IS CLASSIFIED: EXHAUSTIVE, DELIBERATE FALLBACK, OR MISSING CASE.
22
+ A `default` THAT SWALLOWS THE NEW MEMBER IS A MISSING CASE WEARING A BRANCH.
23
+ ```
24
+
25
+ ## Why the ordinary sweep misses it
26
+
27
+ `downstream-changes` enumerates callers, tests, imports, type definitions,
28
+ config bindings, routes and docs — all of which are found by searching for the
29
+ **identifier**. A closed set breaks that assumption: the member list changes,
30
+ the type still compiles, and a serializer, a badge variant, an OpenAPI schema or
31
+ a transition table silently keeps the old set. None of them names the type, so
32
+ no identifier search reaches them. This is the shotgun-surgery shape — one
33
+ conceptual change scattered across many small sites, where forgetting one is the
34
+ default outcome rather than the unlucky one.
35
+
36
+ ## What counts as a closed set
37
+
38
+ PHP enums · TypeScript enums · discriminated unions · literal-union state types ·
39
+ Rust enums · sealed types · Python `enum` classes · DB enum and check
40
+ constraints · OpenAPI / JSON-Schema `enum` · state machines · role and permission
41
+ sets · finite component variants.
42
+
43
+ ## Discover by shape, not by identifier
44
+
45
+ - the member name and its **backing value** (the wire value often differs);
46
+ - `match` / `switch` / if-chains over the type;
47
+ - `Record<Member, …>`, lookup tables and maps keyed by it;
48
+ - `cases()` / `values()` iteration;
49
+ - validators and serializers;
50
+ - DB constraints and migrations;
51
+ - API schemas;
52
+ - UI option sources and variant maps;
53
+ - translation keys;
54
+ - tests, factories and fixtures.
55
+
56
+ ## Classify every hit — three outcomes, one defect
57
+
58
+ | Class | What it means | Action |
59
+ |---|---|---|
60
+ | Exhaustive | The compiler or the data structure forces completeness (a fully-typed `Record<Member, …>`, a `match` with no default) | nothing — this is the outcome to prefer |
61
+ | Deliberate fallback | The fallback is part of the contract: a forward-compatible external value, a protocol unknown, a defensive boundary parse | record why, leave it |
62
+ | Missing case | The new member reaches code written for the old set | fix it |
63
+
64
+ **There is deliberately no blanket rule that a `default` branch is wrong.** Such
65
+ a rule would be refuted by every protocol parser and boundary parse in the tree.
66
+ What is true is sharper and easier to miss: where an exhaustiveness check exists,
67
+ **a `default` clause suppresses its report entirely**, so adding one to quiet the
68
+ check removes exactly the signal it existed to give.
69
+ <!-- harvest:exhaustiveness-default-clause-masks-the-check -->
70
+
71
+ Prefer the language-native guarantee over a comment. In TypeScript a
72
+ `Record<Member, T>` where every member needs a value fails to compile on a new
73
+ member, while a partially-typed string-keyed map does not. In PHP an exhaustive
74
+ `match` without a masking `default` throws on an unhandled case.
75
+
76
+ ## Prove the sweep, do not assert it
77
+
78
+ Add a **synthetic member** to the set, confirm the checks you are relying on go
79
+ red, then update the consumers and confirm they go green. A sweep never seen red
80
+ has unknown coverage — the same sensitivity argument
81
+ [`downstream-changes`](../../../src/rules/downstream-changes.md) § Verification
82
+ makes for tests, applied to the discovery step.
83
+
84
+ ## See also
85
+
86
+ - [`downstream-changes`](../../../src/rules/downstream-changes.md) — the rule this
87
+ extends; its § Defect-pattern search is the sibling-occurrence half.
88
+ - [`redundancy-taxonomy`](../redundancy-taxonomy.md) — the naming half: one
89
+ concept, several terms.
90
+ - [`prefer-enums-over-literals`](../../../src/rules/prefer-enums-over-literals.md)
91
+ — how a closed set comes to exist in the first place.
@@ -246,6 +246,24 @@ Before emitting a comment or docblock, all three must be true:
246
246
 
247
247
  One "no" → drop it. When in doubt: no comment.
248
248
 
249
+ Those three conditions are the code-comment instance of a wider test. The
250
+ generalised form — five questions covering comments, docblocks, labels, hints,
251
+ tooltips, placeholders, badges and empty states alike — is the Information Delta
252
+ Test in [`redundancy-taxonomy`](redundancy-taxonomy.md), together with the
253
+ representation classes that name what a redundant surface *is*. Reach for it
254
+ whenever the surface is not a code comment, and whenever a reduction would touch
255
+ the semantic channel: an accessibility name is required information, so it is a
256
+ hard guard and never a deletion candidate. The rule is not "less text" — it is
257
+ that if removing the text loses no information in any required channel, remove
258
+ it, and if the information is required, express it once, in the strongest native
259
+ form available.
260
+
261
+ The same document carries the **naming** half, which fires earlier than any of
262
+ this: before introducing a term for a concept, search for the term the tree
263
+ already uses. A second word for an existing concept costs a reader more than a
264
+ redundant sentence does — a redundant sentence is skipped, a second name makes
265
+ them check whether they are looking at one thing or two.
266
+
249
267
  ### Additional worked examples
250
268
 
251
269
  (The TypeScript `formatPrice` pair above is the canonical TS example; these
@@ -309,3 +327,6 @@ criteria are proven by `tests/scripts/code_comment_fixtures.test.ts`.
309
327
  removals on untouched code".
310
328
  - `direct-answers` rule — same spirit at the prose level: shortest
311
329
  version that fully answers the question.
330
+ - [`redundancy-taxonomy`](redundancy-taxonomy.md) — the shared classes,
331
+ verdicts and Information Delta Test this section instantiates for code
332
+ comments; also cited by the review and refactoring skills.
@@ -0,0 +1,180 @@
1
+ # Redundancy Taxonomy
2
+
3
+ > The one place this package names what duplication *is*, what may be decided
4
+ > about it, and how to tell a second explanation that adds information from one
5
+ > that only adds length. Cited by [`code-clarity`](code-clarity.md) at the
6
+ > authoring moment, by `skill:code-review` at the review moment, and by
7
+ > `skill:code-refactoring` at the refactoring moment. Those three cite it —
8
+ > they do not restate it, because three copies of a redundancy taxonomy would
9
+ > be the defect it describes.
10
+
11
+ Finding duplication is not a decision. Every finding reaches a **named verdict**
12
+ with a reason, and several of the verdicts keep the duplication. The goal is not
13
+ the lowest clone percentage — it is **one honest authority per shared fact**,
14
+ without marrying independent concepts through a wrong abstraction.
15
+
16
+ ## The classes
17
+
18
+ **Implementation** — the same code exists twice.
19
+
20
+ | Class | What it is |
21
+ |---|---|
22
+ | Exact clone | Same tokens. |
23
+ | Renamed clone | Same structure; identifiers or literals differ. |
24
+ | Near clone | Shared core with local additions or deletions. |
25
+ | Structural pattern | Same shape, no copy/paste lineage. |
26
+ | Boilerplate | Framework, protocol, or generated ceremony. |
27
+ | Test repetition | Repeated setup or assertion structure. |
28
+ | Intentional independence | Similar today, meant to diverge. |
29
+ | Wrong abstraction | Already shared, now growing caller flags and modes. |
30
+
31
+ **Knowledge** — the same *fact* is encoded twice. Usually more actionable than
32
+ raw clone percentage, because a clone can be harmless and a divided fact rarely is.
33
+
34
+ | Class | What it is |
35
+ |---|---|
36
+ | Knowledge duplication | One business rule, constant, or algorithm encoded more than once. |
37
+ | Policy duplication | One governance decision represented across independent surfaces. |
38
+ | Contract duplication | One external protocol or CLI contract reimplemented instead of consumed. |
39
+ | Delivery-authority duplication | Two authored sources can produce the same shipped artifact. |
40
+
41
+ **Representation** — the same *meaning* is presented twice to a reader: a
42
+ comment, label, hint, tooltip, placeholder, badge, heading, caption, or toast.
43
+
44
+ | Class | What it is |
45
+ |---|---|
46
+ | Exact text echo | The same text repeated in the same context. |
47
+ | Paraphrase echo | A second surface restating the first in other words. |
48
+ | Structural narration | Prose naming what the code or UI already shows. |
49
+ | Decorative metadata | An eyebrow, badge, or heading with no scanning or semantic value. |
50
+ | Feedback echo | Status text duplicating already-obvious state. |
51
+ | Accessibility conflict | Removing it would delete required semantic information. |
52
+
53
+ An accessibility conflict is a **hard guard, never a deletion candidate**. A
54
+ reduction that improves the visual channel by breaking the semantic one is not a
55
+ reduction; it is a defect.
56
+
57
+ **Naming** — the *dual* of a representation echo. An echo says one meaning twice;
58
+ divergent naming says one meaning with two words, so the reader cannot tell
59
+ whether they are looking at one concept or two. It is a modelling defect rather
60
+ than a style preference: a concept carries one term across the whole model, and
61
+ several terms for one concept is the model telling you it has not decided.
62
+ <!-- harvest:one-language-per-concept-inconsistency-is-a-model-defect -->
63
+
64
+ | Class | What it is |
65
+ |---|---|
66
+ | Spelling variant | One word, two spellings (`artifact` / `artefact`). No semantic difference; decidable without judgement. |
67
+ | Synonym drift | One concept, several terms. Needs a term map, because the terms may denote different things. |
68
+ | Homonym collision | One term, several meanings. The opposite failure, and usually `keep-duplicated` when the meanings are module-local. |
69
+
70
+ Naming verdicts: `canonicalize-term` · `keep-distinct` (with the recorded reason
71
+ — an external compatibility value, a quoted name, a genuinely different concept)
72
+ · `defer-for-context`.
73
+
74
+ **Only a spelling variant is mechanically decidable, and the split between the
75
+ prose layer and the identifier layer is decisive.** Prose is a substitution;
76
+ filenames, symbols and their test and task references are a rename refactor with
77
+ its own blast radius, and the same cluster can be committed to different sides on
78
+ each layer. Measure both before proposing either — the measured example is in
79
+ `agents/evidence/analysis/wording-baseline-2026-08-25.md`, where nothing imports
80
+ across the split and the identifier layer is therefore `keep-duplicated` while
81
+ the prose layer is `canonicalize-term`.
82
+
83
+ Synonym drift is the class to be slowest about. Words that read as synonyms in
84
+ translation frequently denote different mechanisms — here `route`, `dispatch`,
85
+ `delegate`, `spawn` and `forward` are five mechanisms, not one concept spelled
86
+ five ways — so a sweep over them destroys information the echo classes exist to
87
+ protect.
88
+
89
+ ## Why any of this is worth a gate at all
90
+
91
+ Generated code trends toward duplication rather than reuse: measured
92
+ longitudinally over roughly 211 million changed lines, copy/pasted code rose from
93
+ 8.3 % to 12.3 % of changes over the period assistance became common.
94
+ <!-- harvest:ai-agents-raise-copy-paste-share --> The pressure this document
95
+ resists is therefore not a hypothetical — it is the default direction of the tool
96
+ writing the code, which is why `keep-duplicated` needs to be a recorded verdict
97
+ rather than an unstated outcome.
98
+
99
+ Where enforcement follows, the shape is already known: separate the term list
100
+ from the rules, and control false positives by **syntax awareness** — skip
101
+ frontmatter, fenced code and inline code rather than matching inside them.
102
+ <!-- harvest:prose-linter-vocabulary-accept-reject --> `check_md_language.ts`
103
+ already carries exactly that skip machinery.
104
+
105
+ ## The verdicts
106
+
107
+ For implementation and knowledge findings: `extract-local` · `extract-module` ·
108
+ `canonicalize-knowledge` · `canonicalize-contract` · `single-copy-delivery` ·
109
+ `data-drive` · `compose-strategy` · `generate` · **`keep-duplicated`** ·
110
+ `defer-for-evidence` · **`de-abstract`**.
111
+
112
+ For representation findings: `keep` · `drop` · `consolidate` ·
113
+ `rewrite-for-signal` · `accessibility-block` · `defer-for-context`.
114
+
115
+ `keep-duplicated` and `de-abstract` are **successful outcomes**, not failures to
116
+ act. A wrong abstraction costs more than the duplication it replaced, so a
117
+ recorded decision to leave two copies alone — or to split one shared unit back
118
+ apart — closes a finding as legitimately as an extraction does. What is not
119
+ allowed is silence: a finding with no recorded verdict stays open.
120
+
121
+ ## Before sharing an implementation
122
+
123
+ 1. Is it the same knowledge, or two facts that currently look alike?
124
+ 2. Would both copies change for the same reason?
125
+ 3. Is there one honest domain name that fits every call site?
126
+ 4. Can the common core stay free of caller-specific flags and modes?
127
+ 5. Is the dependency direction healthy?
128
+ 6. Does this reduce maintenance risk, or only line count?
129
+ 7. Are public contracts preserved, and do tests prove behavioural equivalence?
130
+ 8. Is this generated or protocol ceremony that should stay explicit?
131
+ 9. **If the two copies diverged tomorrow, would that be a defect or legitimate
132
+ evolution?**
133
+
134
+ A "legitimate evolution" answer to the last question is decisive: prefer
135
+ independence, verdict `keep-duplicated`.
136
+
137
+ ## The Information Delta Test
138
+
139
+ Before adding any comment, docblock, label, hint, tooltip, placeholder, badge,
140
+ caption, empty-state line, or explanatory sentence, in code or in a user
141
+ interface:
142
+
143
+ - **A — Information delta.** What fact becomes unavailable if this text is
144
+ deleted? A non-obvious reason, an invariant, a required format, a unit, a
145
+ consequence, a safety warning, a recovery action, a privacy implication, an
146
+ unfamiliar concept, an accessibility name, or necessary grouping all count. If
147
+ the answer is "nothing", delete it.
148
+ - **B — Representation delta.** Is that fact already carried adequately by a
149
+ nearby representation — the name, the type, the component structure, the
150
+ semantic element, the visible control text, an icon, a test? If so,
151
+ consolidate; do not repeat.
152
+ - **C — Channel preservation.** Would deleting it weaken visual comprehension,
153
+ semantic accessibility, or both? Never optimise one channel by breaking the
154
+ other.
155
+ - **D — Persistence.** Will it still be true after the next ordinary refactor?
156
+ Text describing the current implementation rather than the durable constraint
157
+ is noise with a delay fuse.
158
+ - **E — Actionability.** For user-facing copy: does it change what the reader
159
+ understands, chooses, enters, expects, or does next? If not, it is a strong
160
+ deletion candidate.
161
+
162
+ The rule is **not** "less text". It is: if removing the text loses no
163
+ information in any required channel, remove it — and if the information is
164
+ required, express it once, in the strongest native form available. A visible
165
+ form label is required information, so it stays; a placeholder repeating that
166
+ label is an exact text echo, so it goes.
167
+
168
+ ## Legacy is baseline, new duplication is the finding
169
+
170
+ Existing duplication does not fail an unrelated change. A review or refactor
171
+ raises a finding when a change **introduces** high-confidence knowledge, policy,
172
+ contract, or delivery-authority duplication — or when it touches a surface that
173
+ already carries some. Anything else is debt with a measurement, not a blocker.
174
+
175
+ ## See also
176
+
177
+ - [`code-clarity`](code-clarity.md) — the authoring moment; comment discipline
178
+ and the banned classes this test generalises.
179
+ - [`abstraction-thresholds`](abstraction-thresholds.md) — how much repetition
180
+ earns an abstraction, per artifact class.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@event4u/agent-config",
3
3
  "mcpName": "io.github.event4u-app/agent-config",
4
- "version": "14.11.0",
4
+ "version": "14.12.0",
5
5
  "description": "Governed skills, rules and commands for AI coding tools (Claude Code, Cursor, Windsurf, Copilot) — every claim machine-checked, including \"zero runtime daemon\".",
6
6
  "license": "MIT",
7
7
  "private": false,
@@ -59,7 +59,11 @@
59
59
  "!dist/**/*.test.js",
60
60
  "!dist/**/*.test.js.map",
61
61
  "!dist/**/*.spec.js",
62
- "!dist/**/*.spec.js.map"
62
+ "!dist/**/*.spec.js.map",
63
+ "!src/**/*.test.ts",
64
+ "!src/**/*.spec.ts",
65
+ "!dist/agent-src/skills/**/evals/**",
66
+ "!dist/**/*.map"
63
67
  ],
64
68
  "bin": {
65
69
  "agent-config": "dist/cli/agent-config.js"
@@ -1344,6 +1344,22 @@ hooks:
1344
1344
  code_graph:
1345
1345
  enabled: false
1346
1346
 
1347
+ # Suggestion-block capture (road-to-suggestion-block-capture). Two slots:
1348
+ # `stop` latches that the assistant turn carried a numbered-options block,
1349
+ # `user_prompt_submit` consumes the latch and classifies the answering turn.
1350
+ # Writes COUNTS ONLY to agents/runtime/state/audit/suggestion-capture.jsonl —
1351
+ # the record type has no field able to hold a prompt, an option label or a
1352
+ # command name, and a test asserts the written key set against
1353
+ # src/config/suggestion-capture.json.
1354
+ #
1355
+ # `enabled: false` is the shipped default because this is an INSTRUMENT, not a
1356
+ # feature: it exists so a capture rate can be measured on a maintainer
1357
+ # workspace during a fixed soak window, and there is nothing in it for a
1358
+ # consumer to gain. Turning it on costs one string match per turn and one
1359
+ # small file write per answered block.
1360
+ suggestion_capture:
1361
+ enabled: false
1362
+
1347
1363
  # --- Decision engine ---
1348
1364
  #
1349
1365
  # Controllable gates layered over the observability surface. Absent
@@ -4,6 +4,25 @@
4
4
  # instead of hard-coding them (measure_augment_budget, and any future
5
5
  # per-tool budget meter).
6
6
 
7
+ # ── Ownership ─────────────────────────────────────────────────────────────────
8
+ # Added 2026-08-24, road-to-standing-payload-truth `b-budgets-yml-outside-ownership`.
9
+ # This file was outside `lint_budget_ownership`'s corpus for its whole life,
10
+ # because that gate filtered on `.json`. A budget without an owner is a budget
11
+ # nobody has to defend, and this is the one that gates `standing_rule_delivery` —
12
+ # the larger of the two red payload numbers. It is now governed by an explicit
13
+ # single-file row in that gate's `GOVERNED_NON_JSON`, not by a widened glob.
14
+ #
15
+ # `review_by` IS DERIVED, AND NO CADENCE RULE IS DOCUMENTED — said plainly rather
16
+ # than presented as policy. `lint_budget_ownership` requires the field and defines
17
+ # no interval for it. Two conventions are observable in the sibling budgets:
18
+ # four files use 2026-11-10 (the preamble milestone) and seven use a ~1-year
19
+ # horizon, including this file's subject-nearest sibling
20
+ # `preamble-payload-budget.json`. Registered 2026-08-24 on that convention →
21
+ # 2027-08-24. If a cadence is ever written down and disagrees, this date is wrong
22
+ # and should move to the rule rather than the rule to the date.
23
+ owner: maintainer
24
+ review_by: '2027-08-24'
25
+
7
26
  augment_workspace_guidelines:
8
27
  # Verified platform maximum: 99,024 chars (re-measured 2026-07; the old
9
28
  # 49,512 ceiling from the 2026-05-08 baseline is obsolete). We deliberately
@@ -109,6 +109,21 @@ ci_only:
109
109
  # self-test is the half that IS worth running locally, and it is reachable —
110
110
  # `classify_change_risk --self-test` — but the workflow invokes it as a step of
111
111
  # its own rather than through the aggregate, which is what this checker sees.
112
+ # road-to-npm-payload-reduction Phase 3.1. `report_pack_delta` measures the
113
+ # BRANCH-vs-BASE packed payload, which has no meaning without a pull request:
114
+ # locally `--base origin/main --head HEAD` on main reads +0.0 KB every time, and
115
+ # the step's own contract is to write nothing when the delta is zero. It also
116
+ # checks out BOTH refs into throwaway worktrees and packs each (~1 minute), so
117
+ # putting it in `task ci` would add a minute to every local run for a number
118
+ # that is structurally absent locally. It is a REPORT and cannot red the build
119
+ # (`continue-on-error: true`, and the script exits 0 whatever the number), so
120
+ # there is no failure a contributor could discover only after pushing — which is
121
+ # the exact harm this checker exists to prevent.
122
+ #
123
+ # Reachable on demand: `task report-pack-delta -- --base <ref> --head <ref>`.
124
+ - id: report_pack_delta
125
+ class: artifact
126
+ reason: "a pull-request-only delta report with no local meaning (base==head reads +0.0 KB and the step writes nothing); it packs two refs in throwaway worktrees at ~1 min, cannot red the build, and is reachable on demand via `task report-pack-delta`"
112
127
  - id: classify_change_risk
113
128
  class: benchmark
114
129
  reason: "invoked as the nightly drift workflow's self-test step; the classifier itself gates nothing and its `--self-test` is runnable locally on demand (`./scripts-run src/scripts/classify_change_risk --self-test`)"
@@ -0,0 +1,56 @@
1
+ # Controlled prompt-pattern vocabulary for command `## Examples` Why lines.
2
+ #
3
+ # Read by `src/scripts/check_command_examples.ts` (sub-check c). A Why line on
4
+ # an example must cite exactly ONE id from `approved_patterns`.
5
+ #
6
+ # WHY A CONTROLLED VOCABULARY AND NOT FREE PROSE. A worked example teaches two
7
+ # things: what to type, and why that phrasing works. The second half is the part
8
+ # that transfers to a command the reader has not seen. Free prose lets every
9
+ # author invent their own account of it, and six accounts of the same pattern
10
+ # teach the pattern less well than one. The ids are deliberately few and
11
+ # deliberately about the SHAPE of the invocation, never about the command.
12
+ #
13
+ # FORWARD-ONLY, on the `command-verbs.yml` precedent (ADR-041): only commands
14
+ # added, or promoted into `visible` / `advanced`, since the frozen grandfather
15
+ # set in `check_command_examples.ts` are required to carry Why lines. The
16
+ # existing surface is grandfathered and melts down voluntarily.
17
+ #
18
+ # Adding an id here is a governance change: land it in its own PR with the
19
+ # reason the six below could not carry the case. Do NOT add an id to make one
20
+ # awkward example pass — rewrite the example to an existing pattern, or leave
21
+ # the Why line off and accept the gate's finding.
22
+
23
+ approved_patterns:
24
+ # Name the end state, not the sequence of steps to reach it. The agent picks
25
+ # the steps; a step list from the operator overconstrains it and goes stale.
26
+ - outcome-not-steps
27
+
28
+ # Build the verification into the ask, so the agent can tell green from done
29
+ # without a second turn.
30
+ - self-check-loop
31
+
32
+ # Point at a file, a ticket, a URL, a line range — a resolvable location
33
+ # beats a description of the thing.
34
+ - measurable-target
35
+
36
+ # Hand over the artifact itself rather than describing it: paste the log, the
37
+ # diff, the failing output.
38
+ - give-the-artifact
39
+
40
+ # Cite an existing convention, doc, or sibling implementation as the standard
41
+ # to match, instead of restating it inline.
42
+ - point-at-reference
43
+
44
+ # State the shape the answer must arrive in — a table, JSON, one sentence, a
45
+ # file path — when the shape is what makes it usable.
46
+ - say-the-format
47
+
48
+ # The two literals a Why line may use. Adopted verbatim from
49
+ # `lint_examples.ts` (`### Why it works` / `**Why it works:**`), the strings
50
+ # the demo linter already detects for the SAME purpose on a different
51
+ # population. Reusing the strings rather than the code keeps the two
52
+ # conventions textually aligned without coupling the gates — the demo linter's
53
+ # scope and observable behaviour are compatibility-pinned and stay untouched.
54
+ why_line_literals:
55
+ - '**Why it works:**'
56
+ - '### Why it works'
@@ -6,18 +6,23 @@
6
6
  "owner": "maintainer",
7
7
  "review_by": "2027-08-18",
8
8
  "metric": {
9
- "basis": "src/scripts/check_estate_count.ts. The live side uses collect() from update_roadmap_progress \u2014 the same parser the dashboard is generated from, imported rather than re-implemented. The floor side runs the SAME functions over a scratch copy of the base ref's agents/roadmaps/, materialised by _lib/base_tree.ts (git ls-tree + git cat-file --batch; `git archive` cannot be used here because .gitattributes carries `/agents export-ignore` and would yield an empty, silently-zero tree).",
9
+ "basis": "src/scripts/check_estate_count.ts. The live side uses collect() from update_roadmap_progress \u2014 the same parser the dashboard is generated from, imported rather than re-implemented. The floor side runs the SAME functions over a scratch copy of the base ref's agents/roadmaps/, materialised by _lib/base_tree.ts (git ls-tree + git cat-file --batch; `git archive` cannot be used here because .gitattributes carries `/agents export-ignore` and would yield an empty, silently-zero tree). SKILL METRICS (added 2026-08-24): _lib/skill_estate.ts walks src/skills/*/SKILL.md under the SAME root, so the floor side measures the base ref's own skill tree with the same function. That needs a SECOND materialised subtree \u2014 materialiseSubtree takes one prefix \u2014 and the two are independent on purpose: a base ref with no src/skills (an old tag, a shallow clone) drops the skill metrics and leaves the roadmap metrics ratcheting.",
10
10
  "active_roadmaps": "non-draft roadmap candidates at the top level of agents/roadmaps/, as collect() counts them. This is exactly the number the dashboard header prints as 'N open roadmaps'.",
11
11
  "later_roadmaps": "roadmap-shaped *.md files under agents/roadmaps/later/ \u2014 the same is_roadmap_candidate name filter the active side uses, so later/README.md is not counted. Counted from the filesystem because parked roadmaps sit outside collect()'s corpus by design; they are estate all the same, and a drawdown that moved everything into later/ and called the number down would be the burial T1's quality anchor exists to prevent.",
12
12
  "open_blockers": "blockers whose Status does not start with `resolved`, summed over the active and later corpora.",
13
- "floor": "the same three metrics measured at the base ref (origin/main, else the merge commit's first parent). No base ref resolves -> no floor -> the gate FAILS rather than skipping: a shrink-only gate with no floor passes every possible tree. `--base <ref>` is the explicit escape."
13
+ "floor": "the same three metrics measured at the base ref (origin/main, else the merge commit's first parent). No base ref resolves -> no floor -> the gate FAILS rather than skipping: a shrink-only gate with no floor passes every possible tree. `--base <ref>` is the explicit escape.",
14
+ "skill_count": "Maintained src/skills/*/SKILL.md files; `lifecycle: deprecated` EXCLUDED. The exclusion is load-bearing rather than tidy: with deprecated skills counted, deprecating one would create no headroom and the retirement mechanism would be unusable against its own gate. 0 skills carry it today, so the exclusion is a no-op now and a correctness property once a tranche lands. Measured 2026-08-24: 299. Reproduce with `find src/skills -name SKILL.md | wc -l` (299 including any deprecated) or `npx tsx -e \"import {measureSkillEstate} from './src/scripts/_lib/skill_estate.ts'; console.log(measureSkillEstate(process.cwd()))\"` for the split.",
15
+ "skill_description_tokens": "Exact-BPE tokens (js-tiktoken, cl100k_base, via _lib/token_count.ts gpt_tokens) across those skills' `description:` frontmatter fields ONLY \u2014 not bodies. Measured 2026-08-24: 11,461 over 299 skills (52,983 chars). A SECOND DIMENSION, not a companion figure: a count ratchet alone is gameable by merging four large skills into one file, which lowers the count while the description payload a host must carry stays put. AI council 2/2 (2026-08-24) asked for both in one gate over the roadmap's own recommendation of count-plus-informational-figure. UNRESOLVED rather than approximated: when the tokeniser does not resolve on either side the metric is dropped from the compare with a printed reason, because an exact reading against a proxy one differs by more than the growth this gate is trying to catch.",
16
+ "skill_metric_rejected_candidates": "Measured before choosing, not argued. (b) catalogue bytes via _lib/skill_catalogue.ts read 0 on a real checkout: readProjectedCatalogue walks .claude/skills, empty in any tree where `task generate-tools` cannot complete (it fails under projection.mode=scoped without the config package) \u2014 a ratchet whose reading depends on whether a generator ran reds for the environment. (d) host-listing slots are the host's decision, not the repository's: a measured install published its own budget event stating it had stripped every description and dropped 402 entries. Neither is reproducible from the repo, so neither can carry a floor."
14
17
  },
15
18
  "growth_allowances": {
16
19
  "_comment": "An exact floor leaves no incidental headroom, so every legitimate increase needs a named path. Two are automatic because existing policy already sanctions the act; the third is the general authorisation.",
17
20
  "active_roadmaps": "+1 per addition carrying `estate_offset_exempt: <reason>` in its own frontmatter (unchanged T3 key). Without this the sanctioned un-offsettable addition would fail the count half with no green path.",
18
21
  "later_roadmaps": "+1 per roadmap moved from the active top level into later/ in the same change. Parking relocates estate rather than creating it. It does NOT cover a later/ file that appears from nowhere, and it is keyed on parking rather than on any offset so that an archive move cannot buy a new later/ file.",
19
22
  "open_blockers": "none. Nothing in the policy sanctions a new blocker, so it takes the claim path or nothing.",
20
- "claim": "`estate_growth_exempt: <reason>` added, in this change, to the frontmatter of any roadmap under agents/roadmaps/. Authorises growth in any metric, with the reason printed. Diff-scoped, so a claim left in a file authorises nothing later \u2014 the banking failure a stored baseline had. Deliberately unbounded, which a stored baseline could not afford: there the surplus of an over-raise was inherited by the next change, where nobody could act on it; here the next change's floor IS this change's measurement, so there is no surplus to inherit."
23
+ "claim": "`estate_growth_exempt: <reason>` added, in this change, to the frontmatter of any roadmap under agents/roadmaps/. Authorises growth in any metric, with the reason printed. Diff-scoped, so a claim left in a file authorises nothing later \u2014 the banking failure a stored baseline had. Deliberately unbounded, which a stored baseline could not afford: there the surplus of an over-raise was inherited by the next change, where nobody could act on it; here the next change's floor IS this change's measurement, so there is no surplus to inherit.",
24
+ "skill_count": "0 \u2014 no allowance, deliberately. The defect this metric addresses is a corpus that grew +8 in one release (290 at 14.0.0, 291 at 14.9.0 and 14.10.0, 299 at 14.11.0) with nothing objecting. An addition takes the estate_growth_exempt claim path \u2014 a recorded reason read from the diff \u2014 or it fails.",
25
+ "skill_description_tokens": "0 \u2014 same reasoning. An addition that grows the description payload without adding a file is the gaming path this dimension exists to close, and an allowance would reopen it."
21
26
  },
22
27
  "target": {
23
28
  "_comment": "T1's proposed ceilings, kept as the destination. PROPOSALS, NOT REGISTERED: the roadmap says in as many words that both numbers and the window belong to the maintainer, and no date is pinned in this file. Nothing reads these values \u2014 `one_in_one_out.applies_above_active` is the only threshold the gate evaluates.",