@event4u/agent-config 1.13.0 → 1.14.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 (252) hide show
  1. package/.agent-src/commands/agent-handoff.md +3 -0
  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 +5 -1
  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 +5 -0
  11. package/.agent-src/commands/chat-history-resume.md +5 -0
  12. package/.agent-src/commands/chat-history.md +5 -0
  13. package/.agent-src/commands/check-current-md.md +126 -0
  14. package/.agent-src/commands/commit-in-chunks.md +98 -0
  15. package/.agent-src/commands/commit.md +4 -0
  16. package/.agent-src/commands/compress.md +3 -0
  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 +3 -0
  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 +24 -0
  50. package/.agent-src/commands/optimize-agents.md +4 -0
  51. package/.agent-src/commands/optimize-augmentignore.md +3 -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 +4 -1
  64. package/.agent-src/commands/review-changes.md +4 -0
  65. package/.agent-src/commands/review-routing.md +4 -0
  66. package/.agent-src/commands/roadmap-create.md +7 -0
  67. package/.agent-src/commands/roadmap-execute.md +12 -1
  68. package/.agent-src/commands/rule-compliance-audit.md +4 -0
  69. package/.agent-src/commands/set-cost-profile.md +3 -0
  70. package/.agent-src/commands/sync-agent-settings.md +3 -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 +4 -0
  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 +8 -0
  89. package/.agent-src/rules/autonomous-execution.md +158 -0
  90. package/.agent-src/rules/chat-history.md +147 -118
  91. package/.agent-src/rules/cli-output-handling.md +26 -3
  92. package/.agent-src/rules/command-suggestion.md +133 -0
  93. package/.agent-src/rules/commit-policy.md +99 -0
  94. package/.agent-src/rules/direct-answers.md +114 -0
  95. package/.agent-src/rules/docs-sync.md +36 -0
  96. package/.agent-src/rules/downstream-changes.md +10 -9
  97. package/.agent-src/rules/improve-before-implement.md +9 -6
  98. package/.agent-src/rules/language-and-tone.md +81 -6
  99. package/.agent-src/rules/non-destructive-by-default.md +117 -0
  100. package/.agent-src/rules/package-ci-checks.md +4 -0
  101. package/.agent-src/rules/preservation-guard.md +20 -0
  102. package/.agent-src/rules/roadmap-progress-sync.md +103 -30
  103. package/.agent-src/rules/scope-control.md +42 -1
  104. package/.agent-src/rules/size-enforcement.md +1 -3
  105. package/.agent-src/rules/skill-quality.md +3 -8
  106. package/.agent-src/rules/ui-audit-before-build.md +106 -0
  107. package/.agent-src/rules/user-interaction.md +82 -50
  108. package/.agent-src/scripts/update_roadmap_progress.py +17 -5
  109. package/.agent-src/skills/blade-ui/SKILL.md +30 -5
  110. package/.agent-src/skills/command-routing/SKILL.md +32 -0
  111. package/.agent-src/skills/command-writing/SKILL.md +41 -2
  112. package/.agent-src/skills/description-assist/SKILL.md +21 -0
  113. package/.agent-src/skills/estimate-ticket/SKILL.md +0 -1
  114. package/.agent-src/skills/existing-ui-audit/SKILL.md +187 -0
  115. package/.agent-src/skills/fe-design/SKILL.md +72 -60
  116. package/.agent-src/skills/finishing-a-development-branch/SKILL.md +4 -0
  117. package/.agent-src/skills/flux/SKILL.md +31 -4
  118. package/.agent-src/skills/guideline-writing/SKILL.md +24 -2
  119. package/.agent-src/skills/learning-to-rule-or-skill/SKILL.md +51 -9
  120. package/.agent-src/skills/livewire/SKILL.md +30 -4
  121. package/.agent-src/skills/md-language-check/SKILL.md +103 -0
  122. package/.agent-src/skills/php-coder/SKILL.md +24 -0
  123. package/.agent-src/skills/react-shadcn-ui/SKILL.md +121 -0
  124. package/.agent-src/skills/refine-prompt/SKILL.md +220 -0
  125. package/.agent-src/skills/refine-ticket/SKILL.md +2 -4
  126. package/.agent-src/skills/roadmap-management/SKILL.md +10 -3
  127. package/.agent-src/skills/rule-writing/SKILL.md +23 -1
  128. package/.agent-src/skills/skill-writing/SKILL.md +1 -3
  129. package/.agent-src/skills/upstream-contribute/SKILL.md +1 -1
  130. package/.agent-src/skills/using-git-worktrees/SKILL.md +3 -1
  131. package/.agent-src/templates/AGENTS.md +24 -6
  132. package/.agent-src/templates/agent-settings.md +149 -0
  133. package/.agent-src/templates/roadmaps.md +8 -2
  134. package/.agent-src/templates/scripts/implement_ticket/__init__.py +63 -26
  135. package/.agent-src/templates/scripts/implement_ticket/__main__.py +8 -2
  136. package/.agent-src/templates/scripts/telemetry/__init__.py +42 -0
  137. package/.agent-src/templates/scripts/telemetry/aggregator.py +154 -0
  138. package/.agent-src/templates/scripts/telemetry/boundary.py +171 -0
  139. package/.agent-src/templates/scripts/telemetry/engagement.py +238 -0
  140. package/.agent-src/templates/scripts/telemetry/report_renderer.py +170 -0
  141. package/.agent-src/templates/scripts/telemetry/settings.py +112 -0
  142. package/.agent-src/templates/scripts/telemetry_record.py +166 -0
  143. package/.agent-src/templates/scripts/telemetry_report.py +161 -0
  144. package/.agent-src/templates/scripts/telemetry_status.py +142 -0
  145. package/.agent-src/templates/scripts/work_engine/__init__.py +58 -0
  146. package/.agent-src/templates/scripts/work_engine/__main__.py +9 -0
  147. package/.agent-src/templates/scripts/work_engine/cli.py +592 -0
  148. package/.agent-src/templates/scripts/{implement_ticket → work_engine}/delivery_state.py +7 -0
  149. package/.agent-src/templates/scripts/work_engine/directives/__init__.py +33 -0
  150. package/.agent-src/templates/scripts/work_engine/directives/backend/__init__.py +98 -0
  151. package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/analyze.py +1 -1
  152. package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/implement.py +2 -2
  153. package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/memory.py +1 -1
  154. package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/plan.py +1 -1
  155. package/.agent-src/templates/scripts/work_engine/directives/backend/refine.py +396 -0
  156. package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/report.py +36 -4
  157. package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/test.py +2 -2
  158. package/.agent-src/templates/scripts/{implement_ticket/steps → work_engine/directives/backend}/verify.py +2 -2
  159. package/.agent-src/templates/scripts/work_engine/directives/mixed/__init__.py +116 -0
  160. package/.agent-src/templates/scripts/work_engine/directives/mixed/contract.py +254 -0
  161. package/.agent-src/templates/scripts/work_engine/directives/mixed/stitch.py +229 -0
  162. package/.agent-src/templates/scripts/work_engine/directives/mixed/ui.py +231 -0
  163. package/.agent-src/templates/scripts/work_engine/directives/ui/__init__.py +113 -0
  164. package/.agent-src/templates/scripts/work_engine/directives/ui/_passthrough.py +44 -0
  165. package/.agent-src/templates/scripts/work_engine/directives/ui/apply.py +241 -0
  166. package/.agent-src/templates/scripts/work_engine/directives/ui/audit.py +414 -0
  167. package/.agent-src/templates/scripts/work_engine/directives/ui/design.py +335 -0
  168. package/.agent-src/templates/scripts/work_engine/directives/ui/polish.py +510 -0
  169. package/.agent-src/templates/scripts/work_engine/directives/ui/review.py +468 -0
  170. package/.agent-src/templates/scripts/work_engine/directives/ui_trivial/__init__.py +119 -0
  171. package/.agent-src/templates/scripts/work_engine/directives/ui_trivial/_skipped.py +37 -0
  172. package/.agent-src/templates/scripts/work_engine/directives/ui_trivial/apply.py +165 -0
  173. package/.agent-src/templates/scripts/work_engine/directives/ui_trivial/refine.py +66 -0
  174. package/.agent-src/templates/scripts/work_engine/directives/ui_trivial/report.py +62 -0
  175. package/.agent-src/templates/scripts/work_engine/directives/ui_trivial/test.py +115 -0
  176. package/.agent-src/templates/scripts/work_engine/dispatcher.py +331 -0
  177. package/.agent-src/templates/scripts/work_engine/hooks/__init__.py +54 -0
  178. package/.agent-src/templates/scripts/work_engine/hooks/builtin/__init__.py +32 -0
  179. package/.agent-src/templates/scripts/work_engine/hooks/builtin/_chat_history_base.py +103 -0
  180. package/.agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_append.py +44 -0
  181. package/.agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_halt_append.py +42 -0
  182. package/.agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_heartbeat.py +50 -0
  183. package/.agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_turn_check.py +49 -0
  184. package/.agent-src/templates/scripts/work_engine/hooks/builtin/directive_set_guard.py +53 -0
  185. package/.agent-src/templates/scripts/work_engine/hooks/builtin/halt_surface_audit.py +50 -0
  186. package/.agent-src/templates/scripts/work_engine/hooks/builtin/state_shape_validation.py +52 -0
  187. package/.agent-src/templates/scripts/work_engine/hooks/builtin/trace.py +84 -0
  188. package/.agent-src/templates/scripts/work_engine/hooks/context.py +66 -0
  189. package/.agent-src/templates/scripts/work_engine/hooks/events.py +44 -0
  190. package/.agent-src/templates/scripts/work_engine/hooks/exceptions.py +79 -0
  191. package/.agent-src/templates/scripts/work_engine/hooks/registry.py +60 -0
  192. package/.agent-src/templates/scripts/work_engine/hooks/runner.py +73 -0
  193. package/.agent-src/templates/scripts/work_engine/hooks/settings.py +141 -0
  194. package/.agent-src/templates/scripts/work_engine/intent/__init__.py +47 -0
  195. package/.agent-src/templates/scripts/work_engine/intent/classify.py +280 -0
  196. package/.agent-src/templates/scripts/work_engine/migration/__init__.py +8 -0
  197. package/.agent-src/templates/scripts/work_engine/migration/v0_to_v1.py +199 -0
  198. package/.agent-src/templates/scripts/work_engine/resolvers/__init__.py +22 -0
  199. package/.agent-src/templates/scripts/work_engine/resolvers/diff.py +106 -0
  200. package/.agent-src/templates/scripts/work_engine/resolvers/file.py +113 -0
  201. package/.agent-src/templates/scripts/work_engine/resolvers/prompt.py +90 -0
  202. package/.agent-src/templates/scripts/work_engine/scoring/__init__.py +14 -0
  203. package/.agent-src/templates/scripts/work_engine/scoring/confidence.py +300 -0
  204. package/.agent-src/templates/scripts/work_engine/stack/__init__.py +31 -0
  205. package/.agent-src/templates/scripts/work_engine/stack/detect.py +187 -0
  206. package/.agent-src/templates/scripts/work_engine/state.py +641 -0
  207. package/.claude-plugin/marketplace.json +105 -2
  208. package/AGENTS.md +36 -8
  209. package/CHANGELOG.md +534 -0
  210. package/README.md +125 -4
  211. package/config/agent-settings.template.yml +45 -0
  212. package/config/gitignore-block.txt +4 -0
  213. package/docs/architecture.md +28 -1
  214. package/docs/development.md +1 -1
  215. package/docs/getting-started.md +2 -2
  216. package/docs/installation.md +86 -0
  217. package/docs/showcase.md +204 -0
  218. package/package.json +1 -1
  219. package/scripts/agent-config +199 -0
  220. package/scripts/audit_cloud_compatibility.py +288 -0
  221. package/scripts/build_cloud_bundle.py +458 -0
  222. package/scripts/build_linear_digest.py +263 -0
  223. package/scripts/chat_history.py +796 -7
  224. package/scripts/check_compression.py +139 -0
  225. package/scripts/check_iron_law_prominence.py +143 -0
  226. package/scripts/check_md_language.py +159 -0
  227. package/scripts/check_portability.py +36 -0
  228. package/scripts/check_reply_consistency.py +140 -0
  229. package/scripts/command_suggester/__init__.py +51 -0
  230. package/scripts/command_suggester/cooldown.py +132 -0
  231. package/scripts/command_suggester/loader.py +70 -0
  232. package/scripts/command_suggester/match.py +180 -0
  233. package/scripts/command_suggester/rank.py +120 -0
  234. package/scripts/command_suggester/render.py +86 -0
  235. package/scripts/command_suggester/sanitize.py +113 -0
  236. package/scripts/command_suggester/settings.py +125 -0
  237. package/scripts/command_suggester/types.py +78 -0
  238. package/scripts/hooks/augment-chat-history.sh +56 -0
  239. package/scripts/install-hooks.sh +67 -0
  240. package/scripts/install.py +150 -33
  241. package/scripts/lint_marketplace.py +27 -0
  242. package/scripts/migrate_command_suggestions.py +151 -0
  243. package/scripts/schemas/command.schema.json +41 -0
  244. package/scripts/skill_linter.py +67 -0
  245. package/scripts/sync_agent_settings.py +42 -12
  246. package/templates/consumer-settings/augment-cli-hooks.json +54 -0
  247. package/templates/consumer-settings/claude-settings.json +55 -1
  248. package/.agent-src/templates/scripts/implement_ticket/cli.py +0 -171
  249. package/.agent-src/templates/scripts/implement_ticket/dispatcher.py +0 -134
  250. package/.agent-src/templates/scripts/implement_ticket/steps/__init__.py +0 -49
  251. package/.agent-src/templates/scripts/implement_ticket/steps/refine.py +0 -140
  252. /package/.agent-src/templates/scripts/{implement_ticket → work_engine}/persona_policy.py +0 -0
@@ -10,6 +10,8 @@ shape used by anthropics/skills:
10
10
  - metadata must have description + version
11
11
  - metadata.version must match package.json (single source of truth)
12
12
  - every plugins[].skills[] entry must exist on disk and carry a SKILL.md
13
+ - every SKILL.md on disk under .claude/skills/ must be listed in some
14
+ plugin's skills[] (drift detection)
13
15
 
14
16
  Exit codes: 0 = clean, 1 = problems found, 3 = internal error.
15
17
  """
@@ -23,6 +25,7 @@ from pathlib import Path
23
25
  ROOT = Path(".")
24
26
  MARKETPLACE = ROOT / ".claude-plugin" / "marketplace.json"
25
27
  PACKAGE_JSON = ROOT / "package.json"
28
+ CLAUDE_SKILLS_DIR = ROOT / ".claude" / "skills"
26
29
 
27
30
 
28
31
  def fail(errors: list[str]) -> int:
@@ -121,6 +124,30 @@ def main() -> int:
121
124
  if not skill_md.exists():
122
125
  errors.append(f"{entry} has no SKILL.md: `{path}`")
123
126
 
127
+ # Reverse-completeness: every SKILL.md on disk under .claude/skills/
128
+ # must appear in some plugin's skills[]. Catches the drift where new
129
+ # skills are generated but never added to the marketplace manifest.
130
+ listed: set[str] = set()
131
+ for plugin in plugins:
132
+ if not isinstance(plugin, dict):
133
+ continue
134
+ for path in plugin.get("skills", []):
135
+ if isinstance(path, str):
136
+ listed.add(path.removeprefix("./"))
137
+
138
+ if CLAUDE_SKILLS_DIR.exists():
139
+ for skill_dir in sorted(CLAUDE_SKILLS_DIR.iterdir()):
140
+ if not skill_dir.is_dir():
141
+ continue
142
+ if not (skill_dir / "SKILL.md").exists():
143
+ continue
144
+ rel = f".claude/skills/{skill_dir.name}"
145
+ if rel not in listed:
146
+ errors.append(
147
+ f"skill exists on disk but is not listed in marketplace.json: "
148
+ f"`./{rel}`"
149
+ )
150
+
124
151
  if errors:
125
152
  return fail(errors)
126
153
 
@@ -0,0 +1,151 @@
1
+ #!/usr/bin/env python3
2
+ """One-shot migration: inject the `suggestion:` frontmatter block into every
3
+ command under `.agent-src.uncompressed/commands/`.
4
+
5
+ Source-of-truth table: `agents/contexts/command-suggestion-eligibility.md`
6
+ (locked at end of road-to-context-aware-command-suggestion Phase 1).
7
+
8
+ Idempotent: if `suggestion:` is already present for a command, the file is
9
+ left untouched. Re-runnable.
10
+ """
11
+ from __future__ import annotations
12
+
13
+ import re
14
+ import sys
15
+ from pathlib import Path
16
+
17
+ ROOT = Path(__file__).resolve().parent.parent
18
+ COMMANDS_DIR = ROOT / ".agent-src.uncompressed" / "commands"
19
+
20
+ INELIGIBLE: dict[str, str] = {
21
+ "agent-handoff": "Explicit fresh-chat handoff — must be deliberate, never inferred from prose.",
22
+ "agent-status": "Pure status display; no natural-language trigger distinct from idle small-talk.",
23
+ "agents-cleanup": "Consumes prior audit output; only meaningful right after /agents-audit.",
24
+ "agents-prepare": "One-shot project scaffolding; only run during initial setup.",
25
+ "chat-history": "Status display only; no NL trigger distinct from 'show status'.",
26
+ "chat-history-clear": "Destructive log wipe — must be deliberate.",
27
+ "chat-history-resume": "Explicit resume mechanic with foreign/returning state machine.",
28
+ "compress": "Package-internal tooling; only the event4u/agent-config repo runs this.",
29
+ "copilot-agents-init": "Project init — only deliberately during onboarding.",
30
+ "copilot-agents-optimize": "Maintenance refactor; only when the maintainer chooses to run it.",
31
+ "do-and-judge": "Subagent orchestration — overlaps /work and judge skills; keep explicit.",
32
+ "do-in-steps": "Subagent orchestration — overlaps /work and /roadmap-execute; keep explicit.",
33
+ "fix-portability": "Package-internal — only the event4u/agent-config repo runs this.",
34
+ "fix-references": "Package-internal — only the event4u/agent-config repo runs this.",
35
+ "judge": "Sibling of /review-changes — eligibility routed there; keep this explicit.",
36
+ "memory-full": "Description states 'never auto-triggered' — opt-in deep-load only.",
37
+ "memory-promote": "Curation pipeline — overlaps /memory-add; keep explicit.",
38
+ "mode": "Role-mode switch is a deliberate context change.",
39
+ "onboard": "Gated by the onboarding-gate rule already; never inferred from prose.",
40
+ "optimize-augmentignore": "Niche maintenance tool with no recurring NL trigger.",
41
+ "optimize-rtk-filters": "Niche maintenance tool with no recurring NL trigger.",
42
+ "package-reset": "Package-internal destructive reset.",
43
+ "package-test": "Package-internal — only the event4u/agent-config repo runs this.",
44
+ "propose-memory": "Programmatic intake fallback — overlaps /memory-add; keep explicit.",
45
+ "set-cost-profile": "Settings mutation — must be deliberate.",
46
+ "sync-agent-settings": "Settings sync — must be deliberate.",
47
+ "sync-gitignore": "Settings sync — must be deliberate.",
48
+ }
49
+
50
+ # (trigger_description, trigger_context)
51
+ ELIGIBLE: dict[str, tuple[str, str]] = {
52
+ "agents-audit": ("audit my agent docs, check the state of the agents/ directory", "stale files under agents/ or recent edits to .augment/ without doc updates"),
53
+ "analyze-reference-repo": ("look at how X does this, compare with that other repo, study this competitor's approach", "external repo URL or path mentioned in the prompt"),
54
+ "bug-fix": ("fix this bug, patch the issue, resolve this error", "branch name matches fix/* or bug/*"),
55
+ "bug-investigate": ("why is this broken, investigate this error, trace the root cause", "Sentry URL, Jira bug ticket key, or stack trace pasted in the prompt"),
56
+ "commit": ("commit my changes, save this to git, create commits for these changes", "git status shows uncommitted changes"),
57
+ "commit-in-chunks": ("commit everything autonomously, split and commit without confirmation", "autonomous mode active and uncommitted changes present"),
58
+ "context-create": ("document this part of the codebase, create a context doc for X", "working in a module without an agents/contexts/ doc"),
59
+ "context-refactor": ("update the context doc, refresh this context document", "existing agents/contexts/*.md referenced in the prompt"),
60
+ "create-pr": ("open a PR, create a pull request, make a PR for this branch", "branch is ahead of base and not yet on a PR"),
61
+ "create-pr-description": ("write a PR description, draft the PR text", "PR exists or branch ready for review without description"),
62
+ "e2e-heal": ("fix the failing E2E tests, playwright tests are red", "failing test output from tests/e2e/"),
63
+ "e2e-plan": ("plan E2E tests for this feature, what should we cover in playwright", "new feature or page added without tests/e2e/ coverage"),
64
+ "estimate-ticket": ("how big is this ticket, estimate PROJ-123, should we split this", "ticket key matching [A-Z]+-[0-9]+ in the prompt and no plan yet"),
65
+ "feature-dev": ("build this feature end-to-end, run the full feature workflow", "long-form feature description spanning multiple components"),
66
+ "feature-explore": ("brainstorm this idea, explore this feature concept", "open-ended feature idea without acceptance criteria"),
67
+ "feature-plan": ("plan this feature, create a feature spec for X", "feature idea referenced and no plan doc exists"),
68
+ "feature-refactor": ("update the feature plan, refine the feature spec", "existing agents/features/*.md referenced in the prompt"),
69
+ "feature-roadmap": ("turn this feature into a roadmap, generate the implementation roadmap", "existing feature plan without linked roadmap"),
70
+ "fix-ci": ("CI is failing, fix the GitHub Actions errors, the pipeline is red", "open PR with failing checks"),
71
+ "fix-pr-bot-comments": ("address the Copilot/Greptile comments, fix the bot review feedback", "open PR with bot review comments unresolved"),
72
+ "fix-pr-comments": ("fix all PR review comments, resolve the review feedback", "open PR with unresolved comments (bot + human)"),
73
+ "fix-pr-developer-comments": ("fix the human reviewer comments, address the developer feedback", "open PR with unresolved human-reviewer comments"),
74
+ "fix-seeder": ("the seeder is broken, foreign key errors in seeders", "seeder error output or recent edits in database/seeders/"),
75
+ "implement-ticket": ("implement this ticket, setze ticket X um, build PROJ-123", "ticket key matching [A-Z]+-[0-9]+ in branch name or prompt"),
76
+ "jira-ticket": ("implement the ticket on this branch, work on the Jira ticket from the branch", "branch name matching feat/PROJ-123-* or similar"),
77
+ "memory-add": ("remember this for later, add this to engineering memory, capture this learning", "post-incident or post-decision conversation"),
78
+ "module-create": ("create a new module, scaffold a module for X", "prompt mentions a new domain area without an existing module"),
79
+ "module-explore": ("show me the X module, load the module context", "existing Modules/<Name>/ referenced in the prompt"),
80
+ "optimize-agents": ("audit agent infrastructure, tune the agent setup", "maintainer working on .augment/ files"),
81
+ "optimize-skills": ("audit my skills, find duplicate skills", "maintainer working on .augment/skills/ files"),
82
+ "override-create": ("override this skill for the project, customize this rule locally", "prompt names a shared skill/rule needing project-specific behavior"),
83
+ "override-manage": ("review my overrides, update the project overrides", "existing entries under agents/overrides/"),
84
+ "prepare-for-review": ("get this branch ready for review, rebase and prep for PR", "branch behind base or part of a PR chain"),
85
+ "project-analyze": ("analyze the project structure, do a full project audit", "new project or after a major refactor"),
86
+ "project-health": ("check project health, what's the state of my docs and modules", "routine health check, no destructive intent"),
87
+ "quality-fix": ("fix the quality errors, run PHPStan and fix issues, fix code style", "PHPStan/Rector/ECS output in recent tool results"),
88
+ "refine-ticket": ("refine PROJ-123, tighten the acceptance criteria, is this ticket clear", "ticket key in prompt with vague acceptance criteria"),
89
+ "review-changes": ("self-review my changes, judge this diff before PR", "uncommitted or staged changes pre-PR"),
90
+ "review-routing": ("who should review this, suggest reviewers for this PR", "PR open without assigned reviewers"),
91
+ "roadmap-create": ("create a roadmap for X, plan this work as a roadmap", "multi-phase work without an existing agents/roadmaps/*.md"),
92
+ "roadmap-execute": ("execute the roadmap, work through the roadmap step by step", "existing agents/roadmaps/*.md referenced in the prompt"),
93
+ "rule-compliance-audit": ("audit my rules, check rule trigger quality", "maintainer working on .augment/rules/ files"),
94
+ "tests-create": ("write tests for these changes, add tests for this branch", "code changes on the branch without matching test changes"),
95
+ "tests-execute": ("run the tests, execute the test suite", "code changes pending verification"),
96
+ "threat-model": ("threat model this change, what could go wrong security-wise", "changes touching auth, webhooks, uploads, secrets, or public endpoints"),
97
+ "update-form-request-messages": ("sync the form request messages, update the validation messages", "edits to app/Http/Requests/*.php referencing rules without messages"),
98
+ "upstream-contribute": ("contribute this back to agent-config, upstream this learning", "project-local skill/rule that fits the shared package"),
99
+ "work": ("build this, implement this, drive this end-to-end", "free-form prompt without a ticket key"),
100
+ }
101
+
102
+ FRONTMATTER_RE = re.compile(r"^(---\n)(.*?)(\n---\n)", re.DOTALL)
103
+
104
+
105
+ def build_block(name: str) -> str:
106
+ if name in INELIGIBLE:
107
+ rationale = INELIGIBLE[name].replace('"', '\\"')
108
+ return f'suggestion:\n eligible: false\n rationale: "{rationale}"'
109
+ if name in ELIGIBLE:
110
+ td, tc = ELIGIBLE[name]
111
+ td_e = td.replace('"', '\\"')
112
+ tc_e = tc.replace('"', '\\"')
113
+ return (f'suggestion:\n eligible: true\n'
114
+ f' trigger_description: "{td_e}"\n'
115
+ f' trigger_context: "{tc_e}"')
116
+ raise SystemExit(f"command not classified: {name}")
117
+
118
+
119
+ def migrate_one(path: Path) -> str:
120
+ name = path.stem
121
+ text = path.read_text(encoding="utf-8")
122
+ if "\nsuggestion:" in text.split("\n---\n", 1)[0]:
123
+ return "skip"
124
+ m = FRONTMATTER_RE.search(text)
125
+ if not m:
126
+ return "no-frontmatter"
127
+ body = m.group(2)
128
+ block = build_block(name)
129
+ new_body = body.rstrip() + "\n" + block
130
+ new_text = text[: m.start()] + m.group(1) + new_body + m.group(3) + text[m.end():]
131
+ path.write_text(new_text, encoding="utf-8")
132
+ return "ok"
133
+
134
+
135
+ def main() -> int:
136
+ files = sorted(COMMANDS_DIR.glob("*.md"))
137
+ counts = {"ok": 0, "skip": 0, "no-frontmatter": 0}
138
+ for f in files:
139
+ status = migrate_one(f)
140
+ counts[status] += 1
141
+ print(f"migrated {counts['ok']}, skipped {counts['skip']}, "
142
+ f"no-frontmatter {counts['no-frontmatter']}, total {len(files)}")
143
+ expected = len(INELIGIBLE) + len(ELIGIBLE)
144
+ if len(files) != expected:
145
+ print(f"WARNING: file count {len(files)} != table count {expected}", file=sys.stderr)
146
+ return 1
147
+ return 0
148
+
149
+
150
+ if __name__ == "__main__":
151
+ sys.exit(main())
@@ -27,6 +27,47 @@
27
27
  "type": "string",
28
28
  "pattern": "^[a-z][a-z0-9-]*$"
29
29
  }
30
+ },
31
+ "suggestion": {
32
+ "type": "object",
33
+ "additionalProperties": false,
34
+ "required": ["eligible"],
35
+ "description": "Context-aware command-suggestion metadata. The suggestion layer is read-only and never auto-executes; see road-to-context-aware-command-suggestion.",
36
+ "properties": {
37
+ "eligible": {
38
+ "type": "boolean",
39
+ "description": "true → suggestion layer may surface this command; false → never suggest (still works when typed explicitly)."
40
+ },
41
+ "rationale": {
42
+ "type": "string",
43
+ "minLength": 0,
44
+ "maxLength": 240,
45
+ "description": "Why the command is ineligible. Required when eligible: false (enforced by linter)."
46
+ },
47
+ "trigger_description": {
48
+ "type": "string",
49
+ "minLength": 0,
50
+ "maxLength": 240,
51
+ "description": "Natural-language pattern trigger. Required when eligible: true (enforced by linter)."
52
+ },
53
+ "trigger_context": {
54
+ "type": "string",
55
+ "minLength": 0,
56
+ "maxLength": 240,
57
+ "description": "Concrete signal trigger (branch name, file pattern, recent tool output). Required when eligible: true (enforced by linter)."
58
+ },
59
+ "confidence_floor": {
60
+ "type": "number",
61
+ "minimum": 0,
62
+ "description": "Optional per-command override of the global confidence floor (0.0–1.0). Defaults to settings."
63
+ },
64
+ "cooldown": {
65
+ "type": "string",
66
+ "minLength": 0,
67
+ "maxLength": 16,
68
+ "description": "Optional per-command override of the global cooldown duration (e.g. '10m'). Defaults to settings."
69
+ }
70
+ }
30
71
  }
31
72
  }
32
73
  }
@@ -772,6 +772,70 @@ def lint_rule(path: Path, text: str) -> LintResult:
772
772
  )
773
773
 
774
774
 
775
+ def _lint_command_suggestion_block(text: str) -> List[Issue]:
776
+ """Validate the suggestion frontmatter block (road-to-context-aware-command-suggestion).
777
+
778
+ Schema-shape is enforced upstream by validate_frontmatter; this function adds the
779
+ *conditional* content rules that JSON Schema (Draft-07 subset used here) cannot
780
+ express: trigger fields must be non-empty when eligible, rationale must be
781
+ non-empty when ineligible.
782
+ """
783
+ issues: List[Issue] = []
784
+ data, _offset = parse_frontmatter_for_schema(text)
785
+ if data is None:
786
+ return issues
787
+ suggestion = data.get("suggestion")
788
+ if suggestion is None:
789
+ issues.append(Issue(
790
+ "warning", "missing_suggestion_block",
791
+ "Command frontmatter is missing the 'suggestion' block — required by "
792
+ "road-to-context-aware-command-suggestion Phase 2.",
793
+ ))
794
+ return issues
795
+ if not isinstance(suggestion, dict):
796
+ issues.append(Issue("error", "invalid_suggestion_block", "'suggestion' must be a mapping"))
797
+ return issues
798
+ eligible = suggestion.get("eligible")
799
+ if eligible is True:
800
+ td = (suggestion.get("trigger_description") or "").strip()
801
+ tc = (suggestion.get("trigger_context") or "").strip()
802
+ if not td:
803
+ issues.append(Issue(
804
+ "error", "missing_trigger_description",
805
+ "suggestion.eligible=true requires a non-empty 'trigger_description'.",
806
+ ))
807
+ elif len(td) < 10:
808
+ issues.append(Issue(
809
+ "warning", "trigger_description_too_short",
810
+ "suggestion.trigger_description is suspiciously short (<10 chars); "
811
+ "linter rejects empty or overly generic patterns.",
812
+ ))
813
+ if not tc:
814
+ issues.append(Issue(
815
+ "error", "missing_trigger_context",
816
+ "suggestion.eligible=true requires a non-empty 'trigger_context'.",
817
+ ))
818
+ elif len(tc) < 10:
819
+ issues.append(Issue(
820
+ "warning", "trigger_context_too_short",
821
+ "suggestion.trigger_context is suspiciously short (<10 chars); "
822
+ "linter rejects empty or overly generic patterns.",
823
+ ))
824
+ elif eligible is False:
825
+ rationale = (suggestion.get("rationale") or "").strip()
826
+ if not rationale:
827
+ issues.append(Issue(
828
+ "error", "missing_suggestion_rationale",
829
+ "suggestion.eligible=false requires a non-empty 'rationale'.",
830
+ ))
831
+ else:
832
+ issues.append(Issue(
833
+ "error", "invalid_suggestion_eligible",
834
+ "suggestion.eligible must be true or false.",
835
+ ))
836
+ return issues
837
+
838
+
775
839
  def lint_command(path: Path, text: str) -> LintResult:
776
840
  issues: List[Issue] = []
777
841
  suggestions: List[str] = []
@@ -800,6 +864,9 @@ def lint_command(path: Path, text: str) -> LintResult:
800
864
  if not description:
801
865
  issues.append(Issue("warning", "missing_description", "Frontmatter description is missing"))
802
866
 
867
+ # suggestion block (road-to-context-aware-command-suggestion Phase 2)
868
+ issues.extend(_lint_command_suggestion_block(text))
869
+
803
870
  # --- Structure checks ---
804
871
  if not H1_PATTERN.search(text):
805
872
  issues.append(Issue("error", "missing_h1", "Command is missing an H1 heading (# Title)"))
@@ -47,29 +47,48 @@ DEFAULT_PROFILE_DIR = Path(__file__).resolve().parent.parent / "config" / "profi
47
47
 
48
48
 
49
49
  def _flatten(data: dict, prefix: str = "") -> dict[str, object]:
50
- """Flatten nested dicts to dotted keys — one level of nesting supported."""
50
+ """Flatten nested dicts to dotted keys — recurses to all leaves.
51
+
52
+ Lists, scalars, and ``None`` are leaves. Dicts are walked and their
53
+ keys folded into the dotted path.
54
+ """
51
55
  out: dict[str, object] = {}
52
56
  for key, value in data.items():
53
57
  path = f"{prefix}{key}"
54
58
  if isinstance(value, dict):
55
- for sub_key, sub_val in value.items():
56
- out[f"{path}.{sub_key}"] = sub_val
59
+ out.update(_flatten(value, prefix=f"{path}."))
57
60
  else:
58
61
  out[path] = value
59
62
  return out
60
63
 
61
64
 
62
- def _as_scalar_text(value: object) -> str:
63
- """Normalize a parsed YAML value to the raw string form expected by
64
- `install._replace_template_value` — which re-quotes via `_yaml_scalar`
65
- internally, so we must pass the *unquoted* payload here."""
65
+ def _as_yaml_value(value: object) -> str | None:
66
+ """Format *value* as an inline-YAML literal.
67
+
68
+ Returns ``None`` when the value cannot be safely represented as a
69
+ scalar / flow-style sequence (e.g. unsupported types). Callers
70
+ must skip those keys so the template default sticks instead of
71
+ producing malformed YAML.
72
+ """
66
73
  if isinstance(value, bool):
67
74
  return "true" if value else "false"
68
75
  if isinstance(value, int):
69
76
  return str(value)
77
+ if isinstance(value, float):
78
+ return repr(value)
70
79
  if value is None:
71
- return ""
72
- return str(value)
80
+ return "~"
81
+ if isinstance(value, list):
82
+ items: list[str] = []
83
+ for item in value:
84
+ rendered = _as_yaml_value(item)
85
+ if rendered is None:
86
+ return None
87
+ items.append(rendered)
88
+ return "[" + ", ".join(items) + "]"
89
+ if isinstance(value, str):
90
+ return _install._yaml_scalar(value)
91
+ return None
73
92
 
74
93
 
75
94
  def _template_keys(template_body: str) -> set[str]:
@@ -81,10 +100,18 @@ def _template_keys(template_body: str) -> set[str]:
81
100
 
82
101
 
83
102
  def _apply_user_values(template_body: str, user_flat: dict[str, object]) -> str:
84
- """Overlay every known user value on the rendered template body."""
103
+ """Overlay every known user value on the rendered template body.
104
+
105
+ Keys whose value cannot be rendered inline (see :func:`_as_yaml_value`)
106
+ are skipped so the template default survives instead of corrupting
107
+ the file.
108
+ """
85
109
  body = template_body
86
110
  for dotted, value in user_flat.items():
87
- body = _install._replace_template_value(body, dotted, _as_scalar_text(value))
111
+ rendered = _as_yaml_value(value)
112
+ if rendered is None:
113
+ continue
114
+ body = _install._replace_template_value_raw(body, dotted, rendered)
88
115
  return body
89
116
 
90
117
 
@@ -100,7 +127,10 @@ def _append_unknown(body: str, user_flat: dict[str, object], known: set[str]) ->
100
127
  "_user:",
101
128
  ]
102
129
  for key in unknown:
103
- lines.append(f" {key}: {_install._yaml_scalar(_as_scalar_text(user_flat[key]))}")
130
+ rendered = _as_yaml_value(user_flat[key])
131
+ if rendered is None:
132
+ continue
133
+ lines.append(f" {key}: {rendered}")
104
134
  suffix = "\n".join(lines) + "\n"
105
135
  return body + (suffix if body.endswith("\n") else "\n" + suffix)
106
136
 
@@ -0,0 +1,54 @@
1
+ {
2
+ "// Instructions": "OPTIONAL: merge this into ~/.augment/settings.json (user-scope, NOT project-scope) to wire chat-history hooks for the Augment CLI.",
3
+ "// Why user-scope": "The Augment CLI reads hooks from ~/.augment/settings.json (per https://docs.augmentcode.com/cli/hooks.md). Project-scoped .augment/settings.json belongs to the IDE plugin, which has no documented hook surface as of 2026-04-30.",
4
+ "// IDE plugin": "Use the /chat-history-checkpoint command at phase boundaries instead — see rules/chat-history.md.",
5
+ "// Wrapper": "The command assumes the project-root ./agent-config wrapper is on PATH or invoked with a project-relative cwd. Adjust to absolute paths if your shell does not chdir into the project.",
6
+
7
+ "hooks": {
8
+ "SessionStart": [
9
+ {
10
+ "hooks": [
11
+ {
12
+ "type": "command",
13
+ "command": "./agent-config chat-history:hook --platform augment",
14
+ "timeout": 5000
15
+ }
16
+ ]
17
+ }
18
+ ],
19
+ "PostToolUse": [
20
+ {
21
+ "matcher": ".*",
22
+ "hooks": [
23
+ {
24
+ "type": "command",
25
+ "command": "./agent-config chat-history:hook --platform augment",
26
+ "timeout": 3000
27
+ }
28
+ ]
29
+ }
30
+ ],
31
+ "Stop": [
32
+ {
33
+ "hooks": [
34
+ {
35
+ "type": "command",
36
+ "command": "./agent-config chat-history:hook --platform augment",
37
+ "timeout": 3000
38
+ }
39
+ ]
40
+ }
41
+ ],
42
+ "SessionEnd": [
43
+ {
44
+ "hooks": [
45
+ {
46
+ "type": "command",
47
+ "command": "./agent-config chat-history:hook --platform augment",
48
+ "timeout": 3000
49
+ }
50
+ ]
51
+ }
52
+ ]
53
+ }
54
+ }
@@ -1,9 +1,63 @@
1
1
  {
2
- "// Instructions": "Copy this into your project's .claude/settings.json to auto-enable the agent-config plugin.",
2
+ "// Instructions": "Copy this into your project's .claude/settings.json to auto-enable the agent-config plugin and chat-history hooks.",
3
3
  "// After setup": "Claude Code will load the plugin when the marketplace is installed.",
4
4
  "// Install marketplace": "Run: claude plugin marketplace add event4u-app/agent-config",
5
+ "// Hooks": "Hooks call ./agent-config (the wrapper installed at the project root) which dispatches to scripts/chat_history.py hook-dispatch. They are no-ops when chat_history.enabled is false in .agent-settings.yml.",
5
6
 
6
7
  "enabledPlugins": {
7
8
  "agent-conf@event4u": true
9
+ },
10
+
11
+ "hooks": {
12
+ "SessionStart": [
13
+ {
14
+ "hooks": [
15
+ {
16
+ "type": "command",
17
+ "command": "./agent-config chat-history:hook --platform claude"
18
+ }
19
+ ]
20
+ }
21
+ ],
22
+ "UserPromptSubmit": [
23
+ {
24
+ "hooks": [
25
+ {
26
+ "type": "command",
27
+ "command": "./agent-config chat-history:hook --platform claude"
28
+ }
29
+ ]
30
+ }
31
+ ],
32
+ "PostToolUse": [
33
+ {
34
+ "hooks": [
35
+ {
36
+ "type": "command",
37
+ "command": "./agent-config chat-history:hook --platform claude"
38
+ }
39
+ ]
40
+ }
41
+ ],
42
+ "Stop": [
43
+ {
44
+ "hooks": [
45
+ {
46
+ "type": "command",
47
+ "command": "./agent-config chat-history:hook --platform claude"
48
+ }
49
+ ]
50
+ }
51
+ ],
52
+ "SessionEnd": [
53
+ {
54
+ "hooks": [
55
+ {
56
+ "type": "command",
57
+ "command": "./agent-config chat-history:hook --platform claude"
58
+ }
59
+ ]
60
+ }
61
+ ]
8
62
  }
9
63
  }