@event4u/agent-config 1.14.0 → 1.16.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 (293) hide show
  1. package/.agent-src/commands/agent-handoff.md +1 -1
  2. package/.agent-src/commands/bug-fix.md +3 -3
  3. package/.agent-src/commands/bug-investigate.md +2 -2
  4. package/.agent-src/commands/chat-history-checkpoint.md +3 -3
  5. package/.agent-src/commands/chat-history-clear.md +2 -2
  6. package/.agent-src/commands/chat-history-resume.md +2 -2
  7. package/.agent-src/commands/chat-history.md +3 -3
  8. package/.agent-src/commands/check-current-md.md +44 -33
  9. package/.agent-src/commands/commit-in-chunks.md +43 -23
  10. package/.agent-src/commands/compress.md +34 -2
  11. package/.agent-src/commands/council-design.md +96 -0
  12. package/.agent-src/commands/council-optimize.md +115 -0
  13. package/.agent-src/commands/council-pr.md +123 -0
  14. package/.agent-src/commands/council.md +219 -0
  15. package/.agent-src/commands/create-pr.md +23 -0
  16. package/.agent-src/commands/do-and-judge.md +3 -3
  17. package/.agent-src/commands/do-in-steps.md +4 -4
  18. package/.agent-src/commands/e2e-heal.md +1 -1
  19. package/.agent-src/commands/e2e-plan.md +1 -1
  20. package/.agent-src/commands/feature-dev.md +8 -0
  21. package/.agent-src/commands/feature-explore.md +6 -1
  22. package/.agent-src/commands/feature-plan.md +33 -2
  23. package/.agent-src/commands/feature-refactor.md +5 -0
  24. package/.agent-src/commands/feature-roadmap.md +8 -3
  25. package/.agent-src/commands/feature.md +58 -0
  26. package/.agent-src/commands/fix-ci.md +5 -0
  27. package/.agent-src/commands/fix-portability.md +7 -2
  28. package/.agent-src/commands/fix-pr-bot-comments.md +5 -0
  29. package/.agent-src/commands/fix-pr-comments.md +5 -0
  30. package/.agent-src/commands/fix-pr-developer-comments.md +5 -0
  31. package/.agent-src/commands/fix-references.md +5 -0
  32. package/.agent-src/commands/fix-seeder.md +5 -0
  33. package/.agent-src/commands/fix.md +60 -0
  34. package/.agent-src/commands/jira-ticket.md +1 -1
  35. package/.agent-src/commands/judge.md +1 -1
  36. package/.agent-src/commands/memory-add.md +3 -3
  37. package/.agent-src/commands/memory-full.md +2 -2
  38. package/.agent-src/commands/memory-promote.md +2 -2
  39. package/.agent-src/commands/mode.md +5 -5
  40. package/.agent-src/commands/onboard.md +17 -8
  41. package/.agent-src/commands/optimize-agents.md +6 -1
  42. package/.agent-src/commands/optimize-augmentignore.md +14 -0
  43. package/.agent-src/commands/optimize-rtk-filters.md +5 -0
  44. package/.agent-src/commands/optimize-skills.md +6 -1
  45. package/.agent-src/commands/optimize.md +54 -0
  46. package/.agent-src/commands/propose-memory.md +2 -2
  47. package/.agent-src/commands/refine-ticket.md +9 -7
  48. package/.agent-src/commands/review-changes.md +61 -9
  49. package/.agent-src/commands/review-routing.md +1 -1
  50. package/.agent-src/commands/roadmap-create.md +42 -4
  51. package/.agent-src/commands/roadmap-execute.md +9 -7
  52. package/.agent-src/commands/set-cost-profile.md +11 -3
  53. package/.agent-src/commands/sync-agent-settings.md +11 -2
  54. package/.agent-src/commands/tests-create.md +1 -1
  55. package/.agent-src/commands/tests-execute.md +2 -3
  56. package/.agent-src/commands/upstream-contribute.md +1 -1
  57. package/.agent-src/contexts/authority/commit-mechanics.md +57 -0
  58. package/.agent-src/contexts/authority/destructive-mechanics.md +66 -0
  59. package/.agent-src/contexts/authority/scope-mechanics.md +87 -0
  60. package/.agent-src/contexts/execution/autonomy-detection.md +54 -0
  61. package/.agent-src/contexts/execution/autonomy-examples.md +90 -0
  62. package/.agent-src/contexts/execution/autonomy-mechanics.md +29 -0
  63. package/.agent-src/contexts/execution/verification-mechanics.md +80 -0
  64. package/.agent-src/personas/README.md +1 -1
  65. package/.agent-src/rules/agent-authority.md +24 -0
  66. package/.agent-src/rules/architecture.md +1 -1
  67. package/.agent-src/rules/artifact-drafting-protocol.md +1 -1
  68. package/.agent-src/rules/artifact-engagement-recording.md +2 -2
  69. package/.agent-src/rules/ask-when-uncertain.md +1 -1
  70. package/.agent-src/rules/augment-portability.md +56 -37
  71. package/.agent-src/rules/autonomous-execution.md +78 -114
  72. package/.agent-src/rules/capture-learnings.md +1 -1
  73. package/.agent-src/rules/chat-history-cadence.md +109 -0
  74. package/.agent-src/rules/chat-history-ownership.md +123 -0
  75. package/.agent-src/rules/chat-history-visibility.md +96 -0
  76. package/.agent-src/rules/cli-output-handling.md +1 -1
  77. package/.agent-src/rules/{command-suggestion.md → command-suggestion-policy.md} +10 -9
  78. package/.agent-src/rules/commit-conventions.md +1 -1
  79. package/.agent-src/rules/commit-policy.md +43 -61
  80. package/.agent-src/rules/context-hygiene.md +3 -3
  81. package/.agent-src/rules/direct-answers.md +2 -2
  82. package/.agent-src/rules/docs-sync.md +1 -1
  83. package/.agent-src/rules/e2e-testing.md +1 -1
  84. package/.agent-src/rules/guidelines.md +4 -4
  85. package/.agent-src/rules/improve-before-implement.md +2 -2
  86. package/.agent-src/rules/language-and-tone.md +41 -96
  87. package/.agent-src/rules/minimal-safe-diff.md +3 -3
  88. package/.agent-src/rules/model-recommendation.md +4 -4
  89. package/.agent-src/rules/no-cheap-questions.md +89 -0
  90. package/.agent-src/rules/non-destructive-by-default.md +25 -59
  91. package/.agent-src/rules/onboarding-gate.md +5 -5
  92. package/.agent-src/rules/review-routing-awareness.md +9 -9
  93. package/.agent-src/rules/roadmap-progress-sync.md +132 -80
  94. package/.agent-src/rules/role-mode-adherence.md +3 -3
  95. package/.agent-src/rules/scope-control.md +65 -46
  96. package/.agent-src/rules/security-sensitive-stop.md +2 -2
  97. package/.agent-src/rules/size-enforcement.md +3 -2
  98. package/.agent-src/rules/think-before-action.md +5 -5
  99. package/.agent-src/rules/token-efficiency.md +4 -4
  100. package/.agent-src/rules/{ui-audit-before-build.md → ui-audit-gate.md} +3 -3
  101. package/.agent-src/rules/user-interaction.md +31 -7
  102. package/.agent-src/rules/verify-before-complete.md +12 -67
  103. package/.agent-src/scripts/update_roadmap_progress.py +65 -8
  104. package/.agent-src/skills/ai-council/SKILL.md +333 -0
  105. package/.agent-src/skills/api-endpoint/SKILL.md +2 -2
  106. package/.agent-src/skills/blade-ui/SKILL.md +30 -11
  107. package/.agent-src/skills/blast-radius-analyzer/SKILL.md +1 -1
  108. package/.agent-src/skills/bug-analyzer/SKILL.md +1 -1
  109. package/.agent-src/skills/command-routing/SKILL.md +1 -1
  110. package/.agent-src/skills/command-writing/SKILL.md +16 -5
  111. package/.agent-src/skills/conventional-commits-writing/SKILL.md +1 -1
  112. package/.agent-src/skills/copilot-agents-optimization/SKILL.md +2 -2
  113. package/.agent-src/skills/developer-like-execution/SKILL.md +2 -2
  114. package/.agent-src/skills/existing-ui-audit/SKILL.md +24 -9
  115. package/.agent-src/skills/fe-design/SKILL.md +20 -15
  116. package/.agent-src/skills/file-editor/SKILL.md +9 -0
  117. package/.agent-src/skills/flux/SKILL.md +1 -1
  118. package/.agent-src/skills/git-workflow/SKILL.md +1 -1
  119. package/.agent-src/skills/guideline-writing/SKILL.md +11 -11
  120. package/.agent-src/skills/learning-to-rule-or-skill/SKILL.md +4 -4
  121. package/.agent-src/skills/livewire/SKILL.md +27 -8
  122. package/.agent-src/skills/override-management/SKILL.md +2 -2
  123. package/.agent-src/skills/php-coder/SKILL.md +1 -1
  124. package/.agent-src/skills/playwright-testing/SKILL.md +2 -2
  125. package/.agent-src/skills/readme-reviewer/SKILL.md +1 -1
  126. package/.agent-src/skills/readme-writing/SKILL.md +1 -1
  127. package/.agent-src/skills/readme-writing-package/SKILL.md +1 -1
  128. package/.agent-src/skills/receiving-code-review/SKILL.md +1 -1
  129. package/.agent-src/skills/refine-ticket/SKILL.md +30 -24
  130. package/.agent-src/skills/review-routing/SKILL.md +2 -2
  131. package/.agent-src/skills/roadmap-management/SKILL.md +22 -16
  132. package/.agent-src/skills/rule-writing/SKILL.md +1 -1
  133. package/.agent-src/skills/skill-reviewer/SKILL.md +1 -1
  134. package/.agent-src/skills/skill-writing/SKILL.md +6 -6
  135. package/.agent-src/skills/subagent-orchestration/SKILL.md +1 -0
  136. package/.agent-src/skills/systematic-debugging/SKILL.md +1 -1
  137. package/.agent-src/skills/upstream-contribute/SKILL.md +3 -3
  138. package/.agent-src/skills/validate-feature-fit/SKILL.md +2 -2
  139. package/.agent-src/skills/{verify-before-complete → verify-completion-evidence}/SKILL.md +2 -2
  140. package/.agent-src/templates/agent-settings.md +9 -9
  141. package/.agent-src/templates/contexts/auth-model.md +1 -1
  142. package/.agent-src/templates/roadmaps.md +9 -8
  143. package/.agent-src/templates/scripts/README.md +2 -2
  144. package/.agent-src/templates/scripts/memory_lookup.py +1 -1
  145. package/.agent-src/templates/scripts/telemetry/aggregator.py +16 -1
  146. package/.agent-src/templates/scripts/telemetry/engagement.py +59 -0
  147. package/.agent-src/templates/scripts/telemetry/report_renderer.py +28 -1
  148. package/.agent-src/templates/scripts/telemetry_record.py +14 -1
  149. package/.agent-src/templates/scripts/work_engine/__init__.py +2 -2
  150. package/.agent-src/templates/scripts/work_engine/cli.py +64 -461
  151. package/.agent-src/templates/scripts/work_engine/cli_args.py +116 -0
  152. package/.agent-src/templates/scripts/work_engine/delivery_state.py +3 -3
  153. package/.agent-src/templates/scripts/work_engine/directives/backend/__init__.py +1 -1
  154. package/.agent-src/templates/scripts/work_engine/directives/backend/implement.py +1 -1
  155. package/.agent-src/templates/scripts/work_engine/directives/backend/memory.py +1 -1
  156. package/.agent-src/templates/scripts/work_engine/directives/backend/plan.py +1 -1
  157. package/.agent-src/templates/scripts/work_engine/directives/backend/report.py +1 -1
  158. package/.agent-src/templates/scripts/work_engine/dispatcher.py +1 -1
  159. package/.agent-src/templates/scripts/work_engine/emitters.py +43 -0
  160. package/.agent-src/templates/scripts/work_engine/errors.py +19 -0
  161. package/.agent-src/templates/scripts/work_engine/hook_bootstrap.py +76 -0
  162. package/.agent-src/templates/scripts/work_engine/input_builders.py +163 -0
  163. package/.agent-src/templates/scripts/work_engine/migration/v0_to_v1.py +34 -2
  164. package/.agent-src/templates/scripts/work_engine/persona_policy.py +1 -1
  165. package/.agent-src/templates/scripts/work_engine/resolvers/prompt.py +1 -1
  166. package/.agent-src/templates/scripts/work_engine/state_io.py +202 -0
  167. package/.claude-plugin/marketplace.json +10 -2
  168. package/AGENTS.md +16 -12
  169. package/CHANGELOG.md +206 -9
  170. package/README.md +51 -52
  171. package/config/agent-settings.template.yml +58 -1
  172. package/config/gitignore-block.txt +3 -0
  173. package/docs/MIGRATION.md +122 -0
  174. package/docs/architecture.md +83 -34
  175. package/docs/catalog.md +331 -0
  176. package/docs/contracts/STABILITY.md +134 -0
  177. package/docs/contracts/adr-chat-history-split.md +132 -0
  178. package/docs/contracts/adr-command-suggestion.md +146 -0
  179. package/docs/contracts/adr-implement-ticket-runtime.md +122 -0
  180. package/docs/contracts/adr-product-ui-track.md +384 -0
  181. package/docs/contracts/adr-prompt-driven-execution.md +187 -0
  182. package/docs/contracts/agent-memory-contract.md +149 -0
  183. package/docs/contracts/artifact-engagement-flow.md +262 -0
  184. package/docs/contracts/command-clusters.md +126 -0
  185. package/docs/contracts/command-suggestion-flow.md +148 -0
  186. package/docs/contracts/implement-ticket-flow.md +628 -0
  187. package/docs/contracts/linear-ai-rules-inclusion.md +143 -0
  188. package/docs/contracts/linear-ai-three-layers.md +131 -0
  189. package/docs/contracts/load-context-schema.md +186 -0
  190. package/docs/contracts/rule-interactions.md +107 -0
  191. package/docs/contracts/rule-interactions.yml +238 -0
  192. package/docs/contracts/rule-priority-hierarchy.md +87 -0
  193. package/docs/contracts/ui-stack-extension.md +236 -0
  194. package/docs/contracts/ui-track-flow.md +338 -0
  195. package/docs/customization.md +14 -0
  196. package/docs/end-to-end-walkthroughs.md +165 -0
  197. package/docs/getting-started.md +27 -9
  198. package/docs/github-topics.md +12 -3
  199. package/docs/guidelines/agent-infra/language-and-tone-examples.md +79 -0
  200. package/{.agent-src → docs}/guidelines/docs/readme-size-and-splitting.md +26 -25
  201. package/docs/guidelines/php/git.md +164 -0
  202. package/docs/installation.md +42 -6
  203. package/docs/migrations/commands-1.15.0.md +112 -0
  204. package/docs/showcase.md +9 -4
  205. package/docs/skills-catalog.md +14 -8
  206. package/docs/ui-track-mental-model.md +121 -0
  207. package/llms.txt +13 -7
  208. package/package.json +1 -1
  209. package/scripts/agent-config +23 -0
  210. package/scripts/ai_council/__init__.py +39 -0
  211. package/scripts/ai_council/_default_prices.py +41 -0
  212. package/scripts/ai_council/_one_off_rebalancing_audit.py +149 -0
  213. package/scripts/ai_council/_one_off_roundtrip.py +106 -0
  214. package/scripts/ai_council/budget_guard.py +172 -0
  215. package/scripts/ai_council/bundler.py +261 -0
  216. package/scripts/ai_council/clients.py +381 -0
  217. package/scripts/ai_council/modes.py +127 -0
  218. package/scripts/ai_council/orchestrator.py +350 -0
  219. package/scripts/ai_council/pricing.py +213 -0
  220. package/scripts/ai_council/project_context.py +159 -0
  221. package/scripts/ai_council/prompts.py +232 -0
  222. package/scripts/ai_council/session.py +144 -0
  223. package/scripts/build_linear_digest.py +4 -4
  224. package/scripts/check_always_budget.py +126 -0
  225. package/scripts/check_augmentignore.py +69 -0
  226. package/scripts/check_command_count_messaging.py +120 -0
  227. package/scripts/check_portability.py +57 -0
  228. package/scripts/check_public_catalog_links.py +122 -0
  229. package/scripts/check_public_links.py +185 -0
  230. package/scripts/check_references.py +5 -1
  231. package/scripts/check_roadmap_trackable.py +111 -0
  232. package/scripts/command_suggester/cooldown.py +1 -1
  233. package/scripts/generate_index.py +266 -0
  234. package/scripts/install_anthropic_key.sh +5 -0
  235. package/scripts/install_openai_key.sh +106 -0
  236. package/scripts/lint_load_context.py +163 -0
  237. package/scripts/lint_no_new_atomic_commands.py +179 -0
  238. package/scripts/lint_rule_interactions.py +149 -0
  239. package/scripts/memory_lookup.py +1 -1
  240. package/scripts/release.py +297 -64
  241. package/scripts/schemas/command.schema.json +20 -0
  242. package/scripts/schemas/rule.schema.json +10 -0
  243. package/scripts/skill_linter.py +26 -4
  244. package/scripts/sync_agent_settings.py +1 -1
  245. package/scripts/update_counts.py +19 -4
  246. package/scripts/update_prices.py +124 -0
  247. package/.agent-src/guidelines/php/git.md +0 -96
  248. package/.agent-src/rules/chat-history.md +0 -200
  249. /package/.agent-src/rules/{slash-commands.md → slash-command-routing-policy.md} +0 -0
  250. /package/{.agent-src → docs}/guidelines/agent-infra/agent-interaction-and-decision-quality.md +0 -0
  251. /package/{.agent-src → docs}/guidelines/agent-infra/break-glass-usage.md +0 -0
  252. /package/{.agent-src → docs}/guidelines/agent-infra/developer-judgment.md +0 -0
  253. /package/{.agent-src → docs}/guidelines/agent-infra/engineering-memory-data-format.md +0 -0
  254. /package/{.agent-src → docs}/guidelines/agent-infra/layered-settings.md +0 -0
  255. /package/{.agent-src → docs}/guidelines/agent-infra/memory-access.md +0 -0
  256. /package/{.agent-src → docs}/guidelines/agent-infra/naming.md +0 -0
  257. /package/{.agent-src → docs}/guidelines/agent-infra/output-patterns.md +0 -0
  258. /package/{.agent-src → docs}/guidelines/agent-infra/review-routing-data-format.md +0 -0
  259. /package/{.agent-src → docs}/guidelines/agent-infra/role-contracts.md +0 -0
  260. /package/{.agent-src → docs}/guidelines/agent-infra/role-mode-router.md +0 -0
  261. /package/{.agent-src → docs}/guidelines/agent-infra/runtime-layer.md +0 -0
  262. /package/{.agent-src → docs}/guidelines/agent-infra/self-improvement-pipeline.md +0 -0
  263. /package/{.agent-src → docs}/guidelines/agent-infra/size-and-scope.md +0 -0
  264. /package/{.agent-src → docs}/guidelines/agent-infra/tool-integration.md +0 -0
  265. /package/{.agent-src → docs}/guidelines/e2e/playwright.md +0 -0
  266. /package/{.agent-src → docs}/guidelines/php/api-design.md +0 -0
  267. /package/{.agent-src → docs}/guidelines/php/artisan-commands.md +0 -0
  268. /package/{.agent-src → docs}/guidelines/php/blade-ui.md +0 -0
  269. /package/{.agent-src → docs}/guidelines/php/controllers.md +0 -0
  270. /package/{.agent-src → docs}/guidelines/php/database.md +0 -0
  271. /package/{.agent-src → docs}/guidelines/php/eloquent.md +0 -0
  272. /package/{.agent-src → docs}/guidelines/php/flux.md +0 -0
  273. /package/{.agent-src → docs}/guidelines/php/general.md +0 -0
  274. /package/{.agent-src → docs}/guidelines/php/jobs.md +0 -0
  275. /package/{.agent-src → docs}/guidelines/php/livewire.md +0 -0
  276. /package/{.agent-src → docs}/guidelines/php/logging.md +0 -0
  277. /package/{.agent-src → docs}/guidelines/php/naming.md +0 -0
  278. /package/{.agent-src → docs}/guidelines/php/patterns/dependency-injection.md +0 -0
  279. /package/{.agent-src → docs}/guidelines/php/patterns/dtos.md +0 -0
  280. /package/{.agent-src → docs}/guidelines/php/patterns/events.md +0 -0
  281. /package/{.agent-src → docs}/guidelines/php/patterns/factory.md +0 -0
  282. /package/{.agent-src → docs}/guidelines/php/patterns/pipelines.md +0 -0
  283. /package/{.agent-src → docs}/guidelines/php/patterns/policies.md +0 -0
  284. /package/{.agent-src → docs}/guidelines/php/patterns/repositories.md +0 -0
  285. /package/{.agent-src → docs}/guidelines/php/patterns/service-layer.md +0 -0
  286. /package/{.agent-src → docs}/guidelines/php/patterns/strategy.md +0 -0
  287. /package/{.agent-src → docs}/guidelines/php/patterns.md +0 -0
  288. /package/{.agent-src → docs}/guidelines/php/performance.md +0 -0
  289. /package/{.agent-src → docs}/guidelines/php/resources.md +0 -0
  290. /package/{.agent-src → docs}/guidelines/php/security.md +0 -0
  291. /package/{.agent-src → docs}/guidelines/php/sql.md +0 -0
  292. /package/{.agent-src → docs}/guidelines/php/validations.md +0 -0
  293. /package/{.agent-src → docs}/guidelines/php/websocket.md +0 -0
@@ -0,0 +1,69 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Advisory check for `.augmentignore` (road-to-governance-cleanup F6.3).
4
+
5
+ Runs as part of `task ci` to surface `/optimize augmentignore` as a
6
+ periodic reminder. Always exits 0 — this is a warn-only advisory, not
7
+ a gate. Failures here never block CI.
8
+
9
+ Checks performed:
10
+ 1. Does `.augmentignore` exist at repo root?
11
+ 2. Is its mtime older than 90 days? (stale reminder)
12
+ 3. Is it suspiciously short (<5 non-blank, non-comment lines)?
13
+
14
+ If any check trips, prints a friendly hint and exits 0. If all clean,
15
+ prints a single-line OK and exits 0.
16
+ """
17
+ from __future__ import annotations
18
+
19
+ import sys
20
+ import time
21
+ from pathlib import Path
22
+
23
+ STALE_DAYS = 90
24
+ MIN_USEFUL_LINES = 5
25
+ REPO_ROOT = Path(__file__).resolve().parent.parent
26
+
27
+
28
+ def check() -> int:
29
+ target = REPO_ROOT / ".augmentignore"
30
+ notes: list[str] = []
31
+
32
+ if not target.exists():
33
+ notes.append("⚠️ .augmentignore is missing — run `/optimize augmentignore` to scaffold it.")
34
+ _emit(notes)
35
+ return 0
36
+
37
+ age_days = (time.time() - target.stat().st_mtime) / 86400
38
+ if age_days > STALE_DAYS:
39
+ notes.append(
40
+ f"ℹ️ .augmentignore is {int(age_days)} days old (threshold: {STALE_DAYS}) — "
41
+ "consider running `/optimize augmentignore` to refresh."
42
+ )
43
+
44
+ useful = [
45
+ ln for ln in target.read_text().splitlines()
46
+ if ln.strip() and not ln.strip().startswith("#")
47
+ ]
48
+ if len(useful) < MIN_USEFUL_LINES:
49
+ notes.append(
50
+ f"ℹ️ .augmentignore has only {len(useful)} active entries — "
51
+ "run `/optimize augmentignore` to detect tech-stack ignores you may be missing."
52
+ )
53
+
54
+ _emit(notes)
55
+ return 0
56
+
57
+
58
+ def _emit(notes: list[str]) -> None:
59
+ if not notes:
60
+ print("✅ .augmentignore advisory: nothing to suggest.")
61
+ return
62
+ print("📒 .augmentignore advisory (non-blocking):")
63
+ for n in notes:
64
+ print(f" {n}")
65
+ print(" (This is a reminder, not a CI failure.)")
66
+
67
+
68
+ if __name__ == "__main__":
69
+ sys.exit(check())
@@ -0,0 +1,120 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Command-count messaging gate (regression guard for road-to-pr-34-followups 1.2).
4
+
5
+ Public surfaces (README.md, AGENTS.md, docs/getting-started.md) advertise
6
+ the size of the command catalog. PR #34 collapses atomic commands into
7
+ clusters via deprecation shims — the externally meaningful number is the
8
+ **active** command count (non-shim files), not the raw file count. This
9
+ gate sources canonical counts from `.agent-src.uncompressed/commands/`
10
+ frontmatter and fails when any documented number drifts from those.
11
+
12
+ Canonical counts:
13
+ total = number of *.md files under .agent-src.uncompressed/commands/
14
+ shims = files whose frontmatter declares `superseded_by:`
15
+ active = total - shims
16
+
17
+ Patterns checked (per file):
18
+
19
+ README.md
20
+ hero row "<strong>{N} Commands</strong>" → active
21
+ browse line "Browse all {N} active commands" → active
22
+ browse meta "{N} files total" → total
23
+ browse meta "{N} are deprecation shims" → shims
24
+ tools blurb "{N} native commands" → active
25
+
26
+ AGENTS.md
27
+ tree "commands/ ({N} files — {A} active + {S} deprecation shims)"
28
+
29
+ docs/getting-started.md
30
+ browse line "Browse all {N} active commands" → active
31
+
32
+ Exit codes: 0 = clean, 1 = drift detected.
33
+ """
34
+
35
+ from __future__ import annotations
36
+
37
+ import re
38
+ import sys
39
+ from pathlib import Path
40
+
41
+ ROOT = Path(__file__).resolve().parent.parent
42
+ COMMANDS_DIR = ROOT / ".agent-src.uncompressed" / "commands"
43
+ README = ROOT / "README.md"
44
+ AGENTS = ROOT / "AGENTS.md"
45
+ GETTING_STARTED = ROOT / "docs" / "getting-started.md"
46
+
47
+ FM_RE = re.compile(r"^---\s*\n(.*?)\n---", re.DOTALL)
48
+ SUPERSEDED_RE = re.compile(r"^superseded_by:\s*\S", re.MULTILINE)
49
+
50
+
51
+ def canonical_counts() -> tuple[int, int, int]:
52
+ if not COMMANDS_DIR.is_dir():
53
+ print(f"❌ {COMMANDS_DIR.relative_to(ROOT)} not found", file=sys.stderr)
54
+ sys.exit(1)
55
+ total = shims = 0
56
+ for f in COMMANDS_DIR.glob("*.md"):
57
+ total += 1
58
+ m = FM_RE.match(f.read_text(encoding="utf-8"))
59
+ fm = m.group(1) if m else ""
60
+ if SUPERSEDED_RE.search(fm):
61
+ shims += 1
62
+ return total, shims, total - shims
63
+
64
+
65
+ def _check(path: Path, pattern: str, expected: int, label: str) -> str | None:
66
+ if not path.exists():
67
+ return f"missing file: {path.relative_to(ROOT)}"
68
+ m = re.search(pattern, path.read_text(encoding="utf-8"))
69
+ if not m:
70
+ return f"{path.relative_to(ROOT)}: pattern not found for `{label}` — /{pattern}/"
71
+ found = int(m.group(1))
72
+ if found != expected:
73
+ return f"{path.relative_to(ROOT)}: `{label}` says {found}, expected {expected}"
74
+ return None
75
+
76
+
77
+ def main() -> int:
78
+ total, shims, active = canonical_counts()
79
+ print(f"Canonical counts: {total} files · {shims} shims · {active} active")
80
+
81
+ checks = [
82
+ # README.md
83
+ (README, r"<strong>(\d+) Commands</strong>", active, "hero row"),
84
+ (README, r"Browse all (\d+) active commands", active, "browse line"),
85
+ (README, r"\((\d+) files total ", total, "browse meta · total files"),
86
+ (README, r"— (\d+) are deprecation shims", shims, "browse meta · shims"),
87
+ (README, r"\+ (\d+) native commands\)", active, "tools blurb"),
88
+ # AGENTS.md (`commands/ (84 files — 69 active + 15 deprecation shims)`)
89
+ (AGENTS, r"commands/\s+\((\d+) files —", total, "tree · total files"),
90
+ (AGENTS, r"files — (\d+) active", active, "tree · active"),
91
+ (AGENTS, r"active \+ (\d+) deprecation shims", shims, "tree · shims"),
92
+ # docs/getting-started.md
93
+ (GETTING_STARTED, r"Browse all (\d+) active commands", active, "browse line"),
94
+ ]
95
+
96
+ errors: list[str] = []
97
+ for path, pattern, expected, label in checks:
98
+ err = _check(path, pattern, expected, label)
99
+ if err:
100
+ errors.append(err)
101
+
102
+ if not errors:
103
+ print("✅ All command-count messaging in sync with registry.")
104
+ return 0
105
+
106
+ print(f"❌ Command-count messaging drift — {len(errors)} mismatch(es):")
107
+ for e in errors:
108
+ print(f" {e}")
109
+ print(
110
+ "\nFix: update the documented numbers above, or run "
111
+ "`task check-command-count` after editing."
112
+ )
113
+ print(
114
+ "Why this gate exists: see `agents/roadmaps/road-to-pr-34-followups.md` § 1.2."
115
+ )
116
+ return 1
117
+
118
+
119
+ if __name__ == "__main__":
120
+ sys.exit(main())
@@ -157,6 +157,8 @@ ALLOWLIST = [
157
157
  r"agent-config", # refers to the package concept, not a specific project
158
158
  r"shared.*package", # "shared package" concept
159
159
  r"package repository", # "package repository" concept
160
+ r"scripts/mcp_server/", # MCP server module path (road-to-mcp-server.md Phase 1)
161
+ r"scripts\.mcp_server", # MCP server Python module entrypoint
160
162
  ]
161
163
 
162
164
  # Directories to scan (only package files, not project-specific agents/)
@@ -248,6 +250,55 @@ def check_file(filepath: Path, patterns: list, allowlist: list) -> List[Violatio
248
250
  return violations
249
251
 
250
252
 
253
+ # ── Identity-framing detector ───────────────────────────────────────────
254
+ # The package's public identity surface (README, AGENTS, copilot-instructions)
255
+ # must read stack-neutral. Laravel is the deepest reference stack today, never
256
+ # the headline. This detector flags banned phrases that elevate any single
257
+ # stack to identity status. Source-of-truth list lives in the
258
+ # road-to-1-15-followups.md roadmap (P0 #1, F1.5).
259
+ _IDENTITY_FRAMING_PATTERNS: list[tuple[re.Pattern, str]] = [
260
+ (re.compile(r"\bLaravel-first\b", re.IGNORECASE), "identity-laravel-first"),
261
+ (re.compile(r"\bfor\s+PHP\s*/\s*Laravel\s+teams?\b", re.IGNORECASE), "identity-for-php-laravel-teams"),
262
+ (re.compile(r"\bfor\s+Laravel\s+teams?\b", re.IGNORECASE), "identity-for-laravel-teams"),
263
+ (re.compile(r"\bprimary\s+audience\s*[:=]\s*Laravel\b", re.IGNORECASE), "identity-primary-audience-laravel"),
264
+ (re.compile(r"\bbuilt\s+for\s+Laravel\b", re.IGNORECASE), "identity-built-for-laravel"),
265
+ (re.compile(r"\bLaravel\s*=\s*primary\b", re.IGNORECASE), "identity-laravel-equals-primary"),
266
+ (re.compile(r"\*\*Reference\s+implementation:\s*Laravel\.?\*\*", re.IGNORECASE), "identity-reference-implementation-laravel"),
267
+ ]
268
+
269
+ # Files whose identity framing must stay stack-neutral. Relative to repo root.
270
+ IDENTITY_SCAN_FILES = [
271
+ "README.md",
272
+ "AGENTS.md",
273
+ ".github/copilot-instructions.md",
274
+ ]
275
+
276
+
277
+ def check_identity_framing(filepath: Path) -> List[Violation]:
278
+ """Flag banned identity-framing phrases in README / AGENTS / copilot-instructions.
279
+
280
+ The package presents itself as a universal governance system; any phrase
281
+ that pins identity to a single stack (Laravel-first, built for Laravel,
282
+ Reference implementation: Laravel as a bolded headline) is a regression.
283
+ """
284
+ violations: List[Violation] = []
285
+ try:
286
+ lines = filepath.read_text(encoding="utf-8").splitlines()
287
+ except Exception:
288
+ return violations
289
+
290
+ for i, line in enumerate(lines, 1):
291
+ for pattern, name in _IDENTITY_FRAMING_PATTERNS:
292
+ m = pattern.search(line)
293
+ if m:
294
+ violations.append(Violation(
295
+ file=str(filepath), line=i, match=m.group(0),
296
+ pattern_name=name, severity="error",
297
+ context=line.strip(),
298
+ ))
299
+ return violations
300
+
301
+
251
302
  # ── Task-command detector ───────────────────────────────────────────────
252
303
  # Artefact files shipped in the package must not reference `task <name>`
253
304
  # invocations (per augment-portability rule). Consumer projects may not
@@ -465,6 +516,12 @@ def scan_all(root: Path) -> tuple[List[Violation], list[str]]:
465
516
  if not any(path_str.endswith(skip) for skip in _CLI_DETECTOR_SKIP):
466
517
  violations.extend(check_cli_invocations(f))
467
518
 
519
+ # Layer 5: identity-framing scan on the public identity surface
520
+ for rel in IDENTITY_SCAN_FILES:
521
+ f = root / rel
522
+ if f.is_file():
523
+ violations.extend(check_identity_framing(f))
524
+
468
525
  return violations, detected
469
526
 
470
527
 
@@ -0,0 +1,122 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Public-catalog link checker (regression guard for road-to-pr-34-followups 1.1).
4
+
5
+ `docs/catalog.md` is the consumer-facing catalog rendered by
6
+ `scripts/generate_index.py`. Consumers receive the package via npm /
7
+ Composer / archive surfaces — `.agent-src.uncompressed/` is **not**
8
+ shipped (see `package.json#files`). Every link in the public catalog
9
+ must therefore resolve to a shipped surface.
10
+
11
+ Checks:
12
+ 1. No link href contains `.agent-src.uncompressed/`.
13
+ 2. Every link href resolves on disk.
14
+ 3. Every link href starts with a path declared in `package.json#files`
15
+ (or one of the always-shipped root files).
16
+
17
+ Exit codes: 0 = clean, 1 = violations found.
18
+
19
+ Usage:
20
+ python3 scripts/check_public_catalog_links.py
21
+ """
22
+
23
+ from __future__ import annotations
24
+
25
+ import json
26
+ import re
27
+ import sys
28
+ from pathlib import Path
29
+
30
+ ROOT = Path(__file__).resolve().parent.parent
31
+ CATALOG = ROOT / "docs" / "catalog.md"
32
+ PACKAGE_JSON = ROOT / "package.json"
33
+
34
+ LINK_RE = re.compile(r"\]\((?P<href>[^)\s]+)(?:\s+\"[^\"]*\")?\)")
35
+ FORBIDDEN_PREFIX = ".agent-src.uncompressed/"
36
+
37
+
38
+ def _shipped_roots() -> tuple[set[str], set[str]]:
39
+ """Return (shipped_dirs, shipped_files) from package.json#files."""
40
+ data = json.loads(PACKAGE_JSON.read_text(encoding="utf-8"))
41
+ dirs: set[str] = set()
42
+ files: set[str] = set()
43
+ for entry in data.get("files", []):
44
+ if entry.endswith("/"):
45
+ dirs.add(entry.rstrip("/"))
46
+ else:
47
+ files.add(entry)
48
+ return dirs, files
49
+
50
+
51
+ def _resolve(href: str) -> Path | None:
52
+ href = href.split("#", 1)[0]
53
+ if not href or href.startswith(("http://", "https://", "mailto:", "tel:")):
54
+ return None
55
+ target = (CATALOG.parent / href).resolve()
56
+ try:
57
+ return target.relative_to(ROOT.resolve())
58
+ except ValueError:
59
+ return None
60
+
61
+
62
+ def _under_shipped_surface(rel: Path, dirs: set[str], files: set[str]) -> bool:
63
+ s = str(rel)
64
+ if s in files:
65
+ return True
66
+ return any(s == d or s.startswith(d + "/") for d in dirs)
67
+
68
+
69
+ def main() -> int:
70
+ if not CATALOG.exists():
71
+ print(f"❌ {CATALOG.relative_to(ROOT)} not found")
72
+ return 1
73
+
74
+ dirs, files = _shipped_roots()
75
+ text = CATALOG.read_text(encoding="utf-8")
76
+
77
+ forbidden: list[tuple[int, str]] = []
78
+ missing: list[tuple[int, str]] = []
79
+ unshipped: list[tuple[int, str]] = []
80
+
81
+ for lineno, line in enumerate(text.splitlines(), 1):
82
+ for m in LINK_RE.finditer(line):
83
+ href = m.group("href")
84
+ if FORBIDDEN_PREFIX in href:
85
+ forbidden.append((lineno, href))
86
+ continue
87
+ rel = _resolve(href)
88
+ if rel is None:
89
+ continue # external / non-resolvable
90
+ if not (ROOT / rel).exists():
91
+ missing.append((lineno, href))
92
+ continue
93
+ if not _under_shipped_surface(rel, dirs, files):
94
+ unshipped.append((lineno, href))
95
+
96
+ total_violations = len(forbidden) + len(missing) + len(unshipped)
97
+ if not total_violations:
98
+ print(f"✅ docs/catalog.md — all links resolve to shipped surfaces.")
99
+ return 0
100
+
101
+ print(f"❌ docs/catalog.md — {total_violations} violation(s):")
102
+ if forbidden:
103
+ print(f"\n {len(forbidden)} link(s) point at unshipped `.agent-src.uncompressed/`:")
104
+ for ln, href in forbidden[:10]:
105
+ print(f" line {ln}: {href}")
106
+ if len(forbidden) > 10:
107
+ print(f" … and {len(forbidden) - 10} more")
108
+ if missing:
109
+ print(f"\n {len(missing)} link(s) do not resolve on disk:")
110
+ for ln, href in missing[:10]:
111
+ print(f" line {ln}: {href}")
112
+ if unshipped:
113
+ print(f"\n {len(unshipped)} link(s) point outside `package.json#files`:")
114
+ for ln, href in unshipped[:10]:
115
+ print(f" line {ln}: {href}")
116
+ print("\nFix: update `scripts/generate_index.py` _to_shipped_path() / catalog renderer,")
117
+ print("then re-run `python3 scripts/generate_index.py`.")
118
+ return 1
119
+
120
+
121
+ if __name__ == "__main__":
122
+ sys.exit(main())
@@ -0,0 +1,185 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Public-link checker for the agent-config public surface.
4
+
5
+ Scans the public-surface files (README.md, AGENTS.md, docs/architecture.md)
6
+ for markdown links into `docs/contracts/`, then validates each link against
7
+ the `stability:` frontmatter declared by the target file (per
8
+ `docs/contracts/STABILITY.md`).
9
+
10
+ Rules:
11
+ - target stability=stable → OK (no marker required).
12
+ - target stability=beta → OK; warns if surrounding text has no
13
+ visible "(beta)" marker.
14
+ - target stability=experimental → ERROR. Public surface MUST NOT link
15
+ to experimental contracts.
16
+ - target outside docs/contracts/ but referenced for contract-shaped
17
+ intent (links into agents/contexts/*.md from public files) → ERROR.
18
+ - target file missing → ERROR.
19
+ - target file under docs/contracts/ without `stability:` frontmatter
20
+ (except STABILITY.md itself) → ERROR.
21
+
22
+ Exit codes: 0 = clean, 1 = violations found, 3 = internal error.
23
+
24
+ Usage:
25
+ python3 scripts/check_public_links.py
26
+ python3 scripts/check_public_links.py --list # list contracts + levels
27
+ python3 scripts/check_public_links.py --json # machine-readable
28
+ """
29
+
30
+ from __future__ import annotations
31
+
32
+ import argparse
33
+ import json
34
+ import re
35
+ import sys
36
+ from dataclasses import dataclass, asdict
37
+ from pathlib import Path
38
+
39
+ ROOT = Path(__file__).resolve().parent.parent
40
+ PUBLIC_FILES = [Path("README.md"), Path("AGENTS.md"), Path("docs/architecture.md")]
41
+ CONTRACTS_DIR = Path("docs/contracts")
42
+ STABILITY_FILE = CONTRACTS_DIR / "STABILITY.md"
43
+
44
+ LINK_RE = re.compile(r"\[(?P<text>[^\]]+)\]\((?P<href>[^)\s]+)(?:\s+\"[^\"]*\")?\)")
45
+ FRONTMATTER_RE = re.compile(r"^---\s*\n(.*?)\n---\s*\n", re.DOTALL)
46
+ STABILITY_RE = re.compile(r"^stability:\s*(\w+)\s*$", re.MULTILINE)
47
+
48
+
49
+ @dataclass
50
+ class Violation:
51
+ file: str
52
+ line: int
53
+ href: str
54
+ reason: str
55
+ severity: str # "error" | "warning"
56
+
57
+
58
+ def read_stability(path: Path) -> str | None:
59
+ if not path.exists():
60
+ return None
61
+ txt = path.read_text(encoding="utf-8")
62
+ m = FRONTMATTER_RE.match(txt)
63
+ if not m:
64
+ return None
65
+ sm = STABILITY_RE.search(m.group(1))
66
+ return sm.group(1) if sm else None
67
+
68
+
69
+ def collect_contracts() -> dict[Path, str | None]:
70
+ out: dict[Path, str | None] = {}
71
+ for p in sorted((ROOT / CONTRACTS_DIR).glob("*.md")):
72
+ rel = p.relative_to(ROOT)
73
+ out[rel] = read_stability(p)
74
+ return out
75
+
76
+
77
+ def resolve(public_file: Path, href: str) -> Path | None:
78
+ href = href.split("#", 1)[0]
79
+ if not href or href.startswith(("http://", "https://", "mailto:", "tel:")):
80
+ return None
81
+ if href.startswith("/"):
82
+ return Path(href.lstrip("/"))
83
+ return (public_file.parent / href).resolve().relative_to(ROOT.resolve())
84
+
85
+
86
+ def scan_file(public_file: Path, contracts: dict[Path, str | None]) -> list[Violation]:
87
+ abs_path = ROOT / public_file
88
+ if not abs_path.exists():
89
+ return []
90
+ violations: list[Violation] = []
91
+ for lineno, line in enumerate(abs_path.read_text(encoding="utf-8").splitlines(), 1):
92
+ for m in LINK_RE.finditer(line):
93
+ href = m.group("href")
94
+ text = m.group("text")
95
+ try:
96
+ target = resolve(public_file, href)
97
+ except ValueError:
98
+ continue
99
+ if target is None:
100
+ continue
101
+ if target.parts[:2] == ("agents", "contexts") and target.suffix == ".md":
102
+ violations.append(Violation(str(public_file), lineno, href,
103
+ "public surface MUST NOT link into agents/contexts/ — move target to docs/contracts/",
104
+ "error"))
105
+ continue
106
+ if target.parts[:2] != ("docs", "contracts") or target.suffix != ".md":
107
+ continue
108
+ if target == STABILITY_FILE:
109
+ continue
110
+ if target not in contracts:
111
+ violations.append(Violation(str(public_file), lineno, href,
112
+ f"target not found: {target}", "error"))
113
+ continue
114
+ level = contracts[target]
115
+ if level is None:
116
+ violations.append(Violation(str(public_file), lineno, href,
117
+ f"target missing 'stability:' frontmatter: {target}", "error"))
118
+ continue
119
+ if level == "experimental":
120
+ violations.append(Violation(str(public_file), lineno, href,
121
+ f"public surface MUST NOT link to experimental contract: {target}",
122
+ "error"))
123
+ continue
124
+ if level == "beta":
125
+ window = line.lower()
126
+ if "(beta)" not in window and "[beta]" not in window:
127
+ violations.append(Violation(str(public_file), lineno, href,
128
+ f"link to beta contract '{target}' lacks visible (beta) marker",
129
+ "warning"))
130
+ return violations
131
+
132
+
133
+ def main() -> int:
134
+ ap = argparse.ArgumentParser()
135
+ ap.add_argument("--list", action="store_true", help="list contracts + stability levels")
136
+ ap.add_argument("--json", action="store_true", help="machine-readable output")
137
+ ap.add_argument("--strict", action="store_true",
138
+ help="fail on warnings as well as errors (default: errors only)")
139
+ args = ap.parse_args()
140
+
141
+ contracts = collect_contracts()
142
+ if args.list:
143
+ for p, lvl in contracts.items():
144
+ print(f" {lvl or '(no frontmatter)':14} {p}")
145
+ return 0
146
+
147
+ missing_fm = [p for p, lvl in contracts.items() if lvl is None and p != STABILITY_FILE]
148
+ violations: list[Violation] = []
149
+ for p in missing_fm:
150
+ violations.append(Violation(str(p), 0, "(self)",
151
+ "missing 'stability:' frontmatter required by docs/contracts/STABILITY.md",
152
+ "error"))
153
+ for f in PUBLIC_FILES:
154
+ violations.extend(scan_file(f, contracts))
155
+
156
+ if args.json:
157
+ print(json.dumps([asdict(v) for v in violations], indent=2))
158
+ else:
159
+ errors = [v for v in violations if v.severity == "error"]
160
+ warnings = [v for v in violations if v.severity == "warning"]
161
+ for v in violations:
162
+ icon = "❌" if v.severity == "error" else "⚠️ "
163
+ loc = f"{v.file}:{v.line}" if v.line else v.file
164
+ print(f"{icon} {loc} {v.href}\n → {v.reason}")
165
+ if not violations:
166
+ print(f"✅ public-link check clean — {len(contracts)} contracts scanned, "
167
+ f"{len(PUBLIC_FILES)} public files clean")
168
+ else:
169
+ print(f"\nsummary: {len(errors)} error(s), {len(warnings)} warning(s)")
170
+
171
+ has_errors = any(v.severity == "error" for v in violations)
172
+ has_warnings = any(v.severity == "warning" for v in violations)
173
+ if has_errors:
174
+ return 1
175
+ if has_warnings and args.strict:
176
+ return 1
177
+ return 0
178
+
179
+
180
+ if __name__ == "__main__":
181
+ try:
182
+ sys.exit(main())
183
+ except Exception as e:
184
+ print(f"❌ internal error: {e}", file=sys.stderr)
185
+ sys.exit(3)
@@ -32,7 +32,10 @@ class BrokenRef:
32
32
 
33
33
 
34
34
  SCAN_DIRS = [".agent-src", "agents"]
35
- SKIP_DIRS = ["agents/roadmaps/archive"] # archived roadmaps have historical refs
35
+ SKIP_DIRS = [
36
+ "agents/roadmaps/archive", # archived roadmaps have historical refs
37
+ "agents/council-sessions", # per-user audit trail (gitignored), captured provider output
38
+ ]
36
39
  ROOT = Path(".")
37
40
 
38
41
  # YAML memory files (engineering-memory layer) live under `agents/memory/`.
@@ -78,6 +81,7 @@ EXAMPLE_PATH_PATTERNS = [
78
81
  re.compile(r"agents/overrides/"), # override examples
79
82
  re.compile(r"commands/old-cmd"), # example placeholder
80
83
  re.compile(r"agents/README"), # README reference (may not exist in package)
84
+ re.compile(r"agents/index[\w.-]*\.md"), # planned auto-generated artefact index (F5)
81
85
  re.compile(r"agents/docs/"), # project-specific docs (not in package)
82
86
  re.compile(r"agents/contexts/"), # project-specific contexts (not in package)
83
87
  re.compile(r"agents/gates"), # project-specific policy docs