@event4u/agent-config 1.13.0 → 1.15.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 (291) hide show
  1. package/.agent-src/commands/agent-handoff.md +4 -1
  2. package/.agent-src/commands/agent-status.md +3 -0
  3. package/.agent-src/commands/agents-audit.md +4 -0
  4. package/.agent-src/commands/agents-cleanup.md +6 -1
  5. package/.agent-src/commands/agents-prepare.md +3 -0
  6. package/.agent-src/commands/analyze-reference-repo.md +4 -0
  7. package/.agent-src/commands/bug-fix.md +7 -3
  8. package/.agent-src/commands/bug-investigate.md +4 -0
  9. package/.agent-src/commands/chat-history-checkpoint.md +126 -0
  10. package/.agent-src/commands/chat-history-clear.md +6 -1
  11. package/.agent-src/commands/chat-history-resume.md +7 -2
  12. package/.agent-src/commands/chat-history.md +7 -2
  13. package/.agent-src/commands/check-current-md.md +137 -0
  14. package/.agent-src/commands/commit-in-chunks.md +118 -0
  15. package/.agent-src/commands/commit.md +4 -0
  16. package/.agent-src/commands/compress.md +37 -2
  17. package/.agent-src/commands/context-create.md +4 -0
  18. package/.agent-src/commands/context-refactor.md +4 -0
  19. package/.agent-src/commands/copilot-agents-init.md +3 -0
  20. package/.agent-src/commands/copilot-agents-optimize.md +3 -0
  21. package/.agent-src/commands/create-pr-description.md +4 -0
  22. package/.agent-src/commands/create-pr.md +4 -0
  23. package/.agent-src/commands/do-and-judge.md +4 -1
  24. package/.agent-src/commands/do-in-steps.md +3 -0
  25. package/.agent-src/commands/e2e-heal.md +4 -0
  26. package/.agent-src/commands/e2e-plan.md +4 -0
  27. package/.agent-src/commands/estimate-ticket.md +4 -1
  28. package/.agent-src/commands/feature-dev.md +4 -0
  29. package/.agent-src/commands/feature-explore.md +4 -0
  30. package/.agent-src/commands/feature-plan.md +4 -0
  31. package/.agent-src/commands/feature-refactor.md +4 -0
  32. package/.agent-src/commands/feature-roadmap.md +6 -0
  33. package/.agent-src/commands/fix-ci.md +4 -0
  34. package/.agent-src/commands/fix-portability.md +5 -2
  35. package/.agent-src/commands/fix-pr-bot-comments.md +4 -0
  36. package/.agent-src/commands/fix-pr-comments.md +4 -0
  37. package/.agent-src/commands/fix-pr-developer-comments.md +4 -0
  38. package/.agent-src/commands/fix-references.md +3 -0
  39. package/.agent-src/commands/fix-seeder.md +4 -0
  40. package/.agent-src/commands/implement-ticket.md +39 -13
  41. package/.agent-src/commands/jira-ticket.md +4 -0
  42. package/.agent-src/commands/judge.md +3 -0
  43. package/.agent-src/commands/memory-add.md +5 -3
  44. package/.agent-src/commands/memory-full.md +5 -2
  45. package/.agent-src/commands/memory-promote.md +7 -6
  46. package/.agent-src/commands/mode.md +3 -0
  47. package/.agent-src/commands/module-create.md +4 -0
  48. package/.agent-src/commands/module-explore.md +4 -0
  49. package/.agent-src/commands/onboard.md +33 -0
  50. package/.agent-src/commands/optimize-agents.md +4 -0
  51. package/.agent-src/commands/optimize-augmentignore.md +12 -0
  52. package/.agent-src/commands/optimize-rtk-filters.md +3 -0
  53. package/.agent-src/commands/optimize-skills.md +4 -0
  54. package/.agent-src/commands/override-create.md +4 -0
  55. package/.agent-src/commands/override-manage.md +4 -0
  56. package/.agent-src/commands/package-reset.md +3 -0
  57. package/.agent-src/commands/package-test.md +3 -0
  58. package/.agent-src/commands/prepare-for-review.md +4 -0
  59. package/.agent-src/commands/project-analyze.md +4 -0
  60. package/.agent-src/commands/project-health.md +4 -0
  61. package/.agent-src/commands/propose-memory.md +6 -8
  62. package/.agent-src/commands/quality-fix.md +4 -0
  63. package/.agent-src/commands/refine-ticket.md +12 -7
  64. package/.agent-src/commands/review-changes.md +39 -8
  65. package/.agent-src/commands/review-routing.md +4 -0
  66. package/.agent-src/commands/roadmap-create.md +18 -0
  67. package/.agent-src/commands/roadmap-execute.md +14 -1
  68. package/.agent-src/commands/rule-compliance-audit.md +4 -0
  69. package/.agent-src/commands/set-cost-profile.md +11 -0
  70. package/.agent-src/commands/sync-agent-settings.md +12 -0
  71. package/.agent-src/commands/sync-gitignore.md +3 -0
  72. package/.agent-src/commands/tests-create.md +4 -0
  73. package/.agent-src/commands/tests-execute.md +6 -3
  74. package/.agent-src/commands/threat-model.md +4 -0
  75. package/.agent-src/commands/update-form-request-messages.md +4 -0
  76. package/.agent-src/commands/upstream-contribute.md +4 -0
  77. package/.agent-src/commands/work.md +161 -0
  78. package/.agent-src/guidelines/agent-infra/engineering-memory-data-format.md +2 -6
  79. package/.agent-src/guidelines/agent-infra/layered-settings.md +0 -1
  80. package/.agent-src/guidelines/agent-infra/memory-access.md +0 -7
  81. package/.agent-src/guidelines/agent-infra/role-contracts.md +2 -4
  82. package/.agent-src/guidelines/agent-infra/self-improvement-pipeline.md +0 -1
  83. package/.agent-src/guidelines/php/patterns/strategy.md +180 -2
  84. package/.agent-src/personas/README.md +0 -1
  85. package/.agent-src/rules/artifact-drafting-protocol.md +7 -2
  86. package/.agent-src/rules/artifact-engagement-recording.md +133 -0
  87. package/.agent-src/rules/ask-when-uncertain.md +18 -13
  88. package/.agent-src/rules/augment-portability.md +64 -37
  89. package/.agent-src/rules/autonomous-execution.md +158 -0
  90. package/.agent-src/rules/chat-history-cadence.md +109 -0
  91. package/.agent-src/rules/chat-history-ownership.md +123 -0
  92. package/.agent-src/rules/chat-history-visibility.md +96 -0
  93. package/.agent-src/rules/cli-output-handling.md +27 -4
  94. package/.agent-src/rules/command-suggestion.md +134 -0
  95. package/.agent-src/rules/commit-policy.md +109 -0
  96. package/.agent-src/rules/direct-answers.md +114 -0
  97. package/.agent-src/rules/docs-sync.md +36 -0
  98. package/.agent-src/rules/downstream-changes.md +10 -9
  99. package/.agent-src/rules/improve-before-implement.md +9 -6
  100. package/.agent-src/rules/language-and-tone.md +85 -6
  101. package/.agent-src/rules/non-destructive-by-default.md +117 -0
  102. package/.agent-src/rules/package-ci-checks.md +4 -0
  103. package/.agent-src/rules/preservation-guard.md +20 -0
  104. package/.agent-src/rules/roadmap-progress-sync.md +159 -27
  105. package/.agent-src/rules/role-mode-adherence.md +1 -1
  106. package/.agent-src/rules/scope-control.md +42 -1
  107. package/.agent-src/rules/size-enforcement.md +2 -3
  108. package/.agent-src/rules/skill-quality.md +3 -8
  109. package/.agent-src/rules/ui-audit-before-build.md +106 -0
  110. package/.agent-src/rules/user-interaction.md +107 -51
  111. package/.agent-src/scripts/update_roadmap_progress.py +73 -9
  112. package/.agent-src/skills/blade-ui/SKILL.md +47 -3
  113. package/.agent-src/skills/command-routing/SKILL.md +32 -0
  114. package/.agent-src/skills/command-writing/SKILL.md +52 -2
  115. package/.agent-src/skills/description-assist/SKILL.md +21 -0
  116. package/.agent-src/skills/estimate-ticket/SKILL.md +0 -1
  117. package/.agent-src/skills/existing-ui-audit/SKILL.md +202 -0
  118. package/.agent-src/skills/fe-design/SKILL.md +78 -61
  119. package/.agent-src/skills/file-editor/SKILL.md +9 -0
  120. package/.agent-src/skills/finishing-a-development-branch/SKILL.md +4 -0
  121. package/.agent-src/skills/flux/SKILL.md +31 -4
  122. package/.agent-src/skills/guideline-writing/SKILL.md +24 -2
  123. package/.agent-src/skills/learning-to-rule-or-skill/SKILL.md +51 -9
  124. package/.agent-src/skills/livewire/SKILL.md +49 -4
  125. package/.agent-src/skills/md-language-check/SKILL.md +103 -0
  126. package/.agent-src/skills/php-coder/SKILL.md +24 -0
  127. package/.agent-src/skills/react-shadcn-ui/SKILL.md +121 -0
  128. package/.agent-src/skills/refine-prompt/SKILL.md +220 -0
  129. package/.agent-src/skills/refine-ticket/SKILL.md +32 -28
  130. package/.agent-src/skills/roadmap-management/SKILL.md +24 -11
  131. package/.agent-src/skills/rule-writing/SKILL.md +23 -1
  132. package/.agent-src/skills/skill-writing/SKILL.md +3 -5
  133. package/.agent-src/skills/upstream-contribute/SKILL.md +3 -3
  134. package/.agent-src/skills/using-git-worktrees/SKILL.md +3 -1
  135. package/.agent-src/templates/AGENTS.md +24 -6
  136. package/.agent-src/templates/agent-settings.md +149 -0
  137. package/.agent-src/templates/roadmaps.md +11 -4
  138. package/.agent-src/templates/scripts/implement_ticket/__init__.py +63 -26
  139. package/.agent-src/templates/scripts/implement_ticket/__main__.py +8 -2
  140. package/.agent-src/templates/scripts/memory_lookup.py +1 -1
  141. package/.agent-src/templates/scripts/telemetry/__init__.py +42 -0
  142. package/.agent-src/templates/scripts/telemetry/aggregator.py +154 -0
  143. package/.agent-src/templates/scripts/telemetry/boundary.py +171 -0
  144. package/.agent-src/templates/scripts/telemetry/engagement.py +238 -0
  145. package/.agent-src/templates/scripts/telemetry/report_renderer.py +170 -0
  146. package/.agent-src/templates/scripts/telemetry/settings.py +112 -0
  147. package/.agent-src/templates/scripts/telemetry_record.py +166 -0
  148. package/.agent-src/templates/scripts/telemetry_report.py +161 -0
  149. package/.agent-src/templates/scripts/telemetry_status.py +142 -0
  150. package/.agent-src/templates/scripts/work_engine/__init__.py +58 -0
  151. package/.agent-src/templates/scripts/work_engine/__main__.py +9 -0
  152. package/.agent-src/templates/scripts/work_engine/cli.py +195 -0
  153. package/.agent-src/templates/scripts/work_engine/cli_args.py +116 -0
  154. package/.agent-src/templates/scripts/{implement_ticket → work_engine}/delivery_state.py +10 -3
  155. package/.agent-src/templates/scripts/work_engine/directives/__init__.py +33 -0
  156. package/.agent-src/templates/scripts/work_engine/directives/backend/__init__.py +98 -0
  157. package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/analyze.py +1 -1
  158. package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/implement.py +3 -3
  159. package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/memory.py +2 -2
  160. package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/plan.py +2 -2
  161. package/.agent-src/templates/scripts/work_engine/directives/backend/refine.py +396 -0
  162. package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/report.py +37 -5
  163. package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/test.py +2 -2
  164. package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/verify.py +2 -2
  165. package/.agent-src/templates/scripts/work_engine/directives/mixed/__init__.py +116 -0
  166. package/.agent-src/templates/scripts/work_engine/directives/mixed/contract.py +254 -0
  167. package/.agent-src/templates/scripts/work_engine/directives/mixed/stitch.py +229 -0
  168. package/.agent-src/templates/scripts/work_engine/directives/mixed/ui.py +231 -0
  169. package/.agent-src/templates/scripts/work_engine/directives/ui/__init__.py +113 -0
  170. package/.agent-src/templates/scripts/work_engine/directives/ui/_passthrough.py +44 -0
  171. package/.agent-src/templates/scripts/work_engine/directives/ui/apply.py +241 -0
  172. package/.agent-src/templates/scripts/work_engine/directives/ui/audit.py +414 -0
  173. package/.agent-src/templates/scripts/work_engine/directives/ui/design.py +335 -0
  174. package/.agent-src/templates/scripts/work_engine/directives/ui/polish.py +510 -0
  175. package/.agent-src/templates/scripts/work_engine/directives/ui/review.py +468 -0
  176. package/.agent-src/templates/scripts/work_engine/directives/ui_trivial/__init__.py +119 -0
  177. package/.agent-src/templates/scripts/work_engine/directives/ui_trivial/_skipped.py +37 -0
  178. package/.agent-src/templates/scripts/work_engine/directives/ui_trivial/apply.py +165 -0
  179. package/.agent-src/templates/scripts/work_engine/directives/ui_trivial/refine.py +66 -0
  180. package/.agent-src/templates/scripts/work_engine/directives/ui_trivial/report.py +62 -0
  181. package/.agent-src/templates/scripts/work_engine/directives/ui_trivial/test.py +115 -0
  182. package/.agent-src/templates/scripts/work_engine/dispatcher.py +331 -0
  183. package/.agent-src/templates/scripts/work_engine/emitters.py +43 -0
  184. package/.agent-src/templates/scripts/work_engine/errors.py +19 -0
  185. package/.agent-src/templates/scripts/work_engine/hook_bootstrap.py +76 -0
  186. package/.agent-src/templates/scripts/work_engine/hooks/__init__.py +54 -0
  187. package/.agent-src/templates/scripts/work_engine/hooks/builtin/__init__.py +32 -0
  188. package/.agent-src/templates/scripts/work_engine/hooks/builtin/_chat_history_base.py +103 -0
  189. package/.agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_append.py +44 -0
  190. package/.agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_halt_append.py +42 -0
  191. package/.agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_heartbeat.py +50 -0
  192. package/.agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_turn_check.py +49 -0
  193. package/.agent-src/templates/scripts/work_engine/hooks/builtin/directive_set_guard.py +53 -0
  194. package/.agent-src/templates/scripts/work_engine/hooks/builtin/halt_surface_audit.py +50 -0
  195. package/.agent-src/templates/scripts/work_engine/hooks/builtin/state_shape_validation.py +52 -0
  196. package/.agent-src/templates/scripts/work_engine/hooks/builtin/trace.py +84 -0
  197. package/.agent-src/templates/scripts/work_engine/hooks/context.py +66 -0
  198. package/.agent-src/templates/scripts/work_engine/hooks/events.py +44 -0
  199. package/.agent-src/templates/scripts/work_engine/hooks/exceptions.py +79 -0
  200. package/.agent-src/templates/scripts/work_engine/hooks/registry.py +60 -0
  201. package/.agent-src/templates/scripts/work_engine/hooks/runner.py +73 -0
  202. package/.agent-src/templates/scripts/work_engine/hooks/settings.py +141 -0
  203. package/.agent-src/templates/scripts/work_engine/input_builders.py +163 -0
  204. package/.agent-src/templates/scripts/work_engine/intent/__init__.py +47 -0
  205. package/.agent-src/templates/scripts/work_engine/intent/classify.py +280 -0
  206. package/.agent-src/templates/scripts/work_engine/migration/__init__.py +8 -0
  207. package/.agent-src/templates/scripts/work_engine/migration/v0_to_v1.py +231 -0
  208. package/.agent-src/templates/scripts/{implement_ticket → work_engine}/persona_policy.py +1 -1
  209. package/.agent-src/templates/scripts/work_engine/resolvers/__init__.py +22 -0
  210. package/.agent-src/templates/scripts/work_engine/resolvers/diff.py +106 -0
  211. package/.agent-src/templates/scripts/work_engine/resolvers/file.py +113 -0
  212. package/.agent-src/templates/scripts/work_engine/resolvers/prompt.py +90 -0
  213. package/.agent-src/templates/scripts/work_engine/scoring/__init__.py +14 -0
  214. package/.agent-src/templates/scripts/work_engine/scoring/confidence.py +300 -0
  215. package/.agent-src/templates/scripts/work_engine/stack/__init__.py +31 -0
  216. package/.agent-src/templates/scripts/work_engine/stack/detect.py +187 -0
  217. package/.agent-src/templates/scripts/work_engine/state.py +641 -0
  218. package/.agent-src/templates/scripts/work_engine/state_io.py +202 -0
  219. package/.claude-plugin/marketplace.json +105 -2
  220. package/AGENTS.md +38 -8
  221. package/CHANGELOG.md +609 -0
  222. package/README.md +136 -14
  223. package/config/agent-settings.template.yml +45 -0
  224. package/config/gitignore-block.txt +4 -0
  225. package/docs/MIGRATION.md +122 -0
  226. package/docs/architecture.md +111 -35
  227. package/docs/contracts/STABILITY.md +95 -0
  228. package/docs/contracts/adr-chat-history-split.md +132 -0
  229. package/docs/contracts/adr-command-suggestion.md +146 -0
  230. package/docs/contracts/adr-implement-ticket-runtime.md +122 -0
  231. package/docs/contracts/adr-product-ui-track.md +384 -0
  232. package/docs/contracts/adr-prompt-driven-execution.md +187 -0
  233. package/docs/contracts/agent-memory-contract.md +149 -0
  234. package/docs/contracts/artifact-engagement-flow.md +262 -0
  235. package/docs/contracts/command-clusters.md +126 -0
  236. package/docs/contracts/command-suggestion-flow.md +148 -0
  237. package/docs/contracts/implement-ticket-flow.md +628 -0
  238. package/docs/contracts/linear-ai-rules-inclusion.md +143 -0
  239. package/docs/contracts/linear-ai-three-layers.md +131 -0
  240. package/docs/contracts/rule-interactions.md +107 -0
  241. package/docs/contracts/rule-interactions.yml +142 -0
  242. package/docs/contracts/ui-stack-extension.md +236 -0
  243. package/docs/contracts/ui-track-flow.md +338 -0
  244. package/docs/development.md +1 -1
  245. package/docs/getting-started.md +3 -3
  246. package/docs/installation.md +124 -2
  247. package/docs/migrations/commands-1.15.0.md +112 -0
  248. package/docs/showcase.md +204 -0
  249. package/docs/ui-track-mental-model.md +121 -0
  250. package/package.json +1 -1
  251. package/scripts/agent-config +199 -0
  252. package/scripts/audit_cloud_compatibility.py +288 -0
  253. package/scripts/build_cloud_bundle.py +458 -0
  254. package/scripts/build_linear_digest.py +263 -0
  255. package/scripts/chat_history.py +796 -7
  256. package/scripts/check_compression.py +139 -0
  257. package/scripts/check_iron_law_prominence.py +143 -0
  258. package/scripts/check_md_language.py +159 -0
  259. package/scripts/check_portability.py +38 -0
  260. package/scripts/check_public_links.py +185 -0
  261. package/scripts/check_references.py +1 -0
  262. package/scripts/check_reply_consistency.py +140 -0
  263. package/scripts/command_suggester/__init__.py +51 -0
  264. package/scripts/command_suggester/cooldown.py +132 -0
  265. package/scripts/command_suggester/loader.py +70 -0
  266. package/scripts/command_suggester/match.py +180 -0
  267. package/scripts/command_suggester/rank.py +120 -0
  268. package/scripts/command_suggester/render.py +86 -0
  269. package/scripts/command_suggester/sanitize.py +113 -0
  270. package/scripts/command_suggester/settings.py +125 -0
  271. package/scripts/command_suggester/types.py +78 -0
  272. package/scripts/hooks/augment-chat-history.sh +56 -0
  273. package/scripts/install-hooks.sh +67 -0
  274. package/scripts/install.py +150 -33
  275. package/scripts/lint_marketplace.py +27 -0
  276. package/scripts/lint_no_new_atomic_commands.py +179 -0
  277. package/scripts/lint_rule_interactions.py +149 -0
  278. package/scripts/memory_lookup.py +1 -1
  279. package/scripts/migrate_command_suggestions.py +151 -0
  280. package/scripts/release.py +297 -64
  281. package/scripts/schemas/command.schema.json +41 -0
  282. package/scripts/skill_linter.py +81 -0
  283. package/scripts/sync_agent_settings.py +42 -12
  284. package/scripts/update_counts.py +10 -0
  285. package/templates/consumer-settings/augment-cli-hooks.json +54 -0
  286. package/templates/consumer-settings/claude-settings.json +55 -1
  287. package/.agent-src/rules/chat-history.md +0 -171
  288. package/.agent-src/templates/scripts/implement_ticket/cli.py +0 -171
  289. package/.agent-src/templates/scripts/implement_ticket/dispatcher.py +0 -134
  290. package/.agent-src/templates/scripts/implement_ticket/steps/__init__.py +0 -49
  291. package/.agent-src/templates/scripts/implement_ticket/steps/refine.py +0 -140
@@ -0,0 +1,149 @@
1
+ ---
2
+ stability: beta
3
+ ---
4
+
5
+ # Agent-Memory Contract (as expected by `agent-config`)
6
+
7
+ **Purpose.** Freeze the interface `agent-config` currently expects from
8
+ the sibling package `@event4u/agent-memory`, so when that package
9
+ actually ships we can diff its real surface against this document in
10
+ one place — instead of chasing drift across skills, commands, and
11
+ helpers.
12
+
13
+ **Ownership.** `agent-memory` is ours; we decide release timing. This
14
+ doc is internal, not a spec handed to an external team. The
15
+ authoritative spec-side documents live under
16
+ [`agents/roadmaps/agent-memory/`](../../agents/roadmaps/agent-memory/); this context
17
+ is the **consumer-side snapshot** — what our wired code assumes today.
18
+
19
+ Last refreshed: 2026-04-22.
20
+
21
+ ## What this doc is *not*
22
+
23
+ - Not a replacement for
24
+ [`road-to-retrieval-contract.md`](../../agents/roadmaps/agent-memory/road-to-retrieval-contract.md)
25
+ — that is the spec we hand to the agent-memory implementer.
26
+ - Not a commitment that consumer code looks exactly like this forever
27
+ — it is a point-in-time pin.
28
+ - Not an agent-facing skill. Humans read this when the package lands.
29
+
30
+ ## Expected backend states
31
+
32
+ Defined in [`memory-access.md`](../../.agent-src.uncompressed/guidelines/agent-infra/memory-access.md)
33
+ and `scripts/memory_status.py`:
34
+
35
+ | Status | Meaning | Agent-config behaviour |
36
+ |---|---|---|
37
+ | `absent` | Package not installed or CLI not on PATH | File fallback only |
38
+ | `misconfigured` | Installed but `health()` fails within 2s | Warn once / session, fall back to file |
39
+ | `present` | Installed and healthy within 2s | Route retrieval through package |
40
+
41
+ Detection must be **bounded** (≤ 2s cold probe), **cached** per
42
+ process, **non-raising** on probe failure.
43
+
44
+ ## Expected CLI surface
45
+
46
+ Probed in `scripts/memory_status.py` via `_CLI_CANDIDATES`:
47
+
48
+ - Executable on `PATH` as **`memory`** (canonical, ships in
49
+ `@event4u/agent-memory` v1.1+ as `package.json#bin.memory`),
50
+ **`agent-memory`** (planned alias), or **`agentmem`** (legacy).
51
+ - Supports `health` subcommand emitting a v1 health envelope on stdout
52
+ (`{contract_version, status, backend_version, features, latency_ms}`)
53
+ and exiting non-zero on unhealthy.
54
+ - Supports `retrieve <query> [--type T …] [--limit N] [--layer 1|2|3]
55
+ [--budget N] [--low-trust] [--repository ID]` emitting a v1
56
+ retrieval envelope on stdout (always JSON).
57
+
58
+ The retrieval invocation is **semantic, not key-based** — see the
59
+ "⚠️ Known contract drift" section below for the consumer-side
60
+ implication.
61
+
62
+ If the released package diverges from these names, we update
63
+ `_CLI_CANDIDATES` in `memory_status.py` — not the other way round.
64
+
65
+ ## Expected retrieval shape (present path)
66
+
67
+ Source of truth:
68
+ [`road-to-retrieval-contract.md`](../../agents/roadmaps/agent-memory/road-to-retrieval-contract.md).
69
+ Consumer skills call the shared abstraction, not the package directly.
70
+
71
+ **Request** (Python):
72
+
73
+ ```python
74
+ retrieve(types=[…], keys=[…] or {…}, limit: int = 20, timeout_ms: int = 2000)
75
+ ```
76
+
77
+ **Response** (v1 envelope) — mandatory fields per entry: `id`, `type`,
78
+ `source ∈ {repo, operational}`, `confidence`, `body`. Optional:
79
+ `trust`, `last_validated`, `shadowed_by`.
80
+
81
+ Envelope: `contract_version`, `status ∈ {ok, partial, error}`,
82
+ `entries`, `slices`, `errors`.
83
+
84
+ ## ⚠️ Known contract drift (consumer vs. spec)
85
+
86
+ **Status: resolved at the consumer boundary.** The CLI / JSON output of
87
+ `scripts/memory_lookup.py` already emits the v1 envelope with
88
+ `source ∈ {repo, operational}`, `confidence`, `slices`, `status`, and
89
+ `contract_version` — see `memory_lookup.py:320-345` (envelope
90
+ assembly).
91
+
92
+ What remains is **internal-only**: the private `Hit` dataclass inside
93
+ `memory_lookup.py` still uses `source ∈ {curated, intake}` and `score`.
94
+ No skill, command, or external consumer imports `Hit` directly — they
95
+ all go through the public JSON surface, which is already spec-aligned.
96
+
97
+ | Internal `Hit` field | Public envelope field | Visible to consumers? |
98
+ |---|---|---|
99
+ | `id`, `type` | `id`, `type` | yes — match |
100
+ | `source ∈ {curated, intake}` | `source ∈ {repo, operational}` | no — translated at boundary |
101
+ | `score ∈ [0,1]` | `confidence` | no — translated at boundary |
102
+ | `path` | — | no — internal scoring signal |
103
+
104
+ **Trigger to revisit:** if a second module starts importing the `Hit`
105
+ dataclass directly (e.g. `memory_lookup.py` is split into multiple
106
+ files and `Hit` becomes a public type), rename `Hit.source`/`Hit.score`
107
+ to match the envelope so the boundary translation can be deleted.
108
+ Until then, the internal naming is an implementation detail.
109
+
110
+ There is also a **calling-convention drift** between the contract's
111
+ key-based `retrieve(types, keys, limit)` and the package's
112
+ semantic-only `retrieve(query, …)`. This is tracked separately and
113
+ is the subject of an ongoing design decision (hybrid contract — keys
114
+ synthesise into a query for the package path; file-fallback stays
115
+ key-match).
116
+
117
+ ## Expected `propose()` / signal emission
118
+
119
+ Shape used by `scripts/memory_signal.py` and the `/propose-memory`
120
+ command: JSONL append-only drop-ins under
121
+ `agents/memory/intake/*.jsonl`, one signal per line. When the package
122
+ is present, the same payload is accepted by a `propose()` CLI or MCP
123
+ call. File-drop is the always-works path.
124
+
125
+ Required fields (keep in sync with `/propose-memory` command):
126
+ `ts`, `type`, `key` (path or logical id), `observation`, `source`
127
+ (`agent` or `human`), `session_id`.
128
+
129
+ ## Revisit triggers
130
+
131
+ Q29 is **parked open**, not a blocker. Revisit when **one** of these
132
+ holds:
133
+
134
+ - `@event4u/agent-memory` ships a tagged release (any v0.x)
135
+ - A consumer project explicitly asks for the `present` path
136
+ - The agent-memory repo opens an integration PR against `agent-config`
137
+ - We change the file fallback's public shape (then rewrite this doc
138
+ *before* the change lands)
139
+
140
+ ## See also
141
+
142
+ - [`road-to-memory-self-consumption.md`](../../agents/roadmaps/road-to-memory-self-consumption.md)
143
+ - [`road-to-agent-memory-integration.md`](../../agents/roadmaps/road-to-agent-memory-integration.md)
144
+ - [`agent-memory/road-to-retrieval-contract.md`](../../agents/roadmaps/agent-memory/road-to-retrieval-contract.md)
145
+ - [`agent-memory/road-to-promotion-flow.md`](../../agents/roadmaps/agent-memory/road-to-promotion-flow.md)
146
+ - [`memory-access guideline`](../../.agent-src.uncompressed/guidelines/agent-infra/memory-access.md)
147
+ - [`scripts/memory_status.py`](../../.agent-src.uncompressed/templates/scripts/memory_status.py)
148
+ - [`scripts/memory_lookup.py`](../../.agent-src.uncompressed/templates/scripts/memory_lookup.py)
149
+ - [`open-questions-2.md`](../../agents/roadmaps/archive/open-questions-2.md) — Q29
@@ -0,0 +1,262 @@
1
+ ---
2
+ stability: beta
3
+ ---
4
+
5
+ # Artifact Engagement — Flow & Recording Contract
6
+
7
+ > Cross-cutting reference for the artifact-engagement telemetry system
8
+ > shipped under
9
+ > [`road-to-artifact-engagement-telemetry.md`](../../agents/roadmaps/road-to-artifact-engagement-telemetry.md).
10
+ > Phase 1 + 2 ship the schema, CLI, and engine. Phase 3 ships the
11
+ > agent-side hooks (this document).
12
+ >
13
+ > - **Created:** 2026-04-30
14
+ > - **Status:** Phase 5 — schema, engine, recording, aggregator, renderer,
15
+ > and redaction validator are in place. Phase 6 (dogfooding) next.
16
+
17
+ This document is the stable reference for **what gets recorded, when, and
18
+ under which constraints**. The roadmap tracks phased delivery; the rule
19
+ ([`artifact-engagement-recording`](../../.agent-src.uncompressed/rules/artifact-engagement-recording.md))
20
+ tells the agent when to fire; this doc explains the contract every
21
+ recording must honour.
22
+
23
+ ## What this is
24
+
25
+ A measurement layer that tells maintainers which **skills, rules,
26
+ commands, guidelines and personas** the agent actually consults and
27
+ applies during a `/implement-ticket` or `/work` run. The output (a local
28
+ JSONL log) becomes the input to the Phase 4 aggregator + report renderer.
29
+
30
+ ## What this is *not*
31
+
32
+ - Token-spend tracking — handled separately by the cost-profile system.
33
+ - Tool-call telemetry — out of scope.
34
+ - A retirement decision-maker — Phase 4's report surfaces signal; humans
35
+ decide what to retire.
36
+ - A consumer-facing analytics product — local-only, opt-in, never
37
+ uploaded.
38
+
39
+ ## Threat model in one paragraph
40
+
41
+ Engagement data is **observation**, not delivery. A missed event is
42
+ cheap. A leaked prompt, a leaked path, or a leaked secret is not. Every
43
+ field in the schema is **id-only**: no free-text, no payloads, no paths.
44
+ The CLI rejects oversized strings on the input boundary; the agent must
45
+ not even attempt to write content.
46
+
47
+ ## When the agent records
48
+
49
+ Two granularities, one per task or one per phase-step:
50
+
51
+ ```
52
+ refine → memory → analyze → plan → implement → test → verify → report
53
+
54
+ granularity: phase-step → 1 record per arrow crossed
55
+ granularity: task → 1 record on terminal state only
56
+ ```
57
+
58
+ The setting lives at `telemetry.artifact_engagement.granularity` in
59
+ `.agent-settings.yml`. Default `task`. Both flows
60
+ ([`/implement-ticket`](../../.agent-src.uncompressed/commands/implement-ticket.md)
61
+ and [`/work`](../../.agent-src.uncompressed/commands/work.md)) use the
62
+ same eight-step contract from
63
+ [`implement-ticket-flow.md`](implement-ticket-flow.md).
64
+
65
+ ### Boundary semantics
66
+
67
+ A boundary is **closed** when:
68
+
69
+ - The dispatcher returns `SUCCESS`, `BLOCKED`, or `PARTIAL` for the
70
+ current step (phase-step granularity), or
71
+ - The full eight-step flow reaches a terminal state (task granularity).
72
+
73
+ A boundary is **never** closed by:
74
+
75
+ - An error inside the agent's tool call (the user's task is paramount;
76
+ see "failure modes" below).
77
+ - A model-side exception or timeout.
78
+ - Settings reload mid-flow — settings are read once per task and cached.
79
+
80
+ Within a single boundary, repeated `consulted` / `applied` mentions of
81
+ the same `<kind>:<id>` pair **dedupe**. Reading `php-coder` three times
82
+ records once.
83
+
84
+ ## What counts as consulted vs applied
85
+
86
+ | Term | Meaning | Examples |
87
+ |---|---|---|
88
+ | **`consulted`** | The agent **read** the artefact this boundary | Opened `SKILL.md`, scanned a rule body, looked at a guideline, checked persona contract, cited the artefact id in reasoning |
89
+ | **`applied`** | The artefact **influenced the output** this boundary | A skill's procedure produced the code; a rule's gate halted a flow; a guideline's pattern shaped the diff |
90
+
91
+ `applied` is a strict subset of `consulted`. When in doubt → record as
92
+ `consulted` only. Over-recording `applied` inflates the engagement
93
+ signal and defeats the whole point of the system.
94
+
95
+ ## Forbidden — what NEVER goes into a record
96
+
97
+ The privacy contract is enforced at **four** layers — schema (write
98
+ gate), aggregator (read gate via `parse_event`), renderer (export gate),
99
+ and CLI (surface gate). Each layer rejects the same set of shapes;
100
+ defense in depth means a leak has to bypass all four to escape:
101
+
102
+ - File paths — any string containing `/`, `\`, or a control character.
103
+ - File extensions — trailing `.md`, `.py`, `.json`, `.yaml`, `.yml`,
104
+ `.php`, `.ts`, `.js`, etc. Detected by
105
+ `re.compile(r"\.[a-z0-9]{1,10}$", re.IGNORECASE)` in
106
+ `telemetry.engagement.check_id_redaction`.
107
+ - Source code, prompts, ticket bodies, AC text, comments.
108
+ - Branch names, commit shas, PR numbers, URLs.
109
+ - Secrets, env vars, credentials, customer data.
110
+ - Free-text strings longer than 200 chars.
111
+ - Leading or trailing whitespace, tabs, newlines.
112
+ - Empty strings.
113
+
114
+ The id namespaces are stable and bounded:
115
+
116
+ | Kind | Source | Example |
117
+ |---|---|---|
118
+ | `skills` | `.agent-src/skills/<id>/SKILL.md` | `php-coder`, `eloquent` |
119
+ | `rules` | `.agent-src/rules/<id>.md` | `scope-control`, `language-and-tone` |
120
+ | `commands` | `.agent-src/commands/<id>.md` | `commit`, `create-pr` |
121
+ | `guidelines` | `.agent-src/guidelines/<path>/<id>.md` | `agent-interaction-and-decision-quality` |
122
+ | `personas` | `.agent-src/personas/<id>.md` | `qa`, `senior-engineer` |
123
+
124
+ `task_id` is the ticket key (`PROJ-123`) for `/implement-ticket` or a
125
+ short opaque slug derived from the prompt for `/work`. Branch names,
126
+ file paths, and free-text titles are forbidden in `task_id` — see the
127
+ schema's `EngagementSchemaError` cases.
128
+
129
+ ### The four enforcement layers
130
+
131
+ 1. **Schema (write gate)** — `EngagementEvent.validate()` in
132
+ `telemetry/engagement.py` runs `check_id_redaction` over `task_id`
133
+ and every `consulted` / `applied` artefact id. The CLI exits `1`
134
+ when this fires; nothing reaches the JSONL.
135
+ 2. **Aggregator (read gate)** — `aggregator._iter_events` calls
136
+ `parse_event`, which re-runs the same validator. A pre-validator
137
+ line (e.g. an archived snapshot from before the validator landed)
138
+ is **skipped** and counted in `result.skipped_lines`. The renderer
139
+ never sees it.
140
+ 3. **Renderer (export gate)** — `_stat_to_dict` (JSON) and the
141
+ markdown row builder both call `check_id_redaction` again before
142
+ emitting any id. If a caller bypasses `parse_event` and hand-builds
143
+ an `AggregateResult`, the renderer raises `EngagementSchemaError`
144
+ instead of producing the row.
145
+ 4. **CLI (surface gate)** — `telemetry_report.main` catches
146
+ `EngagementSchemaError` from the renderer and exits `2` with a
147
+ `redaction validator refused report` message. A bad row is never
148
+ written to stdout, never piped to a teammate.
149
+
150
+ A leak would have to defeat all four layers — write the JSONL outside
151
+ the CLI, parse it outside `parse_event`, render it outside the
152
+ project's renderer, and ship it to a teammate without the CLI in the
153
+ loop. The contract treats that as out of scope.
154
+
155
+ ## How the agent records
156
+
157
+ ```bash
158
+ ./agent-config telemetry:record \
159
+ --task-id "$TASK_ID" \
160
+ --boundary task \
161
+ --consulted skills:php-coder \
162
+ --consulted rules:scope-control \
163
+ --applied skills:php-coder
164
+ ```
165
+
166
+ Exit codes (the agent must read these):
167
+
168
+ | Exit | Meaning | Action |
169
+ |---|---|---|
170
+ | `0` | Recorded, or telemetry disabled (silent no-op) | Continue |
171
+ | `1` | Schema validation failed | Log internally, **continue** the user's task — do not halt |
172
+ | `2` | IO failure (lock contention, disk full) | Same — observation, not delivery |
173
+
174
+ Schema-rejection messages go to stderr; the agent reads them once and
175
+ moves on. The user's task always takes priority.
176
+
177
+ ## Failure modes — DO NOT block the user's task
178
+
179
+ - Telemetry is **observation**, not a delivery requirement.
180
+ - A missing event is cheap; a halted task because telemetry can't write
181
+ is a critical failure mode that defeats the whole opt-in property.
182
+ - The only error the agent surfaces to the user: when the user asked
183
+ for telemetry (`telemetry:status` confirms enabled) but no event
184
+ reached the log over a full task — that is a real bug.
185
+
186
+ ## Cost floor — what "default-off" means
187
+
188
+ When `telemetry.artifact_engagement.enabled: false` (or section absent):
189
+
190
+ - The rule is `auto` and the description does not match a typical
191
+ conversation; the rule never loads. Cost floor: 0 tokens.
192
+ - The CLI exits `0` with no output and no file IO.
193
+ - The engine (`work_engine.dispatcher`, `work_engine.cli`) does not
194
+ import any `telemetry.*` module — locked by
195
+ [`tests/telemetry/test_cost_floor.py`](../../tests/telemetry/test_cost_floor.py).
196
+ - On cloud surfaces (Claude.ai Web, Skills API), the rule's
197
+ `cloud_safe: noop` marker keeps the rule inert regardless of settings.
198
+
199
+ ## Where the JSONL lives
200
+
201
+ Default path: `.agent-engagement.jsonl` in the consumer repo root.
202
+ Configurable via `telemetry.artifact_engagement.output.path`. The path
203
+ is **always** added to the consumer's `.gitignore` block by the
204
+ installer (Phase 1 wiring). Verify locally:
205
+
206
+ ```
207
+ $ grep agent-engagement .gitignore
208
+ .agent-engagement.jsonl
209
+ ```
210
+
211
+ ## How to audit a JSONL by hand
212
+
213
+ The fastest path is the project's own validator — it enforces every
214
+ rule listed above:
215
+
216
+ ```bash
217
+ # Validate every line against the schema + redaction floor
218
+ python3 -c '
219
+ import pathlib, sys
220
+ sys.path.insert(0, ".agent-src.uncompressed/templates/scripts")
221
+ from telemetry.engagement import EngagementSchemaError, parse_event
222
+ log = pathlib.Path(".agent-engagement.jsonl")
223
+ ok = bad = 0
224
+ for i, line in enumerate(log.read_text().splitlines(), 1):
225
+ if not line.strip():
226
+ continue
227
+ try:
228
+ parse_event(line + "\n")
229
+ ok += 1
230
+ except EngagementSchemaError as e:
231
+ bad += 1
232
+ print(f"line {i}: {e}", file=sys.stderr)
233
+ print(f"{ok} valid, {bad} rejected")
234
+ '
235
+
236
+ # A bad-line spot-check that does not depend on the validator
237
+ python3 -c '
238
+ import json, pathlib, re
239
+ forbidden = re.compile(r"[/\\\\]|\.[a-z0-9]{1,10}$", re.IGNORECASE)
240
+ for line in pathlib.Path(".agent-engagement.jsonl").read_text().splitlines():
241
+ if not line.strip():
242
+ continue
243
+ obj = json.loads(line)
244
+ for kind in ("consulted", "applied"):
245
+ for ids in obj.get(kind, {}).values():
246
+ for v in ids:
247
+ if forbidden.search(v) or len(v) > 200:
248
+ print("LEAK:", v)
249
+ '
250
+ ```
251
+
252
+ Either recipe is safe to run on a co-worker's archived JSONL — neither
253
+ writes anything, both surface the same shapes the four enforcement
254
+ layers reject.
255
+
256
+ ## See also
257
+
258
+ - [`road-to-artifact-engagement-telemetry`](../../agents/roadmaps/road-to-artifact-engagement-telemetry.md) — phased delivery
259
+ - [`artifact-engagement-recording`](../../.agent-src.uncompressed/rules/artifact-engagement-recording.md) — agent-side trigger
260
+ - [`implement-ticket-flow`](implement-ticket-flow.md) — the eight-step contract this rule observes
261
+ - [`scripts/telemetry/`](../../.agent-src.uncompressed/templates/scripts/telemetry/) — schema, boundary session, settings reader
262
+ - [`tests/telemetry/`](../../tests/telemetry/) — contract enforcement (104 cases through Phase 5: schema, settings, aggregator, renderer, CLI, cost-floor, redaction)
@@ -0,0 +1,126 @@
1
+ ---
2
+ stability: beta
3
+ ---
4
+
5
+ # Command-cluster contract
6
+
7
+ > **Status:** beta — locked for `1.15.0` Phase 1 (top-3 clusters).
8
+ > Phase 2 (remaining 12 clusters) waits one deprecation cycle.
9
+ > Source roadmap: [`agents/roadmaps/road-to-governance-cleanup.md`](../../agents/roadmaps/road-to-governance-cleanup.md)
10
+ > § F2.
11
+
12
+ The agent-config command surface collapses related atomic commands
13
+ into **verb clusters**. A cluster is a single top-level command
14
+ (e.g. `/fix`) that dispatches to sub-commands (e.g. `/fix ci`,
15
+ `/fix pr`). Old atomic commands stay one release as deprecation
16
+ shims, then disappear.
17
+
18
+ This file is the **locked source of truth** for which clusters
19
+ exist and which sub-commands belong to each. The atomic-command
20
+ linter (`scripts/lint_no_new_atomic_commands.py`) reads this file;
21
+ new atomic commands without a `cluster:` field pointing to an
22
+ entry below fail CI.
23
+
24
+ ## Phase 1 clusters (locked, ship in 1.15.0)
25
+
26
+ | Cluster | Sub-commands | Replaces |
27
+ |---|---|---|
28
+ | `fix` | `ci` · `pr` · `pr-bots` · `pr-developers` · `portability` · `refs` · `seeder` | `fix-ci` · `fix-pr-comments` · `fix-pr-bot-comments` · `fix-pr-developer-comments` · `fix-portability` · `fix-references` · `fix-seeder` |
29
+ | `optimize` | `agents` · `augmentignore` · `rtk` · `skills` | `optimize-agents` · `optimize-augmentignore` · `optimize-rtk-filters` · `optimize-skills` |
30
+ | `feature` | `explore` · `plan` · `refactor` · `roadmap` | `feature-explore` · `feature-plan` · `feature-refactor` · `feature-roadmap` |
31
+
32
+ **Net Phase 1:** 15 atomic commands → 3 cluster commands.
33
+
34
+ ## Phase 2 clusters (deferred to next minor release)
35
+
36
+ Listed in `road-to-governance-cleanup.md` § Finding 2. Not yet locked
37
+ into the linter; new atomic commands matching these prefixes still
38
+ fail CI without a `cluster:` field once a Phase 2 entry is added
39
+ here.
40
+
41
+ - `chat-history` (`show` · `resume` · `clear` · `checkpoint`)
42
+ - `agents` (`audit` · `cleanup` · `prepare`)
43
+ - `memory` (`add` · `load` · `promote` · `propose`)
44
+ - `roadmap` (`create` · `execute`)
45
+ - `module` (`create` · `explore`)
46
+ - `tests` (`create` · `execute`)
47
+ - `context` (`create` · `refactor`)
48
+ - `override` (`create` · `manage`)
49
+ - `copilot-agents` (`init` · `optimize`)
50
+ - `commit` (flag: `--in-chunks`)
51
+ - `judge` (`solo` · `steps` · `on-diff`) + standalone `/review`
52
+ - `create-pr` (flag: `--description-only`)
53
+
54
+ ## Frontmatter contract
55
+
56
+ A new command file under `.agent-src.uncompressed/commands/` MUST
57
+ declare `cluster:` in its frontmatter, pointing to one of the locked
58
+ clusters above:
59
+
60
+ ```yaml
61
+ ---
62
+ name: fix-ci # legacy slug retained for the shim
63
+ cluster: fix # required: locked cluster name
64
+ sub: ci # required: sub-command identifier (kebab-case)
65
+ description: Fetch CI errors from GitHub Actions and fix them
66
+ ---
67
+ ```
68
+
69
+ The linter only flags **newly-added** files under `commands/`
70
+ (git status `A`). Pre-existing commands without `cluster:` are
71
+ grandfathered indefinitely; modifying them does NOT require adding
72
+ the field. The goal is to stop the atomic surface from growing,
73
+ not to retro-fit every legacy command into a Phase 1 cluster.
74
+
75
+ ## Deprecation shim contract
76
+
77
+ A shim is a one-file stub that:
78
+
79
+ 1. Keeps the old command slug in `.agent-src.uncompressed/commands/`.
80
+ 2. Declares `superseded_by:` in frontmatter pointing to the new
81
+ cluster command (e.g. `superseded_by: fix ci`).
82
+ 3. Declares `deprecated_in:` with the release version (e.g.
83
+ `deprecated_in: 1.15.0`).
84
+ 4. Body contains exactly one warning line in the format:
85
+ ```
86
+ ⚠️ /<old-name> is deprecated; use /<cluster> <sub> instead.
87
+ ```
88
+ 5. Otherwise forwards verbatim to the cluster command (no logic).
89
+
90
+ `scripts/skill_linter.py` enforces the warning-line shape on any
91
+ file with `superseded_by:` set.
92
+
93
+ ## Removal cycle
94
+
95
+ | State | Release |
96
+ |---|---|
97
+ | Cluster command shipped, shim active | `1.15.0` |
98
+ | Shim emits warning, both work | `1.15.x` (one minor cycle) |
99
+ | Shim removed, only cluster works | `1.16.0` |
100
+
101
+ No permanent aliases. Consumers who pin a 1.15 minor get a full
102
+ release window of warnings; the 1.16 release notes call out the
103
+ removal explicitly.
104
+
105
+ ## Linter behavior
106
+
107
+ `scripts/lint_no_new_atomic_commands.py`:
108
+
109
+ - Reads the locked cluster names from this file (parsed from the
110
+ Phase 1 table above).
111
+ - Finds every command file **added** since `--baseline`
112
+ (default: `main`) — modifications to existing files are ignored.
113
+ - For each new file, requires `cluster:` to be set to one of the
114
+ locked names — OR `superseded_by:` (the file is a shim).
115
+ - Exits non-zero on the first violation; lists every violator.
116
+
117
+ `--all` mode (manual audit only, not in CI) lints every command
118
+ file and surfaces grandfathered ones — useful when planning a
119
+ Phase 2 cluster expansion.
120
+
121
+ ## See also
122
+
123
+ - [`agents/roadmaps/road-to-governance-cleanup.md`](../../agents/roadmaps/road-to-governance-cleanup.md) — F2 phased-collapse decision.
124
+ - [`agents/roadmaps/road-to-post-pr29-optimize.md`](../../agents/roadmaps/road-to-post-pr29-optimize.md) — P0.8 anchors this contract in 1.15.0.
125
+ - [`docs/migrations/commands-1.15.0.md`](../migrations/commands-1.15.0.md) — user-facing migration notes.
126
+ - [`docs/contracts/STABILITY.md`](STABILITY.md) — `beta` level rules apply.
@@ -0,0 +1,148 @@
1
+ ---
2
+ stability: beta
3
+ ---
4
+
5
+ # Command Suggestion — Flow & Scoring Contract
6
+
7
+ > Cross-cutting reference for the suggestion layer shipped under
8
+ > [`road-to-context-aware-command-suggestion.md`](../../agents/roadmaps/road-to-context-aware-command-suggestion.md).
9
+ > The runtime rule is [`command-suggestion`](../../.agent-src.uncompressed/rules/command-suggestion.md);
10
+ > the architectural decision lives in [`adr-command-suggestion.md`](adr-command-suggestion.md).
11
+ >
12
+ > - **Created:** 2026-04-30
13
+ > - **Status:** Phases 1–7 shipped — engine, rule, settings, sanitiser,
14
+ > GT-CS goldens (9/9 passing) all live.
15
+
16
+ This document is the stable reference for **how a user prompt becomes a
17
+ numbered-options block** (or stays silent). The roadmap tracks phased
18
+ delivery; this doc explains the contract every suggestion must honour.
19
+
20
+ ## Flow at a glance
21
+
22
+ ```
23
+ user turn
24
+
25
+ ├── starts with "/cmd" ──────────────► slash-commands handles it. STOP.
26
+
27
+ ├── senior-rule active ► STOP. (clarification owed,
28
+ │ (ask-when-uncertain, scope gate, role-mode contract, engine
29
+ │ role-mode, engine halt) halt — suggestion stays silent)
30
+
31
+
32
+ sanitize_message + sanitize_context
33
+ (strip fenced + inline code, strip prior suggestion-block echoes)
34
+
35
+
36
+ match() → raw scored matches per eligible command
37
+
38
+
39
+ rank() → apply floor, drop blocklisted, anti-noise heuristics,
40
+ cap at max_options, stable tie-break
41
+
42
+
43
+ apply_cooldown() → drop (command, evidence) pairs shown in window
44
+
45
+
46
+ render() → numbered-options block + Recommendation line
47
+
48
+
49
+ agent emits the block as the first and ONLY thing this turn
50
+ ```
51
+
52
+ ## Scoring breakdown
53
+
54
+ Per match, `match.py` computes:
55
+
56
+ | Component | Weight | Source |
57
+ |---|---|---|
58
+ | `trigger_description` substring hit | base 0.6 | command frontmatter |
59
+ | `trigger_context` substring hit | +0.1 (when both hit, `matched_trigger="both"`) | command frontmatter |
60
+ | Token overlap (Jaccard, message ∪ ctx) | up to +0.05 | runtime |
61
+ | Structural bonus (ticket key, file path) | +0.05, sets `has_structural_bonus=True` | runtime |
62
+
63
+ Phrase length matters — longer matched evidence wins ties. The score is
64
+ clamped to `[0.0, 1.0]`. `rank.py` then enforces the floor and the
65
+ heuristics in
66
+ [`adr-command-suggestion.md`](adr-command-suggestion.md#anti-noise-heuristics).
67
+
68
+ ## What gets recorded as evidence
69
+
70
+ `Match.evidence` is the **literal substring** that triggered the match
71
+ — `"ABC-123"` for a structural bonus, `"commit my changes"` for a
72
+ description hit. The cooldown key is `(command_name, evidence)`, so two
73
+ distinct triggers for the same command (a ticket key vs. a phrase)
74
+ track separately.
75
+
76
+ ## Opt-outs — three paths, picked by scope
77
+
78
+ | Scope | Key | Effect |
79
+ |---|---|---|
80
+ | Whole project | `commands.suggestion.enabled: false` | Layer fully silent; explicit slashes still work |
81
+ | Specific command | `commands.suggestion.blocklist: [cmd1, cmd2]` | Those commands never appear; still callable |
82
+ | Specific conversation | User types `/command-suggestion-off` | Disabled until user types `/command-suggestion-on` or chat ends |
83
+
84
+ Per-command frontmatter overrides the global floor and cooldown:
85
+
86
+ ```yaml
87
+ suggestion:
88
+ eligible: true
89
+ trigger_description: "..."
90
+ trigger_context: "..."
91
+ confidence_floor: 0.7 # stricter than global default
92
+ cooldown: 30m # longer than global default
93
+ ```
94
+
95
+ ## Subordination — when to stay silent
96
+
97
+ The rule lists four senior gates that outrank suggestion. The agent
98
+ self-checks before emitting:
99
+
100
+ 1. **`scope-control`** — never resurface a git-op the user just declined.
101
+ 2. **`ask-when-uncertain`** — clarification owed → suggestion suppressed.
102
+ 3. **`verify-before-complete`** — evidence-gate verification active → silent.
103
+ 4. **Active role-mode contract or engine halt** (`/implement-ticket`
104
+ step waiting on user, `/work` mid-flow, etc.) — active flow has the floor.
105
+
106
+ On any conflict → zero output. The user's prompt processes as it would
107
+ without the rule active.
108
+
109
+ ## Anti-noise heuristics — when not to fire
110
+
111
+ `rank.py` returns `[]` when:
112
+
113
+ - Top score is below `confidence_floor` (default `0.6`).
114
+ - Single match within `floor + 0.1` and no structural bonus.
115
+ - Short prompt (< 6 words) matches > 2 commands without a structural bonus.
116
+ - Prompt is a pure continuation phrase (`ok`, `weiter`, `continue`, …).
117
+
118
+ Structural bonuses (ticket key, file path) override every suppressor.
119
+
120
+ ## Hardening tests — what we lock down
121
+
122
+ `tests/test_command_suggester.py` covers 84 cases (matcher, rank,
123
+ cooldown, sanitiser, render, settings, directive). The 9 GT-CS goldens
124
+ (`tests/test_command_suggester_goldens.py`) lock end-to-end shape.
125
+ Together they enforce:
126
+
127
+ - **No execution without user pick** — engine has no execute path.
128
+ - **No echo-trigger** — `sanitize.py` strips the previous block's shape.
129
+ - **No code-block triggers** — `/commit` inside ``` ``` ``` ``` stays inert.
130
+ - **No conversation hijack** — `enabled: false` and senior gates → silent.
131
+ - **No multi-question stack** — only a numbered-options block, no extra ask.
132
+ - **As-is option always last** — render contract test plus rule self-check.
133
+
134
+ ## Cloud bundles
135
+
136
+ On Claude.ai Web / Skills API, the suggester package is **not** part
137
+ of the standard bundle (T2 ZIPs ship rules + skills, not Python
138
+ helpers). Treat `commands.suggestion.enabled` as `false` — degrade
139
+ silently, never crash the turn. Local agents (Augment, Claude Code,
140
+ Cursor, Cline, Windsurf) get the engine via `scripts/`.
141
+
142
+ ## See also
143
+
144
+ - [`command-suggestion`](../../.agent-src.uncompressed/rules/command-suggestion.md) — runtime rule
145
+ - [`adr-command-suggestion.md`](adr-command-suggestion.md) — architectural decision
146
+ - [`command-suggestion-eligibility.md`](command-suggestion-eligibility.md) — locked eligibility table
147
+ - [`road-to-context-aware-command-suggestion.md`](../../agents/roadmaps/road-to-context-aware-command-suggestion.md) — phased delivery
148
+ - [`agent-settings`](../../.agent-src.uncompressed/templates/agent-settings.md) — `commands.suggestion.*` reference