@event4u/agent-config 8.13.0 → 9.1.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 (316) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +183 -0
  3. package/MIGRATION.md +14 -0
  4. package/README.md +2 -2
  5. package/dist/agent-src/commands/agent-handoff.md +35 -0
  6. package/dist/agent-src/commands/agents/init.md +1 -0
  7. package/dist/agent-src/commands/agents/optimize.md +1 -0
  8. package/dist/agent-src/commands/agents/user/accept.md +3 -2
  9. package/dist/agent-src/commands/agents/user/init.md +5 -4
  10. package/dist/agent-src/commands/agents/user/update.md +3 -2
  11. package/dist/agent-src/commands/agents/user.md +1 -0
  12. package/dist/agent-src/commands/agents.md +1 -0
  13. package/dist/agent-src/commands/analytics/show.md +1 -0
  14. package/dist/agent-src/commands/analytics.md +1 -0
  15. package/dist/agent-src/commands/analyze/decision.md +1 -0
  16. package/dist/agent-src/commands/analyze/incident.md +1 -0
  17. package/dist/agent-src/commands/analyze/near-miss.md +1 -0
  18. package/dist/agent-src/commands/analyze/postmortem.md +1 -0
  19. package/dist/agent-src/commands/analyze/premortem.md +1 -0
  20. package/dist/agent-src/commands/analyze/reference-repo.md +1 -0
  21. package/dist/agent-src/commands/analyze.md +3 -2
  22. package/dist/agent-src/commands/brand/identity.md +6 -5
  23. package/dist/agent-src/commands/brand/review.md +6 -5
  24. package/dist/agent-src/commands/brand/strategy.md +6 -4
  25. package/dist/agent-src/commands/brand/tokens.md +7 -6
  26. package/dist/agent-src/commands/brand/voice.md +5 -4
  27. package/dist/agent-src/commands/brand.md +9 -7
  28. package/dist/agent-src/commands/bug/fix.md +1 -0
  29. package/dist/agent-src/commands/bug/investigate.md +1 -0
  30. package/dist/agent-src/commands/bug.md +2 -1
  31. package/dist/agent-src/commands/challenge-me/vision.md +1 -0
  32. package/dist/agent-src/commands/challenge-me/with-docs.md +1 -0
  33. package/dist/agent-src/commands/challenge-me.md +28 -6
  34. package/dist/agent-src/commands/chat-history.md +1 -0
  35. package/dist/agent-src/commands/check-current-md.md +1 -0
  36. package/dist/agent-src/commands/commit.md +1 -0
  37. package/dist/agent-src/commands/context/create.md +3 -2
  38. package/dist/agent-src/commands/context.md +1 -0
  39. package/dist/agent-src/commands/cost/profile.md +1 -0
  40. package/dist/agent-src/commands/cost.md +2 -1
  41. package/dist/agent-src/commands/council/analysis.md +1 -0
  42. package/dist/agent-src/commands/council/debate.md +1 -0
  43. package/dist/agent-src/commands/council/default.md +21 -20
  44. package/dist/agent-src/commands/council/design.md +1 -0
  45. package/dist/agent-src/commands/council/optimize.md +1 -0
  46. package/dist/agent-src/commands/council/pr.md +1 -0
  47. package/dist/agent-src/commands/council.md +1 -0
  48. package/dist/agent-src/commands/estimate-ticket.md +1 -0
  49. package/dist/agent-src/commands/explain-run.md +88 -0
  50. package/dist/agent-src/commands/feature/dev.md +1 -0
  51. package/dist/agent-src/commands/feature/explore.md +1 -0
  52. package/dist/agent-src/commands/feature/plan.md +1 -0
  53. package/dist/agent-src/commands/feature/refactor.md +1 -0
  54. package/dist/agent-src/commands/feature/roadmap.md +1 -0
  55. package/dist/agent-src/commands/feature.md +2 -1
  56. package/dist/agent-src/commands/fix/pr-comments.md +19 -0
  57. package/dist/agent-src/commands/fix.md +2 -1
  58. package/dist/agent-src/commands/ghostwriter/delete.md +1 -0
  59. package/dist/agent-src/commands/ghostwriter/fetch.md +1 -0
  60. package/dist/agent-src/commands/ghostwriter/show.md +1 -0
  61. package/dist/agent-src/commands/ghostwriter/write.md +1 -0
  62. package/dist/agent-src/commands/ghostwriter.md +1 -0
  63. package/dist/agent-src/commands/grill-me.md +17 -12
  64. package/dist/agent-src/commands/humanize.md +1 -0
  65. package/dist/agent-src/commands/image/analyse.md +2 -1
  66. package/dist/agent-src/commands/image/create.md +1 -0
  67. package/dist/agent-src/commands/image/verify.md +1 -0
  68. package/dist/agent-src/commands/image.md +16 -12
  69. package/dist/agent-src/commands/implement-ticket.md +1 -0
  70. package/dist/agent-src/commands/judge/on-diff.md +1 -0
  71. package/dist/agent-src/commands/judge/solo.md +1 -0
  72. package/dist/agent-src/commands/judge/steps.md +1 -0
  73. package/dist/agent-src/commands/judge.md +1 -0
  74. package/dist/agent-src/commands/knowledge/cross-repo.md +1 -0
  75. package/dist/agent-src/commands/knowledge/forget.md +1 -0
  76. package/dist/agent-src/commands/knowledge/ingest.md +1 -0
  77. package/dist/agent-src/commands/knowledge/list.md +10 -0
  78. package/dist/agent-src/commands/knowledge.md +1 -0
  79. package/dist/agent-src/commands/memory/learn-low-impact.md +1 -0
  80. package/dist/agent-src/commands/memory/mine-session.md +1 -0
  81. package/dist/agent-src/commands/memory/promote.md +3 -2
  82. package/dist/agent-src/commands/memory.md +1 -0
  83. package/dist/agent-src/commands/mission/upgrade.md +45 -24
  84. package/dist/agent-src/commands/mode.md +1 -0
  85. package/dist/agent-src/commands/module/create.md +1 -0
  86. package/dist/agent-src/commands/module/explore.md +1 -0
  87. package/dist/agent-src/commands/module.md +1 -0
  88. package/dist/agent-src/commands/optimize/agents-dir.md +1 -0
  89. package/dist/agent-src/commands/optimize/project.md +1 -0
  90. package/dist/agent-src/commands/optimize/prompt.md +1 -0
  91. package/dist/agent-src/commands/optimize.md +2 -1
  92. package/dist/agent-src/commands/orchestrate.md +1 -0
  93. package/dist/agent-src/commands/override.md +1 -0
  94. package/dist/agent-src/commands/package.md +2 -1
  95. package/dist/agent-src/commands/post-as/ghostwriter.md +1 -0
  96. package/dist/agent-src/commands/post-as/me.md +1 -0
  97. package/dist/agent-src/commands/post-as.md +1 -0
  98. package/dist/agent-src/commands/pr/create/description-only.md +139 -8
  99. package/dist/agent-src/commands/pr/create.md +35 -22
  100. package/dist/agent-src/commands/prediction-pool.md +7 -6
  101. package/dist/agent-src/commands/prepare-for-review.md +1 -0
  102. package/dist/agent-src/commands/profile/activate.md +1 -0
  103. package/dist/agent-src/commands/profile/deactivate.md +1 -0
  104. package/dist/agent-src/commands/profile.md +1 -0
  105. package/dist/agent-src/commands/project.md +2 -1
  106. package/dist/agent-src/commands/refine-ticket.md +7 -0
  107. package/dist/agent-src/commands/research/deep.md +1 -0
  108. package/dist/agent-src/commands/research.md +1 -0
  109. package/dist/agent-src/commands/review/routing.md +1 -0
  110. package/dist/agent-src/commands/review.md +2 -1
  111. package/dist/agent-src/commands/roadmap/ai-council.md +1 -0
  112. package/dist/agent-src/commands/roadmap/materialize.md +1 -0
  113. package/dist/agent-src/commands/roadmap/process-full.md +1 -0
  114. package/dist/agent-src/commands/roadmap/process-phase.md +1 -0
  115. package/dist/agent-src/commands/roadmap/process-step.md +1 -0
  116. package/dist/agent-src/commands/roadmap.md +1 -0
  117. package/dist/agent-src/commands/security-audit-config.md +2 -1
  118. package/dist/agent-src/commands/skill/preview.md +1 -0
  119. package/dist/agent-src/commands/skill.md +1 -0
  120. package/dist/agent-src/commands/skills/discover.md +1 -0
  121. package/dist/agent-src/commands/skills.md +1 -0
  122. package/dist/agent-src/commands/sync/agent-settings.md +1 -0
  123. package/dist/agent-src/commands/sync.md +2 -1
  124. package/dist/agent-src/commands/team/adversarial.md +3 -2
  125. package/dist/agent-src/commands/team/delegate.md +3 -2
  126. package/dist/agent-src/commands/team/review.md +3 -2
  127. package/dist/agent-src/commands/team/status.md +49 -18
  128. package/dist/agent-src/commands/team-knowledge.md +8 -6
  129. package/dist/agent-src/commands/team.md +21 -16
  130. package/dist/agent-src/commands/tests/e2e-heal.md +1 -0
  131. package/dist/agent-src/commands/tests/e2e-plan.md +1 -0
  132. package/dist/agent-src/commands/tests/execute.md +1 -0
  133. package/dist/agent-src/commands/tests.md +2 -1
  134. package/dist/agent-src/commands/update-form-request-messages.md +1 -0
  135. package/dist/agent-src/commands/upstream-contribute.md +1 -0
  136. package/dist/agent-src/commands/video/from-script.md +3 -2
  137. package/dist/agent-src/commands/video/from-song.md +22 -21
  138. package/dist/agent-src/commands/video/scene.md +1 -0
  139. package/dist/agent-src/commands/video/stitch.md +2 -1
  140. package/dist/agent-src/commands/video/storyboard.md +1 -0
  141. package/dist/agent-src/commands/video.md +1 -0
  142. package/dist/agent-src/commands/work.md +1 -0
  143. package/dist/agent-src/commands/worktree/cleanup.md +8 -7
  144. package/dist/agent-src/commands/worktree/create.md +1 -0
  145. package/dist/agent-src/commands/worktree/verify.md +1 -0
  146. package/dist/agent-src/commands/worktree.md +1 -0
  147. package/dist/agent-src/rules/active-remediation.md +12 -36
  148. package/dist/agent-src/rules/artifact-drafting-protocol.md +7 -64
  149. package/dist/agent-src/rules/context-hygiene.md +19 -113
  150. package/dist/agent-src/rules/design-fidelity.md +4 -60
  151. package/dist/agent-src/rules/domain-adoption-policy.md +10 -106
  152. package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +12 -60
  153. package/dist/agent-src/rules/improve-before-implement.md +4 -0
  154. package/dist/agent-src/rules/minimal-safe-diff.md +6 -86
  155. package/dist/agent-src/rules/size-enforcement.md +10 -0
  156. package/dist/agent-src/rules/tool-safety.md +17 -3
  157. package/dist/agent-src/skills/agent-security-review/SKILL.md +12 -1
  158. package/dist/agent-src/skills/ai-council/SKILL.md +11 -0
  159. package/dist/agent-src/skills/bug-analyzer/SKILL.md +24 -2
  160. package/dist/agent-src/skills/code-review/SKILL.md +105 -93
  161. package/dist/agent-src/skills/code-review/checklists/backend.md +50 -0
  162. package/dist/agent-src/skills/code-review/checklists/database.md +19 -0
  163. package/dist/agent-src/skills/code-review/checklists/dependency.md +18 -0
  164. package/dist/agent-src/skills/code-review/checklists/docs.md +14 -0
  165. package/dist/agent-src/skills/code-review/checklists/frontend.md +19 -0
  166. package/dist/agent-src/skills/code-review/checklists/infra.md +17 -0
  167. package/dist/agent-src/skills/code-review/checklists/producing-the-review.md +62 -0
  168. package/dist/agent-src/skills/code-review/checklists/test-only.md +13 -0
  169. package/dist/agent-src/skills/code-review/evals/evals.json +53 -15
  170. package/dist/agent-src/skills/condense-memory/SKILL.md +3 -2
  171. package/dist/agent-src/skills/conventional-commits-writing/evals/evals.json +15 -0
  172. package/dist/agent-src/skills/docker/SKILL.md +10 -0
  173. package/dist/agent-src/skills/docx-authoring/SKILL.md +102 -0
  174. package/dist/agent-src/skills/github-ci/evals/evals.json +25 -0
  175. package/dist/agent-src/skills/humanizer/SKILL.md +79 -3
  176. package/dist/agent-src/skills/humanizer/references/anti-aiisms.md +112 -0
  177. package/dist/agent-src/skills/humanizer/references/fixtures.md +70 -0
  178. package/dist/agent-src/skills/judge-bug-hunter/SKILL.md +7 -1
  179. package/dist/agent-src/skills/laravel/SKILL.md +10 -0
  180. package/dist/agent-src/skills/launch-readiness/SKILL.md +35 -0
  181. package/dist/agent-src/skills/llm-provider-knowledge/SKILL.md +146 -0
  182. package/dist/agent-src/skills/llm-provider-knowledge/evals/triggers.json +20 -0
  183. package/dist/agent-src/skills/merge-conflicts/SKILL.md +30 -0
  184. package/dist/agent-src/skills/pdf-tools/SKILL.md +101 -0
  185. package/dist/agent-src/skills/quality-tools/evals/evals.json +15 -0
  186. package/dist/agent-src/skills/security-audit/SKILL.md +29 -0
  187. package/dist/agent-src/skills/security-maturity-assessment/SKILL.md +90 -0
  188. package/dist/agent-src/skills/security-maturity-assessment/evals/triggers.json +52 -0
  189. package/dist/agent-src/skills/skill-writing/SKILL.md +79 -0
  190. package/dist/agent-src/skills/spreadsheet-authoring/SKILL.md +11 -3
  191. package/dist/agent-src/skills/subagent-orchestration/prompts/README.md +11 -0
  192. package/dist/agent-src/skills/subagent-orchestration/schemas/team-review-status.json +103 -0
  193. package/dist/agent-src/skills/terraform/SKILL.md +10 -0
  194. package/dist/agent-src/skills/test-driven-development/SKILL.md +31 -0
  195. package/dist/agent-src/skills/threat-modeling/SKILL.md +15 -0
  196. package/dist/agent-src/skills/token-optimizer/SKILL.md +10 -4
  197. package/dist/agent-src/templates/agent-settings.md +28 -0
  198. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  199. package/dist/agent-src/templates/scripts/telemetry/aggregator.ts +0 -0
  200. package/dist/agent-src/templates/scripts/telemetry/engagement.ts +30 -0
  201. package/dist/agent-src/templates/scripts/telemetry/report_renderer.ts +22 -9
  202. package/dist/agent-src/templates/scripts/telemetry_record.ts +5 -0
  203. package/dist/agent-src/templates/scripts/work_engine/_lib/agent_settings.ts +4 -1
  204. package/dist/discovery/deprecation-report.md +1 -1
  205. package/dist/discovery/discovery-manifest.json +314 -194
  206. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  207. package/dist/discovery/discovery-manifest.summary.md +5 -5
  208. package/dist/discovery/orphan-report.md +1 -1
  209. package/dist/discovery/packs.json +23 -18
  210. package/dist/discovery/trust-report.md +8 -8
  211. package/dist/discovery/workspaces.json +18 -13
  212. package/dist/install/install.mjs +48 -33
  213. package/dist/mcp/registry-manifest.json +3 -3
  214. package/dist/router.json +1 -1
  215. package/dist/scripts/_lib/agent_settings.js +4 -1
  216. package/dist/scripts/_lib/agent_settings.js.map +1 -1
  217. package/dist/scripts/condense.js +5 -0
  218. package/dist/scripts/condense.js.map +1 -1
  219. package/dist/server/schemas/settings.js +10 -1
  220. package/dist/server/schemas/settings.js.map +1 -1
  221. package/docs/CLAIMS.md +9 -2
  222. package/docs/MIGRATION.md +20 -0
  223. package/docs/SKILL_CENSUS.md +8 -0
  224. package/docs/architecture.md +3 -3
  225. package/docs/benchmark.md +67 -2
  226. package/docs/catalog.md +2 -2
  227. package/docs/command-flows.md +1 -1
  228. package/docs/contracts/agents-layout.md +1 -1
  229. package/docs/contracts/ai-council-config.md +9 -2
  230. package/docs/contracts/ai-team-config.md +37 -4
  231. package/docs/contracts/consumer-bridge.md +55 -63
  232. package/docs/contracts/install-layout.md +1 -1
  233. package/docs/contracts/migrate-command.md +1 -1
  234. package/docs/contracts/prelaunch-diagnostics.md +151 -0
  235. package/docs/contracts/release-pr-gating.md +1 -0
  236. package/docs/customization.md +22 -1
  237. package/docs/decisions/ADR-020-global-only-consumer-scope.md +34 -0
  238. package/docs/decisions/ADR-049-configuration-trust-boundary.md +9 -1
  239. package/docs/featured-skills.md +2 -2
  240. package/docs/getting-started-by-role.md +1 -1
  241. package/docs/getting-started.md +17 -6
  242. package/docs/governance-advantage.md +1 -1
  243. package/docs/guidelines/agent-infra/active-remediation-mechanics.md +45 -0
  244. package/docs/guidelines/agent-infra/agent-interaction-and-decision-quality.md +28 -0
  245. package/docs/guidelines/agent-infra/api-cost-levers.md +126 -0
  246. package/docs/guidelines/agent-infra/artifact-drafting-protocol-mechanics.md +76 -0
  247. package/docs/guidelines/agent-infra/context-hygiene-mechanics.md +90 -0
  248. package/docs/guidelines/agent-infra/domain-adoption-gates.md +112 -0
  249. package/docs/guidelines/agent-infra/framework-neutrality-patterns.md +66 -0
  250. package/docs/guidelines/agent-infra/minimal-safe-diff-mechanics.md +99 -0
  251. package/docs/guidelines/agent-infra/skill-quality-checklist.md +13 -0
  252. package/docs/guidelines/design-fidelity-mechanics.md +76 -0
  253. package/docs/installation.md +2 -1
  254. package/docs/maintainers/dev-mode.md +3 -2
  255. package/docs/parity/command-frontmatter.md +60 -0
  256. package/docs/proof.md +7 -6
  257. package/package.json +1 -1
  258. package/src/agent-src/templates/scripts/telemetry/aggregator.ts +0 -0
  259. package/src/agent-src/templates/scripts/telemetry/engagement.ts +30 -0
  260. package/src/agent-src/templates/scripts/telemetry/report_renderer.ts +22 -9
  261. package/src/agent-src/templates/scripts/telemetry_record.ts +5 -0
  262. package/src/agent-src/templates/scripts/work_engine/_lib/agent_settings.ts +4 -1
  263. package/src/config/agent-settings.template.yml +73 -10
  264. package/src/config/gitignore-block.txt +16 -6
  265. package/src/config/prelaunch-areas.yml +36 -0
  266. package/src/scripts/_cli/cmd_conformance.ts +2 -2
  267. package/src/scripts/_cli/cmd_doctor.ts +280 -39
  268. package/src/scripts/_cli/cmd_refresh.ts +35 -118
  269. package/src/scripts/_lib/agent_settings.ts +4 -1
  270. package/src/scripts/_lib/claude_plugin.ts +77 -2
  271. package/src/scripts/_lib/orchestration_record.ts +5 -0
  272. package/src/scripts/_lib/tool_adapter_registry.ts +120 -0
  273. package/src/scripts/ai_council/clients.ts +68 -6
  274. package/src/scripts/ai_council/pricing.ts +62 -0
  275. package/src/scripts/ai_team/config.ts +73 -1
  276. package/src/scripts/ai_team/review_gate.ts +636 -0
  277. package/src/scripts/ai_team/team_dispatch.ts +612 -0
  278. package/src/scripts/bench_ab_task_runner.ts +11 -1
  279. package/src/scripts/bench_parity_count.ts +279 -0
  280. package/src/scripts/build_linear_digest.ts +3 -1
  281. package/src/scripts/check_bridge_derivation.ts +172 -0
  282. package/src/scripts/check_consumer_scope_flip.ts +179 -0
  283. package/src/scripts/check_council_config_location.ts +115 -15
  284. package/src/scripts/check_host_loadability.ts +81 -0
  285. package/src/scripts/condense.ts +5 -0
  286. package/src/scripts/council_cli.ts +19 -3
  287. package/src/scripts/hook_manifest.yaml +12 -1
  288. package/src/scripts/install.ts +44 -45
  289. package/src/scripts/lint_agents_layout.ts +10 -4
  290. package/src/scripts/lint_breaking_changes_index.ts +303 -0
  291. package/src/scripts/lint_handoffs.ts +42 -0
  292. package/src/scripts/lint_skill_descriptions.ts +228 -0
  293. package/src/scripts/lint_skill_descriptions_allowlist.json +1 -0
  294. package/src/scripts/lint_skill_scripts_readonly.ts +145 -0
  295. package/src/scripts/lint_skill_scripts_readonly_allowlist.json +8 -0
  296. package/src/scripts/lint_supported_tools_matrix.ts +35 -0
  297. package/src/scripts/mcp_server/tools.ts +1 -3
  298. package/src/scripts/optimize_skill_description.ts +144 -0
  299. package/src/scripts/orchestration_record.ts +2 -1
  300. package/src/scripts/prelaunch_diagnostics.ts +248 -0
  301. package/src/scripts/run_skill_evals.ts +70 -4
  302. package/src/scripts/schemas/agent-settings.schema.json +17 -0
  303. package/src/scripts/schemas/command.schema.json +7 -0
  304. package/src/scripts/schemas/evals.schema.json +105 -14
  305. package/src/scripts/schemas/prelaunch-report.schema.json +107 -0
  306. package/src/scripts/schemas/skill.schema.json +18 -1
  307. package/src/scripts/schemas/subagent.schema.json +6 -0
  308. package/src/scripts/self_review_gate.test.ts +11 -0
  309. package/src/scripts/self_review_gate.ts +7 -1
  310. package/src/scripts/skill_eval_coverage.ts +4 -1
  311. package/src/scripts/skill_linter.ts +43 -3
  312. package/src/scripts/smoke_host_loadability.sh +73 -0
  313. package/src/scripts/team_review_gate_hook.ts +115 -0
  314. package/src/scripts/trigger_eval_grandfather.json +1 -2
  315. package/src/scripts/utilization_report.ts +225 -0
  316. package/src/server/schemas/settings.ts +24 -1
@@ -0,0 +1,52 @@
1
+ {
2
+ "skill": "security-maturity-assessment",
3
+ "last_eval": "2026-07-12",
4
+ "description": "5 should-trigger + 5 should-not-trigger queries. Should-trigger covers DE + EN posture/scorecard/baseline phrasings. Should-not-trigger covers the neighbouring security skills (vuln hunt, authz chain, threat model, secure coding, agent config) whose vocabulary overlaps.",
5
+ "queries": [
6
+ {
7
+ "q": "how mature is the security posture of our billing module?",
8
+ "trigger": true
9
+ },
10
+ {
11
+ "q": "give me a security scorecard for this codebase with evidence per category",
12
+ "trigger": true
13
+ },
14
+ {
15
+ "q": "wie sicher ist dieses Modul aufgestellt? Bitte pro Kategorie bewerten",
16
+ "trigger": true
17
+ },
18
+ {
19
+ "q": "baseline our security maturity before the hardening sprint",
20
+ "trigger": true
21
+ },
22
+ {
23
+ "q": "rate input validation, secrets and tenant isolation for the API package",
24
+ "trigger": true
25
+ },
26
+ {
27
+ "q": "audit this module for SQL injection and XSS vulnerabilities",
28
+ "trigger": false,
29
+ "note": "vulnerability hunt → security-audit"
30
+ },
31
+ {
32
+ "q": "review the authorization chain for the invoice download route",
33
+ "trigger": false,
34
+ "note": "single-route authz → authz-review"
35
+ },
36
+ {
37
+ "q": "threat-model the new file-upload feature before we build it",
38
+ "trigger": false,
39
+ "note": "pre-implementation → threat-modeling"
40
+ },
41
+ {
42
+ "q": "write a policy and gate for this new admin action",
43
+ "trigger": false,
44
+ "note": "writing secure code → security"
45
+ },
46
+ {
47
+ "q": "red-team my Claude agent's MCP and hook config",
48
+ "trigger": false,
49
+ "note": "agent config/behaviour → agent-security-review"
50
+ }
51
+ ]
52
+ }
@@ -451,12 +451,91 @@ to every skill you author.
451
451
  4. Does the description carry filler ("comprehensive", "advanced",
452
452
  "powerful")?
453
453
 
454
+ ## Read-only-by-default scripts
455
+
456
+ A script shipped inside a skill (`scripts/**`) is **side-effect-free by
457
+ default** — inspects, computes, prints; does not mutate. Mutation (write /
458
+ delete / rename / copy) gates behind an explicit flag named in this SKILL.md —
459
+ `--writable` / `--apply` / `--write` / `--output` / `--fix` — so the default
460
+ invocation is safe. A generator whose *declared purpose* is to write (emits an
461
+ artifact to a caller-supplied path) is allowlisted with a rationale in
462
+ `src/scripts/lint_skill_scripts_readonly_allowlist.json` instead of a redundant
463
+ flag. `lint_skill_scripts_readonly` enforces this: an ungated, non-allowlisted
464
+ write fails the build.
465
+
466
+ ## Description-optimizer loop (U1 — held-out, not vibes)
467
+
468
+ Descriptions are the trigger surface; tune them like a model, not like prose:
469
+
470
+ 1. Draft 2-3 candidate descriptions for the skill.
471
+ 2. Ensure `evals/triggers.json` has should- AND should-not-trigger queries
472
+ (grow beyond the 5+5 stub when optimizing — more queries = a real test split).
473
+ 3. Run the helper: `npx tsx src/scripts/optimize_skill_description.ts
474
+ --skill <id> --candidate "…" [--candidate "…"] [--live]` — it splits the
475
+ queries deterministically into train/held-out, scores every candidate
476
+ (deterministic token-overlap proxy by default; `--live` = haiku judge,
477
+ ~$0.001 per query·candidate), and picks the best **held-out** accuracy.
478
+ 4. Adopt the pick ONLY if it beats the current description on the held-out
479
+ split — a train-only win is overfitting to the queries you wrote.
480
+
481
+ ## Self-QA loop for output-producing skills (optional pattern)
482
+
483
+ For skills whose product is a rendered/structural artifact (decks, docs,
484
+ diagrams, dashboards, generated UI): **assume there are problems** and have a
485
+ fresh-eyes pass find them before handing back. The author-context is blind to
486
+ its own omissions; a context-free verifier is not.
487
+
488
+ 1. Produce the artifact.
489
+ 2. Dispatch a fresh subagent (no authoring context) with ONLY the artifact +
490
+ the acceptance criteria: "list every visual/structural defect; assume at
491
+ least one exists."
492
+ 3. Fix what it finds; re-run once. Two clean passes → done.
493
+
494
+ Worked example (deck skill): the author renders 12 slides; the fresh-eyes
495
+ pass gets the PDF + "check overflow, contrast, orphaned bullets, broken
496
+ images" — it flags a clipped title on slide 7 the author never re-read.
497
+ One fix, one re-check, done.
498
+
499
+ Scope: complements `verify-before-complete` (which gates the completion
500
+ claim); this pattern is HOW to get the fresh evidence for artifacts where no
501
+ deterministic checker exists. Skip it when a real validator covers the
502
+ surface (linter, schema, test) — deterministic checks beat judge passes.
503
+
504
+ ## Known-pitfalls section (optional pattern, tool skills)
505
+
506
+ Tool/integration skills teach the happy path; the recurring support burden is
507
+ the *silent* failures — the ones that cost money, corrupt state, or fail with no
508
+ error. For a high-support-burden tool skill, add a `## Known pitfalls` section
509
+ in this micro-format:
510
+
511
+ 1. **A Symptom → Root cause → Fix table.** Each row starts from the *observable
512
+ symptom* (what the user sees), not the internal cause — the user greps for
513
+ the symptom, not the fix.
514
+
515
+ | Symptom | Root cause | Fix |
516
+ |---|---|---|
517
+ | `<what the user observes>` | `<why it happens>` | `<the concrete action>` |
518
+
519
+ 2. **Optionally, a quick-reference anti-pattern checklist** (Anti-pattern ·
520
+ cost/impact · fix difficulty) for traps worth scanning before shipping — add
521
+ it only when it does not restate the skill's existing `## Gotcha` / `## Do
522
+ NOT`; the table is the load-bearing part.
523
+
524
+ Sourcing floor — **real, not invented**: every entry names a genuinely common
525
+ failure (a high-vote community question, a documented incident class), never a
526
+ hypothetical. **≤ 5 entries per skill.** The value is a short, sourced,
527
+ high-signal list; a long one is noise. A pitfall is a *section on the existing
528
+ tool skill*, **never** a new skill per pitfall and never a generated grid (see
529
+ [`size-enforcement`](../../rules/size-enforcement.md) § Per-tool pitfall
530
+ content).
531
+
454
532
  ## Do NOT
455
533
 
456
534
  * Write documentation-style, pointer-only, or too-broad skills ("Laravel skill")
457
535
  * Skip Procedure or use vague validation
458
536
  * Exceed size limits (see `docs/guidelines/agent-infra/size-and-scope.md`)
459
537
  * Duplicate rules
538
+ * Ship a skill script that mutates the filesystem on its default invocation — gate it behind a flag or allowlist it with a rationale
460
539
 
461
540
  ## Encode usage policy in the description
462
541
 
@@ -41,9 +41,17 @@ prose document/table (that is the document surface, `doc-coauthoring`).
41
41
  2. **Formulas over hardcoded values.** Any computed cell holds a **formula**
42
42
  (`=SUM(...)`, `=B2*C2`), never the typed-in result. Hardcoding a computed
43
43
  value is the cardinal spreadsheet defect — it does not recalculate.
44
- 3. **Read back after every write.** After writing a formula, read the cell back
45
- and confirm no formula error (`#REF!`, `#DIV/0!`, `#VALUE!`). The read-back is
46
- the spreadsheet's verification truth source.
44
+ 3. **Read back after every write, and RECALCULATE first.** After writing a
45
+ formula, force a recalculation, then read the cell back — a library that
46
+ writes formulas without recalculating leaves the cached value stale, so a
47
+ read-back before recalc proves nothing. The **zero-formula-error contract**:
48
+ any of `#REF!` / `#DIV/0!` / `#VALUE!` / `#N/A` / `#NAME?` in a written cell
49
+ is a **failure**, not a warning — reject the output and fix the formula. The
50
+ recalc'd read-back is the spreadsheet's verification truth source.
51
+ **Formulas, never hardcoded computed values** — a library that writes the
52
+ Python-computed number into the cell instead of the `=` formula has produced
53
+ a dead spreadsheet that will not update when inputs change; write the formula
54
+ string and let the recalc compute it.
47
55
  4. **Source-comment web-sourced cells.** Any figure taken from the web carries a
48
56
  cell comment with its source. Financial figures follow the
49
57
  [`spreadsheet-source-quality`](../../rules/spreadsheet-source-quality.md) rule
@@ -33,6 +33,17 @@ hits (Anthropic `cache_control: ephemeral`) across the cohort — the prefix is
33
33
  cached after the first sibling and served from cache for the rest, cutting
34
34
  input-token cost proportionally to cohort size.
35
35
 
36
+ **Break-even + failure modes.** A cache write costs ~1.25× the base input rate
37
+ (5-min TTL); a read costs ~0.1×. So the prefix pays off once **≥ 2** siblings
38
+ read it — a lone subagent with no sibling reuse only pays the write premium and
39
+ saves nothing. The cache is a **byte-exact prefix match**: any drift in the
40
+ shared prefix (a timestamp, a per-sibling id, reordered text) forces a re-write
41
+ instead of a read, and the prefix must be re-hit within the **5-minute TTL**, so
42
+ dispatch siblings promptly rather than trickling them. This is why the win is
43
+ real for **fan-out** (many siblings, one prefix) and marginal for one-shot
44
+ dispatch. Verify a cohort is actually reading, not re-writing, by checking
45
+ `usage.cache_read_input_tokens > 0` on the 2nd+ sibling.
46
+
36
47
  ## Loading
37
48
 
38
49
  `tests/test_subagent_prompt_loading.py` asserts that every mode named
@@ -0,0 +1,103 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft-07/schema#",
3
+ "$id": "https://event4u.dev/agent-config/schemas/team-review-status.json",
4
+ "title": "Team Review Status Envelope",
5
+ "description": "Wire format for every /team:review return — plugin path and multi-host fallback alike. Extends the subagent-status.json frame (same status enum, same NEEDS_CONTEXT/BLOCKED semantics) with review findings, the reviewed ref, and quota visibility. Emitted by src/scripts/ai_team/team_dispatch.ts; contract prose in docs/contracts/ai-team-config.md.",
6
+ "type": "object",
7
+ "required": ["status", "findings", "reviewed_ref", "model", "quota"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "status": {
11
+ "type": "string",
12
+ "enum": ["DONE", "DONE_WITH_CONCERNS", "NEEDS_CONTEXT", "BLOCKED"],
13
+ "description": "DONE = review ran, no findings above info. DONE_WITH_CONCERNS = review ran and findings[] needs the caller's attention, OR the model output was unparseable (raw carries the verbatim text — never silently dropped). NEEDS_CONTEXT = reviewer lacks context beyond the bundle; blocking_question must be answered. BLOCKED = no review was produced (auth, quota, transport); blocking_reason describes why."
14
+ },
15
+ "summary": {
16
+ "type": "string",
17
+ "minLength": 1,
18
+ "description": "One- or two-sentence review outcome."
19
+ },
20
+ "findings": {
21
+ "type": "array",
22
+ "description": "Review findings. Empty for a clean DONE and for BLOCKED (no review happened).",
23
+ "items": {
24
+ "type": "object",
25
+ "required": ["severity", "evidence", "suggested_fix"],
26
+ "additionalProperties": false,
27
+ "properties": {
28
+ "severity": {
29
+ "type": "string",
30
+ "enum": ["critical", "major", "minor", "info"],
31
+ "description": "critical = data loss / security / correctness on the main path. major = real defect, wrong under realistic input. minor = defect on an edge path or maintainability trap. info = observation, no action required."
32
+ },
33
+ "evidence": {
34
+ "type": "string",
35
+ "minLength": 1,
36
+ "description": "What is wrong, citing the exact hunk/line from the reviewed diff — never invented code."
37
+ },
38
+ "suggested_fix": {
39
+ "type": "string",
40
+ "minLength": 1,
41
+ "description": "Concrete, minimal fix proposal."
42
+ },
43
+ "location": {
44
+ "type": "string",
45
+ "description": "file[:line] when known."
46
+ }
47
+ }
48
+ }
49
+ },
50
+ "reviewed_ref": {
51
+ "type": "string",
52
+ "minLength": 1,
53
+ "description": "HEAD sha the repo-context bundle was built from — pins what was actually reviewed."
54
+ },
55
+ "model": {
56
+ "type": "string",
57
+ "minLength": 1,
58
+ "description": "Reviewer model id, or the literal 'auto' when the codex CLI default was used (no --model flag passed)."
59
+ },
60
+ "quota": {
61
+ "type": "object",
62
+ "required": ["used", "ceiling"],
63
+ "additionalProperties": false,
64
+ "description": "Shared cli_call_budget openai-bucket visibility after this run.",
65
+ "properties": {
66
+ "used": {
67
+ "type": "integer",
68
+ "minimum": 0,
69
+ "description": "Today's openai-bucket call count (UTC-day, shared with the council)."
70
+ },
71
+ "ceiling": {
72
+ "type": "integer",
73
+ "minimum": 0,
74
+ "description": "ai_team.max_calls_per_day — the team-side ceiling on the shared bucket."
75
+ }
76
+ }
77
+ },
78
+ "raw": {
79
+ "type": "string",
80
+ "description": "Verbatim model output, present ONLY when the findings contract could not be parsed (status is then DONE_WITH_CONCERNS). Preserved so a malformed review is loud, never dropped."
81
+ },
82
+ "blocking_question": {
83
+ "type": "string",
84
+ "minLength": 1,
85
+ "description": "Single specific question whose answer would unblock. Required when status = NEEDS_CONTEXT."
86
+ },
87
+ "blocking_reason": {
88
+ "type": "string",
89
+ "minLength": 1,
90
+ "description": "Why no review was produced (auth_expired → codex login, cli_quota_exhausted, transport error). Required when status = BLOCKED."
91
+ }
92
+ },
93
+ "allOf": [
94
+ {
95
+ "if": {"properties": {"status": {"const": "NEEDS_CONTEXT"}}, "required": ["status"]},
96
+ "then": {"required": ["blocking_question"]}
97
+ },
98
+ {
99
+ "if": {"properties": {"status": {"const": "BLOCKED"}}, "required": ["status"]},
100
+ "then": {"required": ["blocking_reason"]}
101
+ }
102
+ ]
103
+ }
@@ -128,6 +128,16 @@ Each env has a GitHub IAM role with:
128
128
  - resources
129
129
  - state management
130
130
 
131
+ ## Known pitfalls
132
+
133
+ | Symptom | Root cause | Fix |
134
+ |---|---|---|
135
+ | `Error acquiring the state lock` blocks every command | A prior `apply` crashed / was killed and left the lock held (DynamoDB / backend lock) | Confirm no apply is actually running, then `terraform force-unlock <lock-id>` — never delete the lock table |
136
+ | `plan` wants to destroy+recreate a resource after a rename | Renaming a resource block changes its address; Terraform sees the old address gone and a new one added | `terraform state mv <old.addr> <new.addr>` (or a `moved {}` block) so it tracks the same object |
137
+ | `count`/`for_each` errors with "value depends on resource attributes that cannot be determined until apply" | The count/for_each expression reads an unknown (not-yet-created) value | Key `for_each` off a static/known map, or split into a two-stage apply with `-target` |
138
+ | A change applies but the next `plan` shows the same diff again (perpetual diff) | The provider normalizes/computes the attribute differently than written (ordering, defaults, case) | Match the provider's canonical form, or `ignore_changes` on that attribute in `lifecycle` |
139
+ | `plan` shows a resource as tainted/replaced after a manual console change | Out-of-band drift — someone edited the resource outside Terraform | `terraform apply -refresh-only` to reconcile state, then decide code-vs-cloud; stop the manual edits |
140
+
131
141
  ## Gotcha
132
142
 
133
143
  - `terraform apply` without `-auto-approve` requires interactive confirmation — don't use in CI without the flag.
@@ -83,6 +83,37 @@ talked-around. Externalized to
83
83
  [`testing-anti-patterns/process-anti-patterns.md`](../testing-anti-patterns/process-anti-patterns.md)
84
84
  to keep this skill under the 400-line sunset trigger.
85
85
 
86
+ ## Mode contracts — Goal / Activities / Forbidden / Output
87
+
88
+ The flow runs as four modes. Each Forbidden item names **how a reviewer
89
+ checks it from the diff** — an unverifiable prohibition does not ship.
90
+
91
+ | Mode | Goal | Activities | Forbidden (diff check) | Output contract |
92
+ |---|---|---|---|---|
93
+ | **Design** | One-sentence behavior + enumerated cases | Steps 1–2 | **No production code** (diff touches no `src/**` production path) · no test bodies yet | Case list (happy/boundary/error) |
94
+ | **Test-Red** | A failing test that fails RIGHT | Steps 3–4 | **No production edits** (diff = `tests/**` only) · test must fail at an **assertion, not an import/setup error** (failure output cites the assertion line) | Failing test + its observed failure reason |
95
+ | **Implement** | Minimum code to green | Steps 5–6 | **No test edits** (no `tests/**` paths in Implement-phase diffs — changing the assertion to fit the code is the canonical violation; genuinely-wrong test → STOP and ask, never silently edit) · no scope beyond the one case | Green run output |
96
+ | **Debug** | Fix a defect found later | (re-enter at 3) | **No bugfix before a reproducing regression test exists** (the fix commit contains a `tests/**` addition that fails without the fix) | Regression test + fix, verified red→green |
97
+
98
+ ### Mode inference on resume
99
+
100
+ Step 0 of any resume: if `agents/runtime/state/HANDOFF.md` exists, resume
101
+ from its Mode + Contract-owed fields (see `/agent-handoff` file mode) instead
102
+ of re-deriving. Otherwise infer the mode from observable state — never
103
+ assume Design:
104
+
105
+ | Observed state | Resume in |
106
+ |---|---|
107
+ | No test for the target behavior | Design |
108
+ | Test exists, currently failing at an assertion | Implement |
109
+ | Test exists + passing, defect reported | Debug |
110
+ | Test failing at import/collection error | Test-Red (fix the test, not the code) |
111
+
112
+ At every mode transition, one consent-checkpoint sentence (per
113
+ `ask-when-uncertain` / `autonomous-execution` — no new mechanism): name the
114
+ mode you are leaving, the output contract you hand over, and the mode you
115
+ enter; under an autonomous mandate the sentence is stated, not asked.
116
+
86
117
  ## Procedure
87
118
 
88
119
  ### 1. Identify the behavior to test
@@ -93,6 +93,21 @@ For every distinct abuse case, answer:
93
93
  Prioritize by **impact × plausibility**, not by novelty. Skip generic
94
94
  OWASP bullets unless you can anchor them in a concrete file or line.
95
95
 
96
+ ### 3b. STRIDE coverage check
97
+
98
+ Sweep the six STRIDE categories once against the change so no threat class is silently skipped. Each row names the question + control family the suite already teaches — anchor any hit in a concrete file per § 3.
99
+
100
+ | STRIDE category | Ask about this change | Control family (suite reference) |
101
+ |---|---|---|
102
+ | **S**poofing | Can an actor claim another identity on this path? | Authentication at the boundary; token/session verification — [`security`](../security/SKILL.md) |
103
+ | **T**ampering | Can the payload or stored state be modified in transit or at rest? | Request-boundary validation + signed webhooks + parameterized queries — [`laravel-validation`](../laravel-validation/SKILL.md) / [`sql-writing`](../sql-writing/SKILL.md) |
104
+ | **R**epudiation | Could the actor later deny having performed the action? | Audit logging of security events (actor + outcome, no credentials) — [`logging-monitoring`](../logging-monitoring/SKILL.md) |
105
+ | **I**nformation disclosure | What leaks if this path errors, over-serializes, or logs? | Field whitelisting + scrubbed errors/logs — [`domain-safety-pii`](../../rules/domain-safety-pii.md) |
106
+ | **D**enial of service | Can this path be made expensive or unbounded by an attacker? | Rate limiting + bounded queries/uploads — [`security-audit`](../security-audit/SKILL.md) § rate limiting, [`performance`](../performance/SKILL.md) |
107
+ | **E**levation of privilege | Can a lower-privilege actor reach a higher-privilege action or object? | Per-object authorization + tenant scope — [`authz-review`](../authz-review/SKILL.md), [`broken-access-control`](../../rules/broken-access-control.md) |
108
+
109
+ Category with no plausible abuse case for this change → mark "n/a — no boundary crossed", never silently omit.
110
+
96
111
  ### 4. Convert risks to engineering actions
97
112
 
98
113
  For each prioritized abuse case, propose the **smallest effective control**
@@ -64,10 +64,15 @@ INTENT
64
64
  │ → cite [agent-handoff](../../../.claude/skills/agent-handoff/SKILL.md)
65
65
  │ (structured handoff envelope; resume in fresh chat)
66
66
  │
67
- └── Cost-aware decision (model pick, budget, stop-criterion)
68
- → cite /cost:report (when shipped) — until then, fall back to
69
- [token-efficiency](../../rules/token-efficiency.md) and
70
- [direct-answers § Brevity by Default](../../rules/direct-answers.md)
67
+ ├── Cost-aware decision (model pick, budget, stop-criterion)
68
+ │ → cite /cost:report (when shipped) — until then, fall back to
69
+ │ [token-efficiency](../../rules/token-efficiency.md) and
70
+ │ [direct-answers § Brevity by Default](../../rules/direct-answers.md)
71
+ │
72
+ └── API-bill lever (stable prefix reused across calls · non-interactive
73
+ bulk cohort · model/effort pick against the paid Anthropic bill)
74
+ → cite [api-cost-levers](../../../docs/guidelines/agent-infra/api-cost-levers.md)
75
+ (prompt caching ~0.1x reads · Batch -50% · model tiering · effort)
71
76
  ```
72
77
 
73
78
  ## Catalog
@@ -81,6 +86,7 @@ INTENT
81
86
  | `direct-answers` | `.agent-src.uncondensed/rules/direct-answers.md` | `brevity`, `flattery`, `severity`, `tiered` | Iron-Law brevity floor (kernel) |
82
87
  | `markitdown` | upstream: github.com/microsoft/markitdown | `PDF`, `DOCX`, `HTML`, `convert` | Document → markdown converter (authoritative-link only) |
83
88
  | `/cost:report` | TBD — an internal roadmap (local-only) | `cost`, `model spend`, `budget` | Per-session cost telemetry (planned) |
89
+ | `api-cost-levers` | `docs/guidelines/agent-infra/api-cost-levers.md` | `cache`, `caching`, `batch`, `tiering`, `effort` | Anthropic billing levers: prompt caching, Batch API, model tiering, effort/output right-sizing |
84
90
 
85
91
  ## Output format
86
92
 
@@ -402,8 +402,31 @@ commands:
402
402
  # When `true`: show title and body in copyable code blocks and ask
403
403
  # for adjustments before creating the PR.
404
404
  # `/create-pr:description-only` always previews — that is its sole purpose.
405
+ #
406
+ # detail_level: verbosity tier of the PR Description body.
407
+ # min (default) = title + 2-3 sentence what/why/impact + linked ticket;
408
+ # med = min + grouped changes + tests note;
409
+ # max = med + how-to-test + edge cases + reviewer guidance.
410
+ # Critical info (breaking changes, migrations, security, rollback) is
411
+ # ALWAYS included at every tier — the tier governs explanatory depth only.
412
+ #
413
+ # api_examples (default true): add a fenced JSON example for API-endpoint
414
+ # changes ONLY when grounded in a real source (DTO/resource, OpenAPI,
415
+ # fixture, probe); else a one-line pointer, never an invented example.
416
+ #
417
+ # screenshots (default false): capability-gated frontend screenshots.
418
+ # true attempts capture only when the host has browser/preview tooling;
419
+ # emits a note and leaves the placeholder when absent — never blocks the PR.
420
+ #
421
+ # ui_paths / api_paths: optional globs to make frontend / API detection
422
+ # explicit; empty = a light heuristic that fails open.
405
423
  create_pr:
406
424
  preview_description: false
425
+ detail_level: min
426
+ api_examples: true
427
+ screenshots: false
428
+ ui_paths: []
429
+ api_paths: []
407
430
 
408
431
  # --- Telemetry (artefact engagement, default-off) ---
409
432
  #
@@ -582,6 +605,11 @@ the canonical narrative lives in
582
605
  | `commands.suggestion.max_options` | integer | `4` | Max number of command suggestions before the always-present "run as-is" option (total rendered = `max_options + 1`). |
583
606
  | `commands.suggestion.blocklist` | list of command names | `[]` | Commands that never appear as a suggestion. They still work when typed explicitly. |
584
607
  | `commands.create_pr.preview_description` | `true`, `false` | `false` | When `false`: `/create-pr` skips the title/body preview + adjust loop and uses the generated content directly. Saves agent tokens. When `true`: show title and body before creating and ask for adjustments. `/create-pr:description-only` always previews regardless of this setting. |
608
+ | `commands.create_pr.detail_level` | `min`, `med`, `max` | `min` | Verbosity tier of the PR Description body. `min` = title + 2-3 sentence what/why/impact + ticket; `med` = + grouped changes + tests note; `max` = + how-to-test + edge cases + reviewer guidance. Critical info (breaking / migration / security / rollback) is included at every tier. |
609
+ | `commands.create_pr.api_examples` | `true`, `false` | `true` | Add a grounded JSON example for API-endpoint changes; `true` includes one only from a real source (DTO/OpenAPI/fixture/probe), else a pointer, never invented; `false` = never. |
610
+ | `commands.create_pr.screenshots` | `true`, `false` | `false` | Capability-gated frontend screenshots. `true` attempts capture when browser/preview tooling is present; notes-and-skips otherwise, never blocks the PR. Before/after is best-effort. |
611
+ | `commands.create_pr.ui_paths` | glob list | `[]` | Optional globs pinning frontend detection; empty = light heuristic, fail-open. |
612
+ | `commands.create_pr.api_paths` | glob list | `[]` | Optional globs pinning API-endpoint detection; empty = light heuristic, fail-open. |
585
613
  | `verbosity.preview_artifacts` | `true`, `false` | `false` | Show generated commit messages, PR titles/bodies, branch names before acting. `false` = use generated content directly. See the token-frugality plate under `agents/roadmaps/` (Phase 2/3). |
586
614
  | `verbosity.routine_confirmations` | `true`, `false` | `false` | Confirmation prompts for routine workflow steps when there is one obvious answer ("looks good — commit?"). Iron-Law gates (`commit-policy`, `scope-control` git-ops, `non-destructive-by-default`) ALWAYS ask regardless. |
587
615
  | `verbosity.offer_council_in_delivery` | `true`, `false` | `false` | Offer "run AI Council on this?" inside delivery commands (`/feature-plan`, `/review-changes`, `/roadmap-create`). Council commands themselves are unaffected. |
@@ -39,7 +39,7 @@ schema_version: 1
39
39
  # CI guard: a release bump of `package.json` must update this value
40
40
  # in lockstep — see scripts/check_template_pin_drift.ts (road-to-
41
41
  # portable-runtime-and-update-check P3.3).
42
- agent_config_version: "8.13.0"
42
+ agent_config_version: "9.1.0"
43
43
 
44
44
  # --- Project identity ---
45
45
  project:
@@ -15,6 +15,10 @@
15
15
  * "boundary_kind": "task" | "phase-step" | "tool-call",
16
16
  * "consulted": {"skills": [...], "rules": [...], ...},
17
17
  * "applied": {"skills": [...], "rules": [...], ...},
18
+ * "loaded": {"skills": [...], "rules": [...], ...} # optional (U1a):
19
+ * what was AVAILABLE/INJECTED at the boundary — the Fired/Loaded
20
+ * denominator. Superset contract: consulted ⊆ loaded. Ids only
21
+ * (same PII-exclusion-by-construction shape as consulted).
18
22
  * "outcomes": ["blocked", "verification_failed", ...] # optional
19
23
  * "tokens_estimate": {"consulted_load": <int>} # optional
20
24
  * }
@@ -127,6 +131,7 @@ export interface EngagementEventInit {
127
131
  boundary_kind: string;
128
132
  consulted?: Record<string, string[]>;
129
133
  applied?: Record<string, string[]>;
134
+ loaded?: Record<string, string[]> | null;
130
135
  outcomes?: string[] | null;
131
136
  tokens_estimate?: Record<string, number> | null;
132
137
  schema_version?: number;
@@ -138,6 +143,7 @@ export class EngagementEvent {
138
143
  boundary_kind: string;
139
144
  consulted: Record<string, string[]>;
140
145
  applied: Record<string, string[]>;
146
+ loaded: Record<string, string[]> | null;
141
147
  outcomes: string[] | null;
142
148
  tokens_estimate: Record<string, number> | null;
143
149
  schema_version: number;
@@ -148,6 +154,7 @@ export class EngagementEvent {
148
154
  this.boundary_kind = init.boundary_kind;
149
155
  this.consulted = init.consulted ?? {};
150
156
  this.applied = init.applied ?? {};
157
+ this.loaded = init.loaded ?? null;
151
158
  this.outcomes = init.outcomes ?? null;
152
159
  this.tokens_estimate = init.tokens_estimate ?? null;
153
160
  this.schema_version = init.schema_version ?? SCHEMA_VERSION;
@@ -171,6 +178,20 @@ export class EngagementEvent {
171
178
  }
172
179
  _validate_artefact_dict('consulted', this.consulted);
173
180
  _validate_artefact_dict('applied', this.applied);
181
+ if (this.loaded !== null) {
182
+ _validate_artefact_dict('loaded', this.loaded);
183
+ for (const [kind, ids] of Object.entries(this.consulted)) {
184
+ const avail = new Set(this.loaded[kind] ?? []);
185
+ for (const art_id of ids) {
186
+ if (!avail.has(art_id)) {
187
+ throw new EngagementSchemaError(
188
+ `consulted.${kind} id '${art_id}' missing from loaded.${kind}; `
189
+ + 'superset contract: consulted \u2286 loaded',
190
+ );
191
+ }
192
+ }
193
+ }
194
+ }
174
195
  if (this.outcomes !== null) {
175
196
  _validate_outcomes(this.outcomes);
176
197
  }
@@ -206,6 +227,12 @@ export class EngagementEvent {
206
227
  consulted: _normalise_artefact_dict(this.consulted),
207
228
  applied: _normalise_artefact_dict(this.applied),
208
229
  };
230
+ if (this.loaded !== null) {
231
+ const norm = _normalise_artefact_dict(this.loaded);
232
+ if (Object.keys(norm).length > 0) {
233
+ out['loaded'] = norm;
234
+ }
235
+ }
209
236
  if (this.outcomes && this.outcomes.length > 0) {
210
237
  out['outcomes'] = [...this.outcomes];
211
238
  }
@@ -310,6 +337,9 @@ export function parse_event(line: string): EngagementEvent {
310
337
  boundary_kind: (r['boundary_kind'] as string) ?? '',
311
338
  consulted: _orEmptyDict(r['consulted']),
312
339
  applied: _orEmptyDict(r['applied']),
340
+ loaded: r['loaded'] === undefined || r['loaded'] === null
341
+ ? null
342
+ : _orEmptyDict(r['loaded']),
313
343
  outcomes: (r['outcomes'] as string[] | null | undefined) ?? null,
314
344
  tokens_estimate: (r['tokens_estimate'] as Record<string, number> | null | undefined) ?? null,
315
345
  schema_version: r['schema_version'] === undefined
@@ -121,15 +121,19 @@ export function render_markdown(aggregate: AggregateResult, opts: RenderOptions
121
121
  lines.push('');
122
122
  continue;
123
123
  }
124
- lines.push('| kind | id | consulted | applied | applied/consulted | last seen |');
125
- lines.push('|---|---|---:|---:|---:|---|');
124
+ const withLoaded = aggregate.loaded_events > 0;
125
+ lines.push(withLoaded
126
+ ? '| kind | id | loaded | consulted | applied | fired/loaded | applied/consulted | last seen |'
127
+ : '| kind | id | consulted | applied | applied/consulted | last seen |');
128
+ lines.push(withLoaded ? '|---|---|---:|---:|---:|---:|---:|---|' : '|---|---|---:|---:|---:|---|');
126
129
  for (const entry of rows) {
127
130
  const s = entry.stat;
128
131
  check_id_redaction(`buckets.${s.kind}.id`, s.artefact_id);
129
- lines.push(
130
- `| ${s.kind} | \`${s.artefact_id}\` | ${s.consulted} | ${s.applied} `
131
- + `| ${_pyFixed(s.applied_ratio, 2)} | \`${s.last_seen_ts}\` |`,
132
- );
132
+ lines.push(withLoaded
133
+ ? `| ${s.kind} | \`${s.artefact_id}\` | ${s.loaded} | ${s.consulted} | ${s.applied} `
134
+ + `| ${_pyFixed(s.fired_ratio, 2)} | ${_pyFixed(s.applied_ratio, 2)} | \`${s.last_seen_ts}\` |`
135
+ : `| ${s.kind} | \`${s.artefact_id}\` | ${s.consulted} | ${s.applied} `
136
+ + `| ${_pyFixed(s.applied_ratio, 2)} | \`${s.last_seen_ts}\` |`);
133
137
  }
134
138
  lines.push('');
135
139
  }
@@ -147,7 +151,9 @@ export function render_json(aggregate: AggregateResult, opts: RenderOptions = {}
147
151
  [BUCKET_BOTTOM]: [],
148
152
  };
149
153
  for (const entry of bucketed) {
150
- (grouped[entry.bucket] as Array<Record<string, unknown>>).push(_stat_to_dict(entry.stat));
154
+ (grouped[entry.bucket] as Array<Record<string, unknown>>).push(
155
+ _stat_to_dict(entry.stat, aggregate.loaded_events > 0),
156
+ );
151
157
  }
152
158
  if (top !== null) {
153
159
  for (const bucket of Object.keys(grouped)) {
@@ -179,9 +185,9 @@ export function render_json(aggregate: AggregateResult, opts: RenderOptions = {}
179
185
  return `${_py_json_dumps_indent2_sorted(payload)}\n`;
180
186
  }
181
187
 
182
- function _stat_to_dict(stat: ArtefactStat): Record<string, unknown> {
188
+ function _stat_to_dict(stat: ArtefactStat, withLoaded = false): Record<string, unknown> {
183
189
  check_id_redaction(`buckets.${stat.kind}.id`, stat.artefact_id);
184
- return {
190
+ const out: Record<string, unknown> = {
185
191
  kind: stat.kind,
186
192
  id: stat.artefact_id,
187
193
  consulted: stat.consulted,
@@ -189,6 +195,13 @@ function _stat_to_dict(stat: ArtefactStat): Record<string, unknown> {
189
195
  applied_ratio: new PyFloat(_pyRound(stat.applied_ratio, 4)),
190
196
  last_seen_ts: stat.last_seen_ts,
191
197
  };
198
+ // U1a: emitted only when the log carries the loaded denominator, so
199
+ // pre-U1a logs render byte-identically to the frozen parity oracle.
200
+ if (withLoaded) {
201
+ out['loaded'] = stat.loaded;
202
+ out['fired_ratio'] = new PyFloat(_pyRound(stat.fired_ratio, 4));
203
+ }
204
+ return out;
192
205
  }
193
206
 
194
207
  // ── Python-parity helpers ───────────────────────────────────────────────
@@ -63,6 +63,7 @@ interface RecordArgs {
63
63
  boundary: string;
64
64
  consulted: string[] | null;
65
65
  applied: string[] | null;
66
+ loaded: string[] | null;
66
67
  outcome: string[] | null;
67
68
  ts: string;
68
69
  payload_file: string | null;
@@ -78,6 +79,7 @@ function _build_event_from_args(args: RecordArgs): EngagementEvent {
78
79
  boundary_kind: args.boundary,
79
80
  consulted: _parse_kv_list(args.consulted ?? []),
80
81
  applied: _parse_kv_list(args.applied ?? []),
82
+ loaded: args.loaded && args.loaded.length > 0 ? _parse_kv_list(args.loaded) : null,
81
83
  outcomes: args.outcome && args.outcome.length > 0 ? [...args.outcome] : null,
82
84
  });
83
85
  }
@@ -101,6 +103,7 @@ function _build_event_from_payload(raw: string): EngagementEvent {
101
103
  boundary_kind: (d['boundary_kind'] as string) ?? '',
102
104
  consulted: _orEmpty(d['consulted']),
103
105
  applied: _orEmpty(d['applied']),
106
+ loaded: d['loaded'] === undefined || d['loaded'] === null ? null : _orEmpty(d['loaded']),
104
107
  outcomes: (d['outcomes'] as string[] | null | undefined) ?? null,
105
108
  tokens_estimate: (d['tokens_estimate'] as Record<string, number> | null | undefined) ?? null,
106
109
  });
@@ -121,6 +124,7 @@ function _parseArgs(argv: string[]): RecordArgs {
121
124
  boundary: 'task',
122
125
  consulted: null,
123
126
  applied: null,
127
+ loaded: null,
124
128
  outcome: null,
125
129
  ts: '',
126
130
  payload_file: null,
@@ -155,6 +159,7 @@ function _parseArgs(argv: string[]): RecordArgs {
155
159
  }
156
160
  a.boundary = v;
157
161
  } else if (tok === '--consulted') (a.consulted ??= []).push(next());
162
+ else if (tok === '--loaded') (a.loaded ??= []).push(next());
158
163
  else if (tok === '--applied') (a.applied ??= []).push(next());
159
164
  else if (tok === '--outcome') {
160
165
  const v = next();