@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.
- package/.agent-src/commands/agent-handoff.md +4 -1
- package/.agent-src/commands/agent-status.md +3 -0
- package/.agent-src/commands/agents-audit.md +4 -0
- package/.agent-src/commands/agents-cleanup.md +6 -1
- package/.agent-src/commands/agents-prepare.md +3 -0
- package/.agent-src/commands/analyze-reference-repo.md +4 -0
- package/.agent-src/commands/bug-fix.md +7 -3
- package/.agent-src/commands/bug-investigate.md +4 -0
- package/.agent-src/commands/chat-history-checkpoint.md +126 -0
- package/.agent-src/commands/chat-history-clear.md +6 -1
- package/.agent-src/commands/chat-history-resume.md +7 -2
- package/.agent-src/commands/chat-history.md +7 -2
- package/.agent-src/commands/check-current-md.md +137 -0
- package/.agent-src/commands/commit-in-chunks.md +118 -0
- package/.agent-src/commands/commit.md +4 -0
- package/.agent-src/commands/compress.md +37 -2
- package/.agent-src/commands/context-create.md +4 -0
- package/.agent-src/commands/context-refactor.md +4 -0
- package/.agent-src/commands/copilot-agents-init.md +3 -0
- package/.agent-src/commands/copilot-agents-optimize.md +3 -0
- package/.agent-src/commands/create-pr-description.md +4 -0
- package/.agent-src/commands/create-pr.md +4 -0
- package/.agent-src/commands/do-and-judge.md +4 -1
- package/.agent-src/commands/do-in-steps.md +3 -0
- package/.agent-src/commands/e2e-heal.md +4 -0
- package/.agent-src/commands/e2e-plan.md +4 -0
- package/.agent-src/commands/estimate-ticket.md +4 -1
- package/.agent-src/commands/feature-dev.md +4 -0
- package/.agent-src/commands/feature-explore.md +4 -0
- package/.agent-src/commands/feature-plan.md +4 -0
- package/.agent-src/commands/feature-refactor.md +4 -0
- package/.agent-src/commands/feature-roadmap.md +6 -0
- package/.agent-src/commands/fix-ci.md +4 -0
- package/.agent-src/commands/fix-portability.md +5 -2
- package/.agent-src/commands/fix-pr-bot-comments.md +4 -0
- package/.agent-src/commands/fix-pr-comments.md +4 -0
- package/.agent-src/commands/fix-pr-developer-comments.md +4 -0
- package/.agent-src/commands/fix-references.md +3 -0
- package/.agent-src/commands/fix-seeder.md +4 -0
- package/.agent-src/commands/implement-ticket.md +39 -13
- package/.agent-src/commands/jira-ticket.md +4 -0
- package/.agent-src/commands/judge.md +3 -0
- package/.agent-src/commands/memory-add.md +5 -3
- package/.agent-src/commands/memory-full.md +5 -2
- package/.agent-src/commands/memory-promote.md +7 -6
- package/.agent-src/commands/mode.md +3 -0
- package/.agent-src/commands/module-create.md +4 -0
- package/.agent-src/commands/module-explore.md +4 -0
- package/.agent-src/commands/onboard.md +33 -0
- package/.agent-src/commands/optimize-agents.md +4 -0
- package/.agent-src/commands/optimize-augmentignore.md +12 -0
- package/.agent-src/commands/optimize-rtk-filters.md +3 -0
- package/.agent-src/commands/optimize-skills.md +4 -0
- package/.agent-src/commands/override-create.md +4 -0
- package/.agent-src/commands/override-manage.md +4 -0
- package/.agent-src/commands/package-reset.md +3 -0
- package/.agent-src/commands/package-test.md +3 -0
- package/.agent-src/commands/prepare-for-review.md +4 -0
- package/.agent-src/commands/project-analyze.md +4 -0
- package/.agent-src/commands/project-health.md +4 -0
- package/.agent-src/commands/propose-memory.md +6 -8
- package/.agent-src/commands/quality-fix.md +4 -0
- package/.agent-src/commands/refine-ticket.md +12 -7
- package/.agent-src/commands/review-changes.md +39 -8
- package/.agent-src/commands/review-routing.md +4 -0
- package/.agent-src/commands/roadmap-create.md +18 -0
- package/.agent-src/commands/roadmap-execute.md +14 -1
- package/.agent-src/commands/rule-compliance-audit.md +4 -0
- package/.agent-src/commands/set-cost-profile.md +11 -0
- package/.agent-src/commands/sync-agent-settings.md +12 -0
- package/.agent-src/commands/sync-gitignore.md +3 -0
- package/.agent-src/commands/tests-create.md +4 -0
- package/.agent-src/commands/tests-execute.md +6 -3
- package/.agent-src/commands/threat-model.md +4 -0
- package/.agent-src/commands/update-form-request-messages.md +4 -0
- package/.agent-src/commands/upstream-contribute.md +4 -0
- package/.agent-src/commands/work.md +161 -0
- package/.agent-src/guidelines/agent-infra/engineering-memory-data-format.md +2 -6
- package/.agent-src/guidelines/agent-infra/layered-settings.md +0 -1
- package/.agent-src/guidelines/agent-infra/memory-access.md +0 -7
- package/.agent-src/guidelines/agent-infra/role-contracts.md +2 -4
- package/.agent-src/guidelines/agent-infra/self-improvement-pipeline.md +0 -1
- package/.agent-src/guidelines/php/patterns/strategy.md +180 -2
- package/.agent-src/personas/README.md +0 -1
- package/.agent-src/rules/artifact-drafting-protocol.md +7 -2
- package/.agent-src/rules/artifact-engagement-recording.md +133 -0
- package/.agent-src/rules/ask-when-uncertain.md +18 -13
- package/.agent-src/rules/augment-portability.md +64 -37
- package/.agent-src/rules/autonomous-execution.md +158 -0
- package/.agent-src/rules/chat-history-cadence.md +109 -0
- package/.agent-src/rules/chat-history-ownership.md +123 -0
- package/.agent-src/rules/chat-history-visibility.md +96 -0
- package/.agent-src/rules/cli-output-handling.md +27 -4
- package/.agent-src/rules/command-suggestion.md +134 -0
- package/.agent-src/rules/commit-policy.md +109 -0
- package/.agent-src/rules/direct-answers.md +114 -0
- package/.agent-src/rules/docs-sync.md +36 -0
- package/.agent-src/rules/downstream-changes.md +10 -9
- package/.agent-src/rules/improve-before-implement.md +9 -6
- package/.agent-src/rules/language-and-tone.md +85 -6
- package/.agent-src/rules/non-destructive-by-default.md +117 -0
- package/.agent-src/rules/package-ci-checks.md +4 -0
- package/.agent-src/rules/preservation-guard.md +20 -0
- package/.agent-src/rules/roadmap-progress-sync.md +159 -27
- package/.agent-src/rules/role-mode-adherence.md +1 -1
- package/.agent-src/rules/scope-control.md +42 -1
- package/.agent-src/rules/size-enforcement.md +2 -3
- package/.agent-src/rules/skill-quality.md +3 -8
- package/.agent-src/rules/ui-audit-before-build.md +106 -0
- package/.agent-src/rules/user-interaction.md +107 -51
- package/.agent-src/scripts/update_roadmap_progress.py +73 -9
- package/.agent-src/skills/blade-ui/SKILL.md +47 -3
- package/.agent-src/skills/command-routing/SKILL.md +32 -0
- package/.agent-src/skills/command-writing/SKILL.md +52 -2
- package/.agent-src/skills/description-assist/SKILL.md +21 -0
- package/.agent-src/skills/estimate-ticket/SKILL.md +0 -1
- package/.agent-src/skills/existing-ui-audit/SKILL.md +202 -0
- package/.agent-src/skills/fe-design/SKILL.md +78 -61
- package/.agent-src/skills/file-editor/SKILL.md +9 -0
- package/.agent-src/skills/finishing-a-development-branch/SKILL.md +4 -0
- package/.agent-src/skills/flux/SKILL.md +31 -4
- package/.agent-src/skills/guideline-writing/SKILL.md +24 -2
- package/.agent-src/skills/learning-to-rule-or-skill/SKILL.md +51 -9
- package/.agent-src/skills/livewire/SKILL.md +49 -4
- package/.agent-src/skills/md-language-check/SKILL.md +103 -0
- package/.agent-src/skills/php-coder/SKILL.md +24 -0
- package/.agent-src/skills/react-shadcn-ui/SKILL.md +121 -0
- package/.agent-src/skills/refine-prompt/SKILL.md +220 -0
- package/.agent-src/skills/refine-ticket/SKILL.md +32 -28
- package/.agent-src/skills/roadmap-management/SKILL.md +24 -11
- package/.agent-src/skills/rule-writing/SKILL.md +23 -1
- package/.agent-src/skills/skill-writing/SKILL.md +3 -5
- package/.agent-src/skills/upstream-contribute/SKILL.md +3 -3
- package/.agent-src/skills/using-git-worktrees/SKILL.md +3 -1
- package/.agent-src/templates/AGENTS.md +24 -6
- package/.agent-src/templates/agent-settings.md +149 -0
- package/.agent-src/templates/roadmaps.md +11 -4
- package/.agent-src/templates/scripts/implement_ticket/__init__.py +63 -26
- package/.agent-src/templates/scripts/implement_ticket/__main__.py +8 -2
- package/.agent-src/templates/scripts/memory_lookup.py +1 -1
- package/.agent-src/templates/scripts/telemetry/__init__.py +42 -0
- package/.agent-src/templates/scripts/telemetry/aggregator.py +154 -0
- package/.agent-src/templates/scripts/telemetry/boundary.py +171 -0
- package/.agent-src/templates/scripts/telemetry/engagement.py +238 -0
- package/.agent-src/templates/scripts/telemetry/report_renderer.py +170 -0
- package/.agent-src/templates/scripts/telemetry/settings.py +112 -0
- package/.agent-src/templates/scripts/telemetry_record.py +166 -0
- package/.agent-src/templates/scripts/telemetry_report.py +161 -0
- package/.agent-src/templates/scripts/telemetry_status.py +142 -0
- package/.agent-src/templates/scripts/work_engine/__init__.py +58 -0
- package/.agent-src/templates/scripts/work_engine/__main__.py +9 -0
- package/.agent-src/templates/scripts/work_engine/cli.py +195 -0
- package/.agent-src/templates/scripts/work_engine/cli_args.py +116 -0
- package/.agent-src/templates/scripts/{implement_ticket → work_engine}/delivery_state.py +10 -3
- package/.agent-src/templates/scripts/work_engine/directives/__init__.py +33 -0
- package/.agent-src/templates/scripts/work_engine/directives/backend/__init__.py +98 -0
- package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/analyze.py +1 -1
- package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/implement.py +3 -3
- package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/memory.py +2 -2
- package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/plan.py +2 -2
- package/.agent-src/templates/scripts/work_engine/directives/backend/refine.py +396 -0
- package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/report.py +37 -5
- package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/test.py +2 -2
- package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/verify.py +2 -2
- package/.agent-src/templates/scripts/work_engine/directives/mixed/__init__.py +116 -0
- package/.agent-src/templates/scripts/work_engine/directives/mixed/contract.py +254 -0
- package/.agent-src/templates/scripts/work_engine/directives/mixed/stitch.py +229 -0
- package/.agent-src/templates/scripts/work_engine/directives/mixed/ui.py +231 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui/__init__.py +113 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui/_passthrough.py +44 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui/apply.py +241 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui/audit.py +414 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui/design.py +335 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui/polish.py +510 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui/review.py +468 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui_trivial/__init__.py +119 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui_trivial/_skipped.py +37 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui_trivial/apply.py +165 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui_trivial/refine.py +66 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui_trivial/report.py +62 -0
- package/.agent-src/templates/scripts/work_engine/directives/ui_trivial/test.py +115 -0
- package/.agent-src/templates/scripts/work_engine/dispatcher.py +331 -0
- package/.agent-src/templates/scripts/work_engine/emitters.py +43 -0
- package/.agent-src/templates/scripts/work_engine/errors.py +19 -0
- package/.agent-src/templates/scripts/work_engine/hook_bootstrap.py +76 -0
- package/.agent-src/templates/scripts/work_engine/hooks/__init__.py +54 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/__init__.py +32 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/_chat_history_base.py +103 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_append.py +44 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_halt_append.py +42 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_heartbeat.py +50 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_turn_check.py +49 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/directive_set_guard.py +53 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/halt_surface_audit.py +50 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/state_shape_validation.py +52 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/trace.py +84 -0
- package/.agent-src/templates/scripts/work_engine/hooks/context.py +66 -0
- package/.agent-src/templates/scripts/work_engine/hooks/events.py +44 -0
- package/.agent-src/templates/scripts/work_engine/hooks/exceptions.py +79 -0
- package/.agent-src/templates/scripts/work_engine/hooks/registry.py +60 -0
- package/.agent-src/templates/scripts/work_engine/hooks/runner.py +73 -0
- package/.agent-src/templates/scripts/work_engine/hooks/settings.py +141 -0
- package/.agent-src/templates/scripts/work_engine/input_builders.py +163 -0
- package/.agent-src/templates/scripts/work_engine/intent/__init__.py +47 -0
- package/.agent-src/templates/scripts/work_engine/intent/classify.py +280 -0
- package/.agent-src/templates/scripts/work_engine/migration/__init__.py +8 -0
- package/.agent-src/templates/scripts/work_engine/migration/v0_to_v1.py +231 -0
- package/.agent-src/templates/scripts/{implement_ticket → work_engine}/persona_policy.py +1 -1
- package/.agent-src/templates/scripts/work_engine/resolvers/__init__.py +22 -0
- package/.agent-src/templates/scripts/work_engine/resolvers/diff.py +106 -0
- package/.agent-src/templates/scripts/work_engine/resolvers/file.py +113 -0
- package/.agent-src/templates/scripts/work_engine/resolvers/prompt.py +90 -0
- package/.agent-src/templates/scripts/work_engine/scoring/__init__.py +14 -0
- package/.agent-src/templates/scripts/work_engine/scoring/confidence.py +300 -0
- package/.agent-src/templates/scripts/work_engine/stack/__init__.py +31 -0
- package/.agent-src/templates/scripts/work_engine/stack/detect.py +187 -0
- package/.agent-src/templates/scripts/work_engine/state.py +641 -0
- package/.agent-src/templates/scripts/work_engine/state_io.py +202 -0
- package/.claude-plugin/marketplace.json +105 -2
- package/AGENTS.md +38 -8
- package/CHANGELOG.md +609 -0
- package/README.md +136 -14
- package/config/agent-settings.template.yml +45 -0
- package/config/gitignore-block.txt +4 -0
- package/docs/MIGRATION.md +122 -0
- package/docs/architecture.md +111 -35
- package/docs/contracts/STABILITY.md +95 -0
- package/docs/contracts/adr-chat-history-split.md +132 -0
- package/docs/contracts/adr-command-suggestion.md +146 -0
- package/docs/contracts/adr-implement-ticket-runtime.md +122 -0
- package/docs/contracts/adr-product-ui-track.md +384 -0
- package/docs/contracts/adr-prompt-driven-execution.md +187 -0
- package/docs/contracts/agent-memory-contract.md +149 -0
- package/docs/contracts/artifact-engagement-flow.md +262 -0
- package/docs/contracts/command-clusters.md +126 -0
- package/docs/contracts/command-suggestion-flow.md +148 -0
- package/docs/contracts/implement-ticket-flow.md +628 -0
- package/docs/contracts/linear-ai-rules-inclusion.md +143 -0
- package/docs/contracts/linear-ai-three-layers.md +131 -0
- package/docs/contracts/rule-interactions.md +107 -0
- package/docs/contracts/rule-interactions.yml +142 -0
- package/docs/contracts/ui-stack-extension.md +236 -0
- package/docs/contracts/ui-track-flow.md +338 -0
- package/docs/development.md +1 -1
- package/docs/getting-started.md +3 -3
- package/docs/installation.md +124 -2
- package/docs/migrations/commands-1.15.0.md +112 -0
- package/docs/showcase.md +204 -0
- package/docs/ui-track-mental-model.md +121 -0
- package/package.json +1 -1
- package/scripts/agent-config +199 -0
- package/scripts/audit_cloud_compatibility.py +288 -0
- package/scripts/build_cloud_bundle.py +458 -0
- package/scripts/build_linear_digest.py +263 -0
- package/scripts/chat_history.py +796 -7
- package/scripts/check_compression.py +139 -0
- package/scripts/check_iron_law_prominence.py +143 -0
- package/scripts/check_md_language.py +159 -0
- package/scripts/check_portability.py +38 -0
- package/scripts/check_public_links.py +185 -0
- package/scripts/check_references.py +1 -0
- package/scripts/check_reply_consistency.py +140 -0
- package/scripts/command_suggester/__init__.py +51 -0
- package/scripts/command_suggester/cooldown.py +132 -0
- package/scripts/command_suggester/loader.py +70 -0
- package/scripts/command_suggester/match.py +180 -0
- package/scripts/command_suggester/rank.py +120 -0
- package/scripts/command_suggester/render.py +86 -0
- package/scripts/command_suggester/sanitize.py +113 -0
- package/scripts/command_suggester/settings.py +125 -0
- package/scripts/command_suggester/types.py +78 -0
- package/scripts/hooks/augment-chat-history.sh +56 -0
- package/scripts/install-hooks.sh +67 -0
- package/scripts/install.py +150 -33
- package/scripts/lint_marketplace.py +27 -0
- package/scripts/lint_no_new_atomic_commands.py +179 -0
- package/scripts/lint_rule_interactions.py +149 -0
- package/scripts/memory_lookup.py +1 -1
- package/scripts/migrate_command_suggestions.py +151 -0
- package/scripts/release.py +297 -64
- package/scripts/schemas/command.schema.json +41 -0
- package/scripts/skill_linter.py +81 -0
- package/scripts/sync_agent_settings.py +42 -12
- package/scripts/update_counts.py +10 -0
- package/templates/consumer-settings/augment-cli-hooks.json +54 -0
- package/templates/consumer-settings/claude-settings.json +55 -1
- package/.agent-src/rules/chat-history.md +0 -171
- package/.agent-src/templates/scripts/implement_ticket/cli.py +0 -171
- package/.agent-src/templates/scripts/implement_ticket/dispatcher.py +0 -134
- package/.agent-src/templates/scripts/implement_ticket/steps/__init__.py +0 -49
- 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
|