@event4u/agent-config 1.16.0 → 1.17.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 (203) hide show
  1. package/.agent-src/commands/{agents-audit.md → agents/audit.md} +4 -3
  2. package/.agent-src/commands/{agents-cleanup.md → agents/cleanup.md} +12 -6
  3. package/.agent-src/commands/{agents-prepare.md → agents/prepare.md} +4 -3
  4. package/.agent-src/commands/agents.md +46 -0
  5. package/.agent-src/commands/{chat-history-checkpoint.md → chat-history/checkpoint.md} +4 -4
  6. package/.agent-src/commands/{chat-history-clear.md → chat-history/clear.md} +4 -4
  7. package/.agent-src/commands/{chat-history-resume.md → chat-history/resume.md} +4 -4
  8. package/.agent-src/commands/chat-history/show.md +107 -0
  9. package/.agent-src/commands/chat-history.md +33 -89
  10. package/.agent-src/commands/{commit-in-chunks.md → commit/in-chunks.md} +15 -13
  11. package/.agent-src/commands/commit.md +22 -2
  12. package/.agent-src/commands/{context-create.md → context/create.md} +4 -3
  13. package/.agent-src/commands/{context-refactor.md → context/refactor.md} +4 -3
  14. package/.agent-src/commands/context.md +44 -0
  15. package/.agent-src/commands/{copilot-agents-init.md → copilot-agents/init.md} +4 -3
  16. package/.agent-src/commands/{copilot-agents-optimize.md → copilot-agents/optimize.md} +4 -3
  17. package/.agent-src/commands/copilot-agents.md +44 -0
  18. package/.agent-src/commands/council/default.md +221 -0
  19. package/.agent-src/commands/{council-design.md → council/design.md} +6 -5
  20. package/.agent-src/commands/{council-optimize.md → council/optimize.md} +7 -6
  21. package/.agent-src/commands/{council-pr.md → council/pr.md} +6 -5
  22. package/.agent-src/commands/council.md +47 -212
  23. package/.agent-src/commands/{create-pr-description.md → create-pr/description-only.md} +4 -2
  24. package/.agent-src/commands/create-pr.md +26 -5
  25. package/.agent-src/commands/{feature-dev.md → feature/dev.md} +5 -10
  26. package/.agent-src/commands/{feature-explore.md → feature/explore.md} +4 -8
  27. package/.agent-src/commands/{feature-plan.md → feature/plan.md} +4 -8
  28. package/.agent-src/commands/{feature-refactor.md → feature/refactor.md} +4 -8
  29. package/.agent-src/commands/{feature-roadmap.md → feature/roadmap.md} +6 -10
  30. package/.agent-src/commands/feature.md +6 -12
  31. package/.agent-src/commands/{fix-ci.md → fix/ci.md} +4 -8
  32. package/.agent-src/commands/{fix-portability.md → fix/portability.md} +4 -8
  33. package/.agent-src/commands/{fix-pr-bot-comments.md → fix/pr-bots.md} +4 -8
  34. package/.agent-src/commands/{fix-pr-developer-comments.md → fix/pr-developers.md} +4 -8
  35. package/.agent-src/commands/{fix-pr-comments.md → fix/pr.md} +7 -11
  36. package/.agent-src/commands/{fix-references.md → fix/refs.md} +4 -8
  37. package/.agent-src/commands/{fix-seeder.md → fix/seeder.md} +4 -8
  38. package/.agent-src/commands/fix.md +7 -13
  39. package/.agent-src/commands/{do-and-judge.md → judge/on-diff.md} +4 -3
  40. package/.agent-src/commands/judge/solo.md +90 -0
  41. package/.agent-src/commands/{do-in-steps.md → judge/steps.md} +4 -3
  42. package/.agent-src/commands/judge.md +35 -70
  43. package/.agent-src/commands/{memory-add.md → memory/add.md} +4 -3
  44. package/.agent-src/commands/{memory-full.md → memory/load.md} +4 -3
  45. package/.agent-src/commands/{memory-promote.md → memory/promote.md} +4 -3
  46. package/.agent-src/commands/{propose-memory.md → memory/propose.md} +4 -3
  47. package/.agent-src/commands/memory.md +48 -0
  48. package/.agent-src/commands/{module-create.md → module/create.md} +4 -3
  49. package/.agent-src/commands/{module-explore.md → module/explore.md} +4 -3
  50. package/.agent-src/commands/module.md +44 -0
  51. package/.agent-src/commands/{optimize-agents.md → optimize/agents.md} +4 -8
  52. package/.agent-src/commands/{optimize-augmentignore.md → optimize/augmentignore.md} +4 -9
  53. package/.agent-src/commands/{optimize-rtk-filters.md → optimize/rtk.md} +4 -8
  54. package/.agent-src/commands/{optimize-skills.md → optimize/skills.md} +4 -8
  55. package/.agent-src/commands/optimize.md +4 -10
  56. package/.agent-src/commands/{override-create.md → override/create.md} +4 -3
  57. package/.agent-src/commands/{override-manage.md → override/manage.md} +4 -3
  58. package/.agent-src/commands/override.md +44 -0
  59. package/.agent-src/commands/{roadmap-create.md → roadmap/create.md} +4 -3
  60. package/.agent-src/commands/{roadmap-execute.md → roadmap/execute.md} +4 -3
  61. package/.agent-src/commands/roadmap.md +44 -0
  62. package/.agent-src/commands/{tests-create.md → tests/create.md} +4 -3
  63. package/.agent-src/commands/{tests-execute.md → tests/execute.md} +4 -3
  64. package/.agent-src/commands/tests.md +44 -0
  65. package/.agent-src/contexts/communication/rules-auto/artifact-engagement-recording-mechanics.md +72 -0
  66. package/.agent-src/contexts/communication/rules-auto/augment-portability-mechanics.md +79 -0
  67. package/.agent-src/contexts/communication/rules-auto/augment-source-of-truth-mechanics.md +98 -0
  68. package/.agent-src/contexts/communication/rules-auto/cli-output-handling-mechanics.md +87 -0
  69. package/.agent-src/contexts/communication/rules-auto/command-suggestion-policy-mechanics.md +62 -0
  70. package/.agent-src/contexts/communication/rules-auto/docs-sync-mechanics.md +78 -0
  71. package/.agent-src/contexts/communication/rules-auto/package-ci-checks-mechanics.md +85 -0
  72. package/.agent-src/contexts/communication/rules-auto/review-routing-awareness-mechanics.md +65 -0
  73. package/.agent-src/contexts/communication/rules-auto/roadmap-progress-sync-mechanics.md +78 -0
  74. package/.agent-src/contexts/communication/rules-auto/skill-quality-mechanics.md +62 -0
  75. package/.agent-src/contexts/communication/rules-auto/slash-command-routing-policy-mechanics.md +55 -0
  76. package/.agent-src/contexts/communication/rules-auto/ui-audit-gate-mechanics.md +53 -0
  77. package/.agent-src/contexts/communication/rules-auto/user-interaction-mechanics.md +77 -0
  78. package/.agent-src/contexts/judges/no-consolidate-rationale.md +102 -0
  79. package/.agent-src/contexts/judges/persona-voice-rubric.md +140 -0
  80. package/.agent-src/rules/artifact-engagement-recording.md +13 -69
  81. package/.agent-src/rules/ask-when-uncertain.md +27 -42
  82. package/.agent-src/rules/augment-portability.md +15 -61
  83. package/.agent-src/rules/augment-source-of-truth.md +27 -93
  84. package/.agent-src/rules/cli-output-handling.md +10 -76
  85. package/.agent-src/rules/command-suggestion-policy.md +18 -59
  86. package/.agent-src/rules/commit-conventions.md +17 -14
  87. package/.agent-src/rules/direct-answers.md +34 -49
  88. package/.agent-src/rules/docker-commands.md +5 -5
  89. package/.agent-src/rules/docs-sync.md +15 -69
  90. package/.agent-src/rules/language-and-tone.md +48 -72
  91. package/.agent-src/rules/missing-tool-handling.md +28 -22
  92. package/.agent-src/rules/no-cheap-questions.md +45 -52
  93. package/.agent-src/rules/no-roadmap-references.md +73 -0
  94. package/.agent-src/rules/package-ci-checks.md +21 -61
  95. package/.agent-src/rules/preservation-guard.md +64 -29
  96. package/.agent-src/rules/review-routing-awareness.md +24 -43
  97. package/.agent-src/rules/roadmap-progress-sync.md +10 -71
  98. package/.agent-src/rules/security-sensitive-stop.md +8 -8
  99. package/.agent-src/rules/skill-quality.md +16 -48
  100. package/.agent-src/rules/slash-command-routing-policy.md +7 -4
  101. package/.agent-src/rules/think-before-action.md +52 -42
  102. package/.agent-src/rules/tool-safety.md +19 -16
  103. package/.agent-src/rules/ui-audit-gate.md +24 -38
  104. package/.agent-src/rules/user-interaction.md +13 -68
  105. package/.agent-src/skills/ai-council/SKILL.md +2 -0
  106. package/.agent-src/skills/api-testing/SKILL.md +1 -1
  107. package/.agent-src/skills/check-refs/SKILL.md +59 -40
  108. package/.agent-src/skills/conventional-commits-writing/SKILL.md +86 -28
  109. package/.agent-src/skills/copilot-agents-optimization/SKILL.md +5 -5
  110. package/.agent-src/skills/developer-like-execution/SKILL.md +4 -4
  111. package/.agent-src/skills/finishing-a-development-branch/SKILL.md +101 -65
  112. package/.agent-src/skills/flux/SKILL.md +30 -10
  113. package/.agent-src/skills/github-ci/SKILL.md +2 -2
  114. package/.agent-src/skills/judge-code-quality/SKILL.md +7 -8
  115. package/.agent-src/skills/judge-security-auditor/SKILL.md +4 -5
  116. package/.agent-src/skills/judge-test-coverage/SKILL.md +3 -4
  117. package/.agent-src/skills/lint-skills/SKILL.md +57 -39
  118. package/.agent-src/skills/md-language-check/SKILL.md +61 -39
  119. package/.agent-src/skills/override-management/SKILL.md +5 -5
  120. package/.agent-src/skills/quality-tools/SKILL.md +2 -2
  121. package/.agent-src/skills/react-shadcn-ui/SKILL.md +116 -43
  122. package/.agent-src/skills/readme-reviewer/SKILL.md +30 -29
  123. package/.agent-src/skills/readme-writing/SKILL.md +78 -53
  124. package/.agent-src/skills/readme-writing-package/SKILL.md +50 -47
  125. package/.agent-src/skills/receiving-code-review/SKILL.md +52 -47
  126. package/.agent-src/skills/refine-prompt/SKILL.md +0 -1
  127. package/.agent-src/skills/requesting-code-review/SKILL.md +35 -30
  128. package/.agent-src/skills/security/SKILL.md +7 -2
  129. package/.agent-src/skills/security-audit/SKILL.md +7 -3
  130. package/.agent-src/skills/systematic-debugging/SKILL.md +68 -60
  131. package/.agent-src/skills/test-driven-development/SKILL.md +59 -57
  132. package/.agent-src/skills/test-performance/SKILL.md +0 -1
  133. package/.agent-src/skills/traefik/SKILL.md +4 -4
  134. package/.agent-src/skills/verify-completion-evidence/SKILL.md +28 -26
  135. package/.claude-plugin/marketplace.json +22 -11
  136. package/AGENTS.md +2 -2
  137. package/CHANGELOG.md +90 -1
  138. package/README.md +18 -17
  139. package/docs/architecture.md +4 -6
  140. package/docs/catalog.md +67 -39
  141. package/docs/contracts/STABILITY.md +13 -7
  142. package/docs/contracts/adr-chat-history-split.md +1 -3
  143. package/docs/contracts/adr-command-suggestion.md +0 -2
  144. package/docs/contracts/adr-implement-ticket-runtime.md +1 -2
  145. package/docs/contracts/adr-product-ui-track.md +3 -6
  146. package/docs/contracts/adr-prompt-driven-execution.md +3 -4
  147. package/docs/contracts/agent-memory-contract.md +6 -11
  148. package/docs/contracts/artifact-engagement-flow.md +6 -9
  149. package/docs/contracts/command-clusters.md +56 -46
  150. package/docs/contracts/command-suggestion-flow.md +1 -3
  151. package/docs/contracts/context-paths.md +99 -0
  152. package/docs/contracts/file-ownership-matrix.json +6722 -0
  153. package/docs/contracts/file-ownership-matrix.md +134 -0
  154. package/docs/contracts/implement-ticket-flow.md +6 -9
  155. package/docs/contracts/linear-ai-rules-inclusion.md +0 -1
  156. package/docs/contracts/linear-ai-three-layers.md +0 -2
  157. package/docs/contracts/load-context-budget-model.md +178 -0
  158. package/docs/contracts/load-context-schema.md +1 -3
  159. package/docs/contracts/rule-interactions.md +0 -1
  160. package/docs/contracts/rule-priority-hierarchy.md +1 -1
  161. package/docs/contracts/ui-track-flow.md +7 -17
  162. package/docs/customization.md +2 -0
  163. package/docs/getting-started.md +5 -4
  164. package/docs/guidelines/agent-infra/asking-and-brevity-examples.md +100 -0
  165. package/package.json +1 -1
  166. package/scripts/_one_off_phase4_dispatch_latency.py +108 -0
  167. package/scripts/_one_off_phase6_trigger_jaccard.py +92 -0
  168. package/scripts/_phase2_shim_helper.py +109 -0
  169. package/scripts/agent-config +10 -0
  170. package/scripts/ai_council/_one_off_2a4_acceptance.py +208 -0
  171. package/scripts/ai_council/_one_off_context_layer_v1_estimate.py +67 -0
  172. package/scripts/ai_council/_one_off_context_layer_v1_review.py +292 -0
  173. package/scripts/ai_council/_one_off_followups_review.py +259 -0
  174. package/scripts/ai_council/_one_off_nondestructive_inline_audit.py +209 -0
  175. package/scripts/ai_council/_one_off_phase_2a_budget_rebalance.py +257 -0
  176. package/scripts/ai_council/_one_off_phase_2a_post_revert.py +197 -0
  177. package/scripts/ai_council/_one_off_rule_hardening_v1.py +251 -0
  178. package/scripts/ai_council/_one_off_structural_open_questions.py +232 -0
  179. package/scripts/ai_council/_one_off_structural_optimization.py +144 -0
  180. package/scripts/ai_council/_one_off_structural_v3_gaps.py +252 -0
  181. package/scripts/ai_council/_one_off_structural_v3_review.py +240 -0
  182. package/scripts/check_always_budget.py +363 -45
  183. package/scripts/check_cluster_patterns.py +159 -0
  184. package/scripts/check_command_count_messaging.py +14 -7
  185. package/scripts/check_context_paths.py +201 -0
  186. package/scripts/check_no_roadmap_refs.py +155 -0
  187. package/scripts/check_phase_coupling.py +148 -0
  188. package/scripts/check_portability.py +2 -0
  189. package/scripts/check_references.py +29 -2
  190. package/scripts/check_safety_floor_untouched.py +125 -0
  191. package/scripts/command_suggester/loader.py +4 -1
  192. package/scripts/compress.py +59 -13
  193. package/scripts/generate_index.py +6 -2
  194. package/scripts/generate_ownership_matrix.py +323 -0
  195. package/scripts/hooks/augment-roadmap-progress.sh +57 -0
  196. package/scripts/install.py +49 -28
  197. package/scripts/lint_no_new_atomic_commands.py +12 -11
  198. package/scripts/requirements-evals.txt +1 -0
  199. package/scripts/roadmap_progress_hook.py +159 -0
  200. package/scripts/schemas/command.schema.json +4 -3
  201. package/scripts/skill_linter.py +1 -0
  202. package/scripts/sync_agent_settings.py +25 -2
  203. package/scripts/update_counts.py +7 -0
@@ -0,0 +1,108 @@
1
+ #!/usr/bin/env python3
2
+ """Phase 4.3.1 — council cluster dispatch-latency benchmark.
3
+
4
+ Measures the wall-clock overhead of the cluster dispatch layer for the
5
+ `/council` family. Compares:
6
+
7
+ baseline: directly read council-pr.md / council-design.md (atomic shape)
8
+ cluster : read council.md (dispatcher) + parse table + read council-pr.md
9
+ / council-design.md (cluster shape)
10
+
11
+ The dispatch layer in agent-config is a markdown parse, not a runtime
12
+ function, so this benchmarks the file-system + frontmatter + table-row
13
+ extraction cost. Threshold per roadmap § 4.3.1: ≤ +100ms wall-clock.
14
+ """
15
+ from __future__ import annotations
16
+
17
+ import re
18
+ import statistics
19
+ import time
20
+ from pathlib import Path
21
+
22
+ ROOT = Path(__file__).resolve().parent.parent
23
+ COMMANDS = ROOT / ".agent-src/commands"
24
+ N_ITER = 1000 # cold + warm; markdown is tiny so we run a lot of iterations
25
+
26
+ FRONTMATTER_RE = re.compile(r"^---\n(.*?)\n---\n", re.DOTALL)
27
+ TABLE_ROW_RE = re.compile(r"\|\s*`/council\s+([a-z-]+)`\s*\|\s*`([^`]+)`")
28
+
29
+
30
+ def _read_atomic(target: str) -> str:
31
+ """Baseline: directly read the routed file (atomic shape)."""
32
+ path = COMMANDS / f"council-{target}.md"
33
+ text = path.read_text(encoding="utf-8")
34
+ m = FRONTMATTER_RE.match(text)
35
+ if not m:
36
+ raise RuntimeError(f"no frontmatter in {path}")
37
+ return text
38
+
39
+
40
+ def _read_cluster(target: str) -> str:
41
+ """Cluster: read dispatcher, parse routing table, then read routed file."""
42
+ dispatcher = (COMMANDS / "council.md").read_text(encoding="utf-8")
43
+ routes = dict(TABLE_ROW_RE.findall(dispatcher))
44
+ routed = routes.get(target)
45
+ if routed is None:
46
+ raise RuntimeError(f"no route for {target!r} in dispatcher")
47
+ text = (COMMANDS / routed).read_text(encoding="utf-8")
48
+ m = FRONTMATTER_RE.match(text)
49
+ if not m:
50
+ raise RuntimeError(f"no frontmatter in {routed}")
51
+ return text
52
+
53
+
54
+ def _bench(fn, target: str, n: int) -> list[float]:
55
+ samples: list[float] = []
56
+ for _ in range(n):
57
+ t0 = time.perf_counter()
58
+ fn(target)
59
+ samples.append((time.perf_counter() - t0) * 1000.0)
60
+ return samples
61
+
62
+
63
+ def _summary(name: str, samples: list[float]) -> None:
64
+ samples = sorted(samples)
65
+ p50 = statistics.median(samples)
66
+ p95 = samples[int(len(samples) * 0.95)]
67
+ p99 = samples[int(len(samples) * 0.99)]
68
+ mean = statistics.mean(samples)
69
+ print(f" {name:18s} mean={mean:6.3f}ms p50={p50:6.3f}ms p95={p95:6.3f}ms p99={p99:6.3f}ms")
70
+
71
+
72
+ def main() -> int:
73
+ print(f"Phase 4.3.1 — council cluster dispatch latency (n={N_ITER} per probe)")
74
+ print()
75
+
76
+ overruns = 0
77
+ for target in ("pr", "design"):
78
+ print(f"target = /council {target}")
79
+
80
+ # warm cache
81
+ _read_atomic(target)
82
+ _read_cluster(target)
83
+
84
+ baseline = _bench(_read_atomic, target, N_ITER)
85
+ cluster = _bench(_read_cluster, target, N_ITER)
86
+
87
+ _summary("atomic (baseline)", baseline)
88
+ _summary("cluster (dispatcher)", cluster)
89
+
90
+ delta_mean = statistics.mean(cluster) - statistics.mean(baseline)
91
+ delta_p95 = sorted(cluster)[int(N_ITER * 0.95)] - sorted(baseline)[int(N_ITER * 0.95)]
92
+ verdict = "PASS" if delta_p95 <= 100.0 else "FAIL"
93
+ marker = "✅" if verdict == "PASS" else "❌"
94
+ print(f" delta-mean = {delta_mean:+.3f}ms delta-p95 = {delta_p95:+.3f}ms threshold = +100ms {marker} {verdict}")
95
+ print()
96
+
97
+ if delta_p95 > 100.0:
98
+ overruns += 1
99
+
100
+ if overruns:
101
+ print(f"❌ {overruns} probe(s) exceeded +100ms p95 threshold.")
102
+ return 1
103
+ print("✅ All probes within +100ms p95 threshold.")
104
+ return 0
105
+
106
+
107
+ if __name__ == "__main__":
108
+ raise SystemExit(main())
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env python3
2
+ """Phase 6.1 — chat-history-* trigger overlap (Jaccard).
3
+
4
+ Source of truth per rule = frontmatter `description:` field
5
+ (the trigger surface that decides when an `auto` rule activates).
6
+ Tokens = lowercased alphanum words length ≥ 3, minus a small
7
+ stop-list of file-name fragments and connective words that carry
8
+ no trigger signal.
9
+
10
+ Output: pairwise Jaccard + branch verdict per roadmap § 6.1.
11
+ """
12
+ from __future__ import annotations
13
+
14
+ import re
15
+ from itertools import combinations
16
+ from pathlib import Path
17
+
18
+ ROOT = Path(__file__).resolve().parent.parent
19
+ RULES_DIR = ROOT / ".agent-src.uncompressed/rules"
20
+
21
+ RULES = [
22
+ "chat-history-cadence",
23
+ "chat-history-ownership",
24
+ "chat-history-visibility",
25
+ ]
26
+
27
+ STOP = {
28
+ "the", "and", "for", "with", "from", "via", "per", "not",
29
+ "into", "onto", "out", "off", "any", "all", "this", "that",
30
+ "agent", "chat", "history",
31
+ "agentchathistory", "chathistory",
32
+ "rule", "rules", "file", "files",
33
+ }
34
+
35
+ DESC_RE = re.compile(r'^description:\s*"([^"]+)"', re.MULTILINE)
36
+ TOKEN_RE = re.compile(r"[a-z][a-z0-9_]{2,}")
37
+
38
+
39
+ def tokens(rule_id: str) -> set[str]:
40
+ text = (RULES_DIR / f"{rule_id}.md").read_text(encoding="utf-8")
41
+ m = DESC_RE.search(text)
42
+ if not m:
43
+ raise RuntimeError(f"no description in {rule_id}")
44
+ desc = m.group(1).lower()
45
+ raw = TOKEN_RE.findall(desc)
46
+ return {t for t in raw if t not in STOP}
47
+
48
+
49
+ def jaccard(a: set[str], b: set[str]) -> float:
50
+ union = a | b
51
+ if not union:
52
+ return 0.0
53
+ return len(a & b) / len(union)
54
+
55
+
56
+ def main() -> int:
57
+ sets = {r: tokens(r) for r in RULES}
58
+
59
+ print(f"Phase 6.1 — trigger Jaccard (source: frontmatter `description:`)")
60
+ print()
61
+ for r, ts in sets.items():
62
+ print(f" {r} ({len(ts)} tokens)")
63
+ print(f" {sorted(ts)}")
64
+ print()
65
+
66
+ print("Pairwise Jaccard:")
67
+ print()
68
+ print(f" {'pair':55s} intersect union Jaccard")
69
+ pairs_above = 0
70
+ for a, b in combinations(RULES, 2):
71
+ inter = sets[a] & sets[b]
72
+ union = sets[a] | sets[b]
73
+ j = jaccard(sets[a], sets[b])
74
+ marker = " **" if j >= 0.30 else ""
75
+ print(f" {a + ' × ' + b:55s} {len(inter):>8d} {len(union):>5d} {j:>6.3f}{marker}")
76
+ print(f" intersection: {sorted(inter)}")
77
+ if j >= 0.30:
78
+ pairs_above += 1
79
+ print()
80
+
81
+ if pairs_above >= 2:
82
+ print(f"VERDICT: ≥ 30% on {pairs_above}/3 pairs → PROCEED to 6.2 (unified shape).")
83
+ return 0
84
+ if pairs_above == 1:
85
+ print(f"VERDICT: mixed ({pairs_above}/3 pairs ≥ 30%) → ESCALATE to council.")
86
+ return 0
87
+ print(f"VERDICT: < 30% on all 3 pairs → STOP at 6.1 (orthogonal — current shape optimal).")
88
+ return 0
89
+
90
+
91
+ if __name__ == "__main__":
92
+ raise SystemExit(main())
@@ -0,0 +1,109 @@
1
+ #!/usr/bin/env python3
2
+ """One-shot helper: add `superseded_by:` + `deprecated_in:` + warning
3
+ banner to Phase 2 atomic-command shims.
4
+
5
+ Idempotent — if a file already has `superseded_by:` set, it is skipped.
6
+ """
7
+ from __future__ import annotations
8
+ import sys
9
+ from pathlib import Path
10
+
11
+ # (file-stem, "<cluster> <sub>") — "<cluster> --flag" for flag-based
12
+ PHASE2_SHIMS: list[tuple[str, str]] = [
13
+ # chat-history cluster
14
+ ("chat-history-resume", "chat-history resume"),
15
+ ("chat-history-clear", "chat-history clear"),
16
+ ("chat-history-checkpoint", "chat-history checkpoint"),
17
+ # agents cluster
18
+ ("agents-audit", "agents audit"),
19
+ ("agents-cleanup", "agents cleanup"),
20
+ ("agents-prepare", "agents prepare"),
21
+ # memory cluster
22
+ ("memory-add", "memory add"),
23
+ ("memory-full", "memory load"),
24
+ ("memory-promote", "memory promote"),
25
+ ("propose-memory", "memory propose"),
26
+ # roadmap cluster
27
+ ("roadmap-create", "roadmap create"),
28
+ ("roadmap-execute", "roadmap execute"),
29
+ # module cluster
30
+ ("module-create", "module create"),
31
+ ("module-explore", "module explore"),
32
+ # tests cluster
33
+ ("tests-create", "tests create"),
34
+ ("tests-execute", "tests execute"),
35
+ # context cluster
36
+ ("context-create", "context create"),
37
+ ("context-refactor", "context refactor"),
38
+ # override cluster
39
+ ("override-create", "override create"),
40
+ ("override-manage", "override manage"),
41
+ # copilot-agents cluster
42
+ ("copilot-agents-init", "copilot-agents init"),
43
+ ("copilot-agents-optimize", "copilot-agents optimize"),
44
+ # judge cluster (do-and-judge / do-in-steps now sub-commands)
45
+ ("do-and-judge", "judge on-diff"),
46
+ ("do-in-steps", "judge steps"),
47
+ # commit / create-pr — flag-based clusters
48
+ ("commit-in-chunks", "commit --in-chunks"),
49
+ ("create-pr-description", "create-pr --description-only"),
50
+ ]
51
+
52
+ DEPRECATED_IN = "1.17.0"
53
+ COMMANDS_DIR = Path(".agent-src.uncompressed/commands")
54
+
55
+
56
+ def patch_file(stem: str, target: str) -> str:
57
+ path = COMMANDS_DIR / f"{stem}.md"
58
+ if not path.exists():
59
+ return f"SKIP {stem}: not found"
60
+ text = path.read_text(encoding="utf-8")
61
+ if "superseded_by:" in text.split("---", 2)[1] if text.startswith("---") else False:
62
+ return f"SKIP {stem}: already shimmed"
63
+
64
+ if not text.startswith("---\n"):
65
+ return f"SKIP {stem}: no frontmatter"
66
+ end = text.find("\n---\n", 4)
67
+ if end == -1:
68
+ return f"SKIP {stem}: malformed frontmatter"
69
+ fm_block = text[4:end]
70
+ body = text[end + len("\n---\n"):]
71
+
72
+ if "superseded_by:" in fm_block:
73
+ return f"SKIP {stem}: already shimmed"
74
+
75
+ new_fm_lines = fm_block.rstrip("\n").splitlines()
76
+ new_fm_lines.append(f"superseded_by: {target}")
77
+ new_fm_lines.append(f'deprecated_in: "{DEPRECATED_IN}"')
78
+ new_fm = "\n".join(new_fm_lines)
79
+
80
+ is_flag = target.startswith(("commit ", "create-pr "))
81
+ if is_flag:
82
+ cluster_invocation = f"/{target}"
83
+ else:
84
+ cluster_invocation = f"/{target}"
85
+ banner = (
86
+ f"> ⚠️ /{stem} is deprecated; use {cluster_invocation} instead.\n"
87
+ f"> This shim is retained for one release cycle "
88
+ f"({DEPRECATED_IN} → next minor) and forwards to the same "
89
+ f"instructions below. See "
90
+ f"[`docs/contracts/command-clusters.md`]"
91
+ f"(../../docs/contracts/command-clusters.md).\n\n"
92
+ )
93
+
94
+ new_text = f"---\n{new_fm}\n---\n\n{banner}{body.lstrip(chr(10))}"
95
+ path.write_text(new_text, encoding="utf-8")
96
+ return f"OK {stem} → {target}"
97
+
98
+
99
+ def main() -> int:
100
+ results = []
101
+ for stem, target in PHASE2_SHIMS:
102
+ results.append(patch_file(stem, target))
103
+ for r in results:
104
+ print(r)
105
+ return 0
106
+
107
+
108
+ if __name__ == "__main__":
109
+ sys.exit(main())
@@ -70,6 +70,8 @@ Commands:
70
70
  Usage: chat-history:hook --platform <claude|augment|cursor|cline|windsurf|gemini>
71
71
  chat-history:checkpoint Append a phase-boundary entry to .agent-chat-history
72
72
  (CHECKPOINT fallback for platforms without native hooks)
73
+ roadmap-progress:hook PostToolUse hook entry point (read JSON from stdin)
74
+ Regenerates roadmaps-progress.md when a tool wrote under agents/roadmaps/
73
75
  telemetry:record Append one artefact-engagement event (default-off)
74
76
  telemetry:status Print artefact-engagement telemetry status (read-only)
75
77
  telemetry:report Aggregate the engagement log into a quartile report
@@ -316,6 +318,13 @@ cmd_chat_history_hook() {
316
318
  exec python3 "$script" hook-dispatch "$@"
317
319
  }
318
320
 
321
+ cmd_roadmap_progress_hook() {
322
+ require_python3
323
+ local script
324
+ script="$(resolve_script "scripts/roadmap_progress_hook.py")" || return 1
325
+ exec python3 "$script" "$@"
326
+ }
327
+
319
328
  cmd_chat_history_checkpoint() {
320
329
  require_python3
321
330
  local script
@@ -436,6 +445,7 @@ main() {
436
445
  refine-ticket:detect) cmd_refine_ticket_detect "$@" ;;
437
446
  chat-history:hook) cmd_chat_history_hook "$@" ;;
438
447
  chat-history:checkpoint) cmd_chat_history_checkpoint "$@" ;;
448
+ roadmap-progress:hook) cmd_roadmap_progress_hook "$@" ;;
439
449
  telemetry:record) cmd_telemetry_record "$@" ;;
440
450
  telemetry:status) cmd_telemetry_status "$@" ;;
441
451
  telemetry:report) cmd_telemetry_report "$@" ;;
@@ -0,0 +1,208 @@
1
+ """Council acceptance review of Phase 0.4 2A.4 worked example.
2
+
3
+ Purpose: Phase 0.4.3 of road-to-structural-optimization.md requires a
4
+ council acceptance pass on the 2A.4 obligation-keyword-diff contract
5
+ before Phase 2A may begin. The artefact lives at
6
+ `agents/roadmaps/structural-optimization-2A4-example.md` plus two
7
+ sandbox files. Status will move from `draft` to `locked` only on
8
+ ACCEPT or ACCEPT_WITH_REVISIONS where revisions are minor.
9
+
10
+ Invocation:
11
+ .venv/bin/python -m scripts.ai_council._one_off_2a4_acceptance
12
+ """
13
+ from __future__ import annotations
14
+
15
+ import sys
16
+ from pathlib import Path
17
+
18
+ from scripts.ai_council.bundler import bundle_files
19
+ from scripts.ai_council.clients import (
20
+ AnthropicClient,
21
+ OpenAIClient,
22
+ load_anthropic_key,
23
+ load_openai_key,
24
+ )
25
+ from scripts.ai_council.orchestrator import (
26
+ CostBudget,
27
+ CouncilQuestion,
28
+ consult,
29
+ estimate,
30
+ )
31
+ from scripts.ai_council.pricing import estimate_cost, load_prices
32
+ from scripts.ai_council.project_context import detect_project_context
33
+ from scripts.ai_council.session import SessionManifest, save as save_session
34
+
35
+ REPO_ROOT = Path(__file__).resolve().parents[2]
36
+ ARTEFACTS = [
37
+ REPO_ROOT / "agents/roadmaps/structural-optimization-2A4-example.md",
38
+ REPO_ROOT / "agents/roadmaps/examples/2A4-direct-answers/direct-answers.slim.md",
39
+ REPO_ROOT / "agents/roadmaps/examples/2A4-direct-answers/direct-answers-mechanics.md",
40
+ ]
41
+
42
+ ORIGINAL_ASK = (
43
+ "Phase 0.4 of road-to-structural-optimization v3.1 dry-runs the "
44
+ "2A.4 obligation-keyword-diff contract on `direct-answers.md` to "
45
+ "lock the contract before Phase 2A begins. The artefact and two "
46
+ "sandbox files (slim rule + extracted mechanics) are presented. "
47
+ "Council task: ACCEPT / ACCEPT_WITH_REVISIONS / REJECT the "
48
+ "contract for use across the remaining 8 always-rules in Phase 2A."
49
+ )
50
+
51
+ REVIEW_PROMPT = """\
52
+ # Council Acceptance Review — 2A.4 Worked Example
53
+
54
+ ## Context
55
+
56
+ The host agent ran Phase 0.4 of `road-to-structural-optimization` v3.1: \
57
+ took one always-rule (`direct-answers.md`, smallest of the top-3), split \
58
+ it into a slim RULE+LOGIC half and a MECHANICS context, then applied \
59
+ the 2A.4 obligation-keyword diff contract. The artefact is the report \
60
+ of that dry-run; the two sandbox files are the actual produced split.
61
+
62
+ You are not asked to re-litigate the v3.1 roadmap or the choice of \
63
+ `direct-answers.md` — both were settled in earlier rounds. Verdict \
64
+ solely concerns whether the **contract** (keyword × counts × \
65
+ accept-rationale table, plus its tie-break rules) is now ready to be \
66
+ applied to the remaining 8 always-rules in Phase 2A.
67
+
68
+ ## Output Contract (STRICT)
69
+
70
+ Produce exactly these blocks in order. Be decisive — total response \
71
+ budget <= 1200 words.
72
+
73
+ ```
74
+ ### Contract correctness
75
+
76
+ **Verdict:** <ACCEPT | ACCEPT_WITH_REVISIONS | REJECT>
77
+ **Keyword extraction completeness:** <COMPLETE | PARTIAL — list missing>
78
+ **Tie-break rules sufficient:** <YES | NO — name the gap>
79
+ **Required revisions (numbered, 1-3 max, only on ACCEPT_WITH_REVISIONS):**
80
+ 1. <one sentence — smallest change>
81
+ 2. <...>
82
+ 3. <...>
83
+ ```
84
+
85
+ ```
86
+ ### Sandbox split quality
87
+
88
+ **Slim file preserves all RULE+LOGIC obligations:** <YES | NO — list lost>
89
+ **Mechanics file holds only mechanics+examples:** <YES | NO — list misplaced>
90
+ **Round-trip: rule_slim + load_context(mechanics) == original behaviour:**
91
+ <YES | NO — name the divergence>
92
+ ```
93
+
94
+ ```
95
+ ### Generalisability to remaining 8 rules
96
+
97
+ **Contract scales without per-rule tuning:** <YES | NO — name failure mode>
98
+ **Single biggest risk on the next rule (likely `non-destructive-by-default`):**
99
+ <one sentence>
100
+ ```
101
+
102
+ ```
103
+ ### Final verdict
104
+
105
+ **Lockable as-is for Phase 2A?** <YES | NO>
106
+ **If NO, single blocking change required:** <one sentence>
107
+ ```
108
+
109
+ Verdict definitions:
110
+ - **ACCEPT** — contract ships unchanged; status moves to locked.
111
+ - **ACCEPT_WITH_REVISIONS** — locks after the 1-3 listed revisions land.
112
+ - **REJECT** — contract is structurally wrong; describe the fault.
113
+
114
+ The three artefacts follow this prompt verbatim.
115
+ """
116
+
117
+
118
+ def main() -> int:
119
+ anthropic = AnthropicClient(api_key=load_anthropic_key(), model="claude-sonnet-4-5")
120
+ openai = OpenAIClient(api_key=load_openai_key(), model="gpt-4o")
121
+ members = [anthropic, openai]
122
+
123
+ context = bundle_files(ARTEFACTS)
124
+ project = detect_project_context(REPO_ROOT)
125
+ table = load_prices()
126
+
127
+ user_prompt = REVIEW_PROMPT + "\n\n---\n\n" + context.text
128
+
129
+ question = CouncilQuestion(
130
+ mode="files",
131
+ user_prompt=user_prompt,
132
+ max_tokens=3072,
133
+ )
134
+
135
+ estimates = estimate(
136
+ question, members, table, project=project, original_ask=ORIGINAL_ASK,
137
+ )
138
+ print("=== ESTIMATE (single round, max tokens) ===")
139
+ total_est = 0.0
140
+ for c, e in zip(members, estimates):
141
+ print(f" {c.name}/{c.model}: ~{e.input_tokens} in + {e.output_tokens} out = ${e.total_usd:.4f}")
142
+ total_est += e.total_usd
143
+ print(f" TOTAL per round (max): ${total_est:.4f}")
144
+ print()
145
+
146
+ budget = CostBudget(
147
+ max_input_tokens=200_000,
148
+ max_output_tokens=80_000,
149
+ max_calls=20,
150
+ max_total_usd=2.50,
151
+ )
152
+
153
+ rounds_collected: list[list] = []
154
+
155
+ def _on_round_complete(round_idx: int, round_responses) -> None:
156
+ rounds_collected.append(list(round_responses))
157
+ print(f"=== ROUND {round_idx + 1} COMPLETE ===")
158
+ for r in round_responses:
159
+ if r.error:
160
+ print(f" [error] {r.provider}/{r.model}: {r.error}")
161
+ continue
162
+ actual = estimate_cost(r.provider, r.model, r.input_tokens, r.output_tokens, table)
163
+ print(f" [done] {r.provider}/{r.model}: {r.input_tokens} in / "
164
+ f"{r.output_tokens} out · {r.latency_ms} ms · ${actual.total_usd:.4f}")
165
+ print()
166
+
167
+ print("=== CONSULT (1 round, 2A.4 acceptance review) ===")
168
+ consult(
169
+ members, question, budget,
170
+ rounds=1,
171
+ on_round_complete=_on_round_complete,
172
+ table=table, project=project, original_ask=ORIGINAL_ASK,
173
+ )
174
+
175
+ if not rounds_collected:
176
+ print("[error] no rounds completed", file=sys.stderr)
177
+ return 1
178
+
179
+ actual_total = 0.0
180
+ for round_responses in rounds_collected:
181
+ for r in round_responses:
182
+ if r.error:
183
+ continue
184
+ actual = estimate_cost(r.provider, r.model, r.input_tokens, r.output_tokens, table)
185
+ actual_total += actual.total_usd
186
+ print(f"=== TOTAL ACTUAL: ${actual_total:.4f} ===")
187
+
188
+ final_round = rounds_collected[-1]
189
+ if not [r for r in final_round if not r.error]:
190
+ return 1
191
+
192
+ manifest = SessionManifest(
193
+ mode="files",
194
+ artefact="agents/roadmaps/structural-optimization-2A4-example.md",
195
+ original_ask=ORIGINAL_ASK,
196
+ members=[f"{r.provider}/{r.model}" for r in final_round],
197
+ rounds=len(rounds_collected),
198
+ cost_usd_estimated=total_est,
199
+ cost_usd_actual=actual_total,
200
+ extra={"purpose": "Council acceptance review of Phase 0.4 2A.4 worked example"},
201
+ )
202
+ session_dir = save_session(manifest=manifest, responses=rounds_collected)
203
+ print(f"[saved] {session_dir.relative_to(REPO_ROOT)}/")
204
+ return 1 if any(r.error for round_r in rounds_collected for r in round_r) else 0
205
+
206
+
207
+ if __name__ == "__main__":
208
+ raise SystemExit(main())
@@ -0,0 +1,67 @@
1
+ """One-shot estimator for the v1 council review (no consult call).
2
+
3
+ Sibling of `_one_off_context_layer_v1_review.py`. Prints bundle size and
4
+ per-model token / cost projection so the user can confirm spend before
5
+ the actual consult fires.
6
+ """
7
+ from __future__ import annotations
8
+
9
+ from pathlib import Path
10
+
11
+ from scripts.ai_council._one_off_context_layer_v1_review import (
12
+ ORIGINAL_ASK,
13
+ REVIEW_PROMPT_HEADER,
14
+ ROADMAP_PATH,
15
+ _diff_stat,
16
+ _pr_body,
17
+ )
18
+ from scripts.ai_council.bundler import bundle_prompt
19
+ from scripts.ai_council.clients import (
20
+ AnthropicClient,
21
+ OpenAIClient,
22
+ load_anthropic_key,
23
+ load_openai_key,
24
+ )
25
+ from scripts.ai_council.orchestrator import CouncilQuestion, estimate
26
+ from scripts.ai_council.pricing import load_prices
27
+ from scripts.ai_council.project_context import detect_project_context
28
+
29
+ REPO_ROOT = Path(__file__).resolve().parents[2]
30
+
31
+
32
+ def main() -> int:
33
+ roadmap_text = ROADMAP_PATH.read_text(encoding="utf-8")
34
+ parts = [
35
+ REVIEW_PROMPT_HEADER,
36
+ "## PR #36 — diff --stat\n\n```\n" + _diff_stat() + "\n```",
37
+ "## PR #36 — body\n\n" + _pr_body(),
38
+ "## Roadmap v1\n\n" + roadmap_text,
39
+ ]
40
+ bundle_text = "\n\n---\n\n".join(parts)
41
+ print(f"Bundle bytes: {len(bundle_text.encode('utf-8'))}")
42
+
43
+ ctx = bundle_prompt(bundle_text)
44
+ project = detect_project_context(REPO_ROOT)
45
+ table = load_prices()
46
+
47
+ anthropic = AnthropicClient(api_key=load_anthropic_key(), model="claude-sonnet-4-5")
48
+ openai = OpenAIClient(api_key=load_openai_key(), model="gpt-4o")
49
+ members = [anthropic, openai]
50
+
51
+ question = CouncilQuestion(mode="prompt", user_prompt=ctx.text, max_tokens=4096)
52
+ estimates = estimate(
53
+ question, members, table, project=project, original_ask=ORIGINAL_ASK,
54
+ )
55
+ total = 0.0
56
+ for c, e in zip(members, estimates):
57
+ print(
58
+ f" {c.name}/{c.model}: ~{e.input_tokens} in + "
59
+ f"{e.output_tokens} out = ${e.total_usd:.4f}"
60
+ )
61
+ total += e.total_usd
62
+ print(f" TOTAL (max, single round): ${total:.4f}")
63
+ return 0
64
+
65
+
66
+ if __name__ == "__main__":
67
+ raise SystemExit(main())