@event4u/agent-config 10.4.0 → 12.0.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 (303) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +73 -182
  3. package/dist/agent-src/commands/agent-handoff.md +0 -1
  4. package/dist/agent-src/commands/agent-status.md +0 -1
  5. package/dist/agent-src/commands/agents/audit.md +0 -1
  6. package/dist/agent-src/commands/agents/init.md +0 -1
  7. package/dist/agent-src/commands/agents/optimize.md +0 -1
  8. package/dist/agent-src/commands/agents/user/accept.md +0 -1
  9. package/dist/agent-src/commands/agents/user/delete.md +0 -1
  10. package/dist/agent-src/commands/agents/user/init.md +0 -1
  11. package/dist/agent-src/commands/agents/user/review.md +0 -1
  12. package/dist/agent-src/commands/agents/user/show.md +0 -1
  13. package/dist/agent-src/commands/agents/user/update.md +0 -1
  14. package/dist/agent-src/commands/agents/user.md +0 -1
  15. package/dist/agent-src/commands/agents.md +0 -1
  16. package/dist/agent-src/commands/analytics/prune.md +0 -1
  17. package/dist/agent-src/commands/analytics/show.md +0 -1
  18. package/dist/agent-src/commands/analytics.md +0 -1
  19. package/dist/agent-src/commands/analyze/conformance.md +0 -1
  20. package/dist/agent-src/commands/analyze/decision.md +0 -1
  21. package/dist/agent-src/commands/analyze/inbox.md +0 -1
  22. package/dist/agent-src/commands/analyze/incident.md +0 -1
  23. package/dist/agent-src/commands/analyze/near-miss.md +0 -1
  24. package/dist/agent-src/commands/analyze/postmortem.md +0 -1
  25. package/dist/agent-src/commands/analyze/premortem.md +0 -1
  26. package/dist/agent-src/commands/analyze/reference-repo.md +0 -1
  27. package/dist/agent-src/commands/analyze.md +0 -1
  28. package/dist/agent-src/commands/brand/identity.md +0 -1
  29. package/dist/agent-src/commands/brand/review.md +0 -1
  30. package/dist/agent-src/commands/brand/strategy.md +0 -1
  31. package/dist/agent-src/commands/brand/tokens.md +0 -1
  32. package/dist/agent-src/commands/brand/voice.md +0 -1
  33. package/dist/agent-src/commands/brand.md +0 -1
  34. package/dist/agent-src/commands/bug/fix.md +0 -1
  35. package/dist/agent-src/commands/bug/investigate.md +0 -1
  36. package/dist/agent-src/commands/bug.md +0 -1
  37. package/dist/agent-src/commands/challenge-me/vision.md +0 -1
  38. package/dist/agent-src/commands/challenge-me/with-docs.md +0 -1
  39. package/dist/agent-src/commands/challenge-me.md +0 -1
  40. package/dist/agent-src/commands/chat-history/import.md +0 -1
  41. package/dist/agent-src/commands/chat-history.md +0 -1
  42. package/dist/agent-src/commands/check-current-md.md +0 -1
  43. package/dist/agent-src/commands/commit/in-chunks.md +0 -1
  44. package/dist/agent-src/commands/commit.md +0 -1
  45. package/dist/agent-src/commands/condense.md +0 -1
  46. package/dist/agent-src/commands/context/create.md +0 -1
  47. package/dist/agent-src/commands/context/refactor.md +0 -1
  48. package/dist/agent-src/commands/context.md +0 -1
  49. package/dist/agent-src/commands/contribution-precheck.md +0 -1
  50. package/dist/agent-src/commands/cost/profile.md +0 -1
  51. package/dist/agent-src/commands/cost/report.md +0 -1
  52. package/dist/agent-src/commands/cost.md +0 -1
  53. package/dist/agent-src/commands/council/analysis.md +0 -1
  54. package/dist/agent-src/commands/council/debate.md +13 -5
  55. package/dist/agent-src/commands/council/default.md +26 -12
  56. package/dist/agent-src/commands/council/design.md +0 -1
  57. package/dist/agent-src/commands/council/optimize.md +0 -1
  58. package/dist/agent-src/commands/council/pr.md +0 -1
  59. package/dist/agent-src/commands/council.md +1 -2
  60. package/dist/agent-src/commands/design-system/capture.md +0 -1
  61. package/dist/agent-src/commands/design-system/generate.md +23 -2
  62. package/dist/agent-src/commands/design-system/import.md +0 -1
  63. package/dist/agent-src/commands/design-system.md +0 -1
  64. package/dist/agent-src/commands/estimate-ticket.md +0 -1
  65. package/dist/agent-src/commands/explain-run.md +0 -1
  66. package/dist/agent-src/commands/feature/dev.md +0 -1
  67. package/dist/agent-src/commands/feature/explore.md +0 -1
  68. package/dist/agent-src/commands/feature/plan.md +0 -1
  69. package/dist/agent-src/commands/feature/refactor.md +0 -1
  70. package/dist/agent-src/commands/feature/roadmap.md +0 -1
  71. package/dist/agent-src/commands/feature.md +0 -1
  72. package/dist/agent-src/commands/fix/ci.md +0 -1
  73. package/dist/agent-src/commands/fix/comments.md +0 -1
  74. package/dist/agent-src/commands/fix/portability.md +0 -1
  75. package/dist/agent-src/commands/fix/pr-comments-loop.md +0 -1
  76. package/dist/agent-src/commands/fix/pr-comments.md +0 -1
  77. package/dist/agent-src/commands/fix/quality.md +0 -1
  78. package/dist/agent-src/commands/fix/refs.md +0 -1
  79. package/dist/agent-src/commands/fix/route.md +0 -1
  80. package/dist/agent-src/commands/fix/seeder.md +0 -1
  81. package/dist/agent-src/commands/fix.md +0 -1
  82. package/dist/agent-src/commands/ghostwriter/delete.md +0 -1
  83. package/dist/agent-src/commands/ghostwriter/fetch.md +0 -1
  84. package/dist/agent-src/commands/ghostwriter/list.md +0 -1
  85. package/dist/agent-src/commands/ghostwriter/show.md +0 -1
  86. package/dist/agent-src/commands/ghostwriter/write.md +0 -1
  87. package/dist/agent-src/commands/ghostwriter.md +0 -1
  88. package/dist/agent-src/commands/grill-me.md +0 -1
  89. package/dist/agent-src/commands/humanize.md +0 -1
  90. package/dist/agent-src/commands/image/analyse.md +0 -1
  91. package/dist/agent-src/commands/image/create.md +0 -1
  92. package/dist/agent-src/commands/image/verify.md +0 -1
  93. package/dist/agent-src/commands/image.md +0 -1
  94. package/dist/agent-src/commands/implement-ticket.md +0 -1
  95. package/dist/agent-src/commands/jira-ticket.md +0 -1
  96. package/dist/agent-src/commands/judge/on-diff.md +0 -1
  97. package/dist/agent-src/commands/judge/solo.md +0 -1
  98. package/dist/agent-src/commands/judge/steps.md +0 -1
  99. package/dist/agent-src/commands/judge.md +0 -1
  100. package/dist/agent-src/commands/knowledge/cross-repo.md +0 -1
  101. package/dist/agent-src/commands/knowledge/forget.md +0 -1
  102. package/dist/agent-src/commands/knowledge/ingest.md +0 -1
  103. package/dist/agent-src/commands/knowledge/list.md +0 -1
  104. package/dist/agent-src/commands/knowledge.md +0 -1
  105. package/dist/agent-src/commands/memory/add.md +0 -1
  106. package/dist/agent-src/commands/memory/learn-low-impact.md +0 -1
  107. package/dist/agent-src/commands/memory/load.md +0 -1
  108. package/dist/agent-src/commands/memory/mine-session.md +0 -1
  109. package/dist/agent-src/commands/memory/promote.md +0 -1
  110. package/dist/agent-src/commands/memory/propose.md +0 -1
  111. package/dist/agent-src/commands/memory.md +0 -1
  112. package/dist/agent-src/commands/mission/upgrade.md +0 -1
  113. package/dist/agent-src/commands/mode.md +0 -1
  114. package/dist/agent-src/commands/module/create.md +0 -1
  115. package/dist/agent-src/commands/module/explore.md +0 -1
  116. package/dist/agent-src/commands/module.md +0 -1
  117. package/dist/agent-src/commands/optimize/agents-dir.md +0 -1
  118. package/dist/agent-src/commands/optimize/augmentignore.md +0 -1
  119. package/dist/agent-src/commands/optimize/deep.md +0 -1
  120. package/dist/agent-src/commands/optimize/project.md +0 -1
  121. package/dist/agent-src/commands/optimize/prompt.md +0 -1
  122. package/dist/agent-src/commands/optimize/rtk.md +0 -1
  123. package/dist/agent-src/commands/optimize/skills.md +0 -1
  124. package/dist/agent-src/commands/optimize.md +0 -1
  125. package/dist/agent-src/commands/orchestrate.md +0 -1
  126. package/dist/agent-src/commands/override/create.md +0 -1
  127. package/dist/agent-src/commands/override/manage.md +0 -1
  128. package/dist/agent-src/commands/override.md +0 -1
  129. package/dist/agent-src/commands/package/reset.md +0 -1
  130. package/dist/agent-src/commands/package/test.md +0 -1
  131. package/dist/agent-src/commands/package.md +0 -1
  132. package/dist/agent-src/commands/post-as/ghostwriter.md +0 -1
  133. package/dist/agent-src/commands/post-as/me.md +0 -1
  134. package/dist/agent-src/commands/post-as.md +0 -1
  135. package/dist/agent-src/commands/pr/create/description-only.md +0 -1
  136. package/dist/agent-src/commands/pr/create.md +67 -28
  137. package/dist/agent-src/commands/prediction-pool.md +0 -1
  138. package/dist/agent-src/commands/prepare-for-review.md +0 -1
  139. package/dist/agent-src/commands/profile/activate.md +0 -1
  140. package/dist/agent-src/commands/profile/deactivate.md +0 -1
  141. package/dist/agent-src/commands/profile/show.md +0 -1
  142. package/dist/agent-src/commands/profile.md +0 -1
  143. package/dist/agent-src/commands/project/analyze.md +0 -1
  144. package/dist/agent-src/commands/project/health.md +0 -1
  145. package/dist/agent-src/commands/project.md +0 -1
  146. package/dist/agent-src/commands/refine-ticket.md +0 -1
  147. package/dist/agent-src/commands/research/deep.md +0 -1
  148. package/dist/agent-src/commands/research/report.md +0 -1
  149. package/dist/agent-src/commands/research.md +0 -1
  150. package/dist/agent-src/commands/review/changes.md +0 -1
  151. package/dist/agent-src/commands/review/routing.md +0 -1
  152. package/dist/agent-src/commands/review.md +0 -1
  153. package/dist/agent-src/commands/roadmap/ai-council.md +0 -1
  154. package/dist/agent-src/commands/roadmap/create.md +0 -1
  155. package/dist/agent-src/commands/roadmap/materialize.md +0 -1
  156. package/dist/agent-src/commands/roadmap/next.md +0 -1
  157. package/dist/agent-src/commands/roadmap/process-full.md +0 -1
  158. package/dist/agent-src/commands/roadmap/process-phase.md +0 -1
  159. package/dist/agent-src/commands/roadmap/process-step.md +0 -1
  160. package/dist/agent-src/commands/roadmap.md +0 -1
  161. package/dist/agent-src/commands/rule-compliance-audit.md +0 -1
  162. package/dist/agent-src/commands/security-audit-config.md +0 -1
  163. package/dist/agent-src/commands/skill/preview.md +0 -1
  164. package/dist/agent-src/commands/skill.md +0 -1
  165. package/dist/agent-src/commands/skills/discover.md +0 -1
  166. package/dist/agent-src/commands/skills.md +0 -1
  167. package/dist/agent-src/commands/sync/agent-settings.md +0 -1
  168. package/dist/agent-src/commands/sync/gitignore/fix.md +0 -1
  169. package/dist/agent-src/commands/sync/gitignore.md +0 -1
  170. package/dist/agent-src/commands/sync.md +0 -1
  171. package/dist/agent-src/commands/tdd/green.md +0 -1
  172. package/dist/agent-src/commands/tdd/red.md +0 -1
  173. package/dist/agent-src/commands/tdd/refactor.md +0 -1
  174. package/dist/agent-src/commands/tdd.md +0 -1
  175. package/dist/agent-src/commands/team/adversarial.md +0 -1
  176. package/dist/agent-src/commands/team/delegate.md +0 -1
  177. package/dist/agent-src/commands/team/review.md +0 -1
  178. package/dist/agent-src/commands/team/status.md +0 -1
  179. package/dist/agent-src/commands/team-knowledge/bootstrap.md +0 -1
  180. package/dist/agent-src/commands/team-knowledge/consolidate.md +0 -1
  181. package/dist/agent-src/commands/team-knowledge.md +0 -1
  182. package/dist/agent-src/commands/team.md +0 -1
  183. package/dist/agent-src/commands/tests/create.md +0 -1
  184. package/dist/agent-src/commands/tests/e2e-heal.md +0 -1
  185. package/dist/agent-src/commands/tests/e2e-plan.md +0 -1
  186. package/dist/agent-src/commands/tests/execute.md +0 -1
  187. package/dist/agent-src/commands/tests.md +0 -1
  188. package/dist/agent-src/commands/threat-model.md +0 -1
  189. package/dist/agent-src/commands/update-form-request-messages.md +0 -1
  190. package/dist/agent-src/commands/upstream-contribute.md +0 -1
  191. package/dist/agent-src/commands/video/from-script.md +0 -1
  192. package/dist/agent-src/commands/video/from-song.md +0 -1
  193. package/dist/agent-src/commands/video/scene.md +0 -1
  194. package/dist/agent-src/commands/video/stitch.md +0 -1
  195. package/dist/agent-src/commands/video/storyboard.md +0 -1
  196. package/dist/agent-src/commands/video.md +0 -1
  197. package/dist/agent-src/commands/work.md +0 -1
  198. package/dist/agent-src/commands/worktree/cleanup.md +0 -1
  199. package/dist/agent-src/commands/worktree/create.md +5 -4
  200. package/dist/agent-src/commands/worktree/status.md +0 -1
  201. package/dist/agent-src/commands/worktree/verify.md +0 -1
  202. package/dist/agent-src/commands/worktree.md +0 -1
  203. package/dist/agent-src/rules/settings-ask-protocol.md +14 -9
  204. package/dist/agent-src/skills/ai-council/SKILL.md +24 -6
  205. package/dist/agent-src/skills/corpus-grounding/SKILL.md +12 -1
  206. package/dist/agent-src/skills/corpus-grounding/scripts/decision_engine.ts +215 -7
  207. package/dist/agent-src/skills/corpus-grounding/scripts/ground.ts +39 -1
  208. package/dist/agent-src/skills/design-intelligence/ATTRIBUTION.md +19 -2
  209. package/dist/agent-src/skills/design-intelligence/data/manifest.json +36 -1
  210. package/dist/agent-src/skills/design-intelligence/data/motion.csv +17 -0
  211. package/dist/agent-src/skills/docx-authoring/SKILL.md +1 -0
  212. package/dist/agent-src/skills/git-workflow/SKILL.md +17 -3
  213. package/dist/agent-src/skills/pdf-tools/SKILL.md +1 -0
  214. package/dist/agent-src/skills/skill-writing/SKILL.md +35 -0
  215. package/dist/agent-src/skills/subagent-orchestration/SKILL.md +9 -6
  216. package/dist/agent-src/skills/using-git-worktrees/SKILL.md +25 -21
  217. package/dist/agent-src/templates/agent-settings.md +0 -1
  218. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  219. package/dist/cli/commands/commands.candidates.test.js +1 -1
  220. package/dist/cli/commands/commands.candidates.test.js.map +1 -1
  221. package/dist/cli/commands/commands.js +9 -15
  222. package/dist/cli/commands/commands.js.map +1 -1
  223. package/dist/cli/commands/profiles.test.js +7 -7
  224. package/dist/cli/commands/profiles.test.js.map +1 -1
  225. package/dist/cli/discovery/loadManifest.js.map +1 -1
  226. package/dist/cli/main.js +2 -2
  227. package/dist/cli/main.js.map +1 -1
  228. package/dist/cli-delegate/{chunk-BV3WR67D.js → chunk-55WZN5VF.js} +3 -6
  229. package/dist/cli-delegate/{chunk-X3VOARZD.js → chunk-L565YFXH.js} +3 -3
  230. package/dist/cli-delegate/{chunk-JMQZ7MM5.js → chunk-MNWRDMR5.js} +1 -1
  231. package/dist/cli-delegate/{chunk-IR3IVRVC.js → chunk-NLP54U3J.js} +2 -1
  232. package/dist/cli-delegate/{chunk-FV34EGEX.js → chunk-NN4KW4HZ.js} +1 -1
  233. package/dist/cli-delegate/{chunk-6ENSXSBW.js → chunk-PPQO4NGR.js} +1 -1
  234. package/dist/cli-delegate/{chunk-6LOPHJLD.js → chunk-RYNADUFG.js} +1 -1
  235. package/dist/cli-delegate/cmd_analyze_session.js +1 -1
  236. package/dist/cli-delegate/cmd_brand_status.js +1 -1
  237. package/dist/cli-delegate/cmd_conformance.js +16 -4
  238. package/dist/cli-delegate/cmd_doctor.js +2 -2
  239. package/dist/cli-delegate/cmd_explain.js +2 -2
  240. package/dist/cli-delegate/cmd_export.js +4 -4
  241. package/dist/cli-delegate/cmd_handoff.js +2 -2
  242. package/dist/cli-delegate/cmd_mcp_available.js +1 -1
  243. package/dist/cli-delegate/cmd_migrate.js +2 -2
  244. package/dist/cli-delegate/cmd_packs_active.js +2 -2
  245. package/dist/cli-delegate/cmd_prune.js +4 -4
  246. package/dist/cli-delegate/cmd_route_audit.js +2 -2
  247. package/dist/cli-delegate/cmd_route_explain.js +1 -1
  248. package/dist/cli-delegate/cmd_session_recycle.js +1 -1
  249. package/dist/cli-delegate/cmd_settings_get.js +1 -1
  250. package/dist/cli-delegate/cmd_settings_migrate.js +4 -4
  251. package/dist/cli-delegate/cmd_settings_set.js +1 -1
  252. package/dist/cli-delegate/cmd_sync.js +4 -4
  253. package/dist/cli-delegate/cmd_uninstall.js +4 -4
  254. package/dist/cli-delegate/cmd_update.js +1 -1
  255. package/dist/cli-delegate/cmd_upgrade.js +1 -1
  256. package/dist/cli-delegate/cmd_validate.js +4 -4
  257. package/dist/cli-delegate/cmd_versions.js +1 -1
  258. package/dist/discovery/deprecation-report.md +1 -1
  259. package/dist/discovery/discovery-manifest.json +216 -415
  260. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  261. package/dist/discovery/discovery-manifest.summary.md +2 -2
  262. package/dist/discovery/dormancy-report.md +1 -1
  263. package/dist/discovery/orphan-report.md +1 -1
  264. package/dist/discovery/packs.json +3 -3
  265. package/dist/discovery/trust-report.md +1 -1
  266. package/dist/discovery/workspaces.json +3 -3
  267. package/dist/hooks/dispatch.js +68 -14
  268. package/dist/install/install.mjs +5 -7
  269. package/dist/mcp/registry-manifest.json +3 -3
  270. package/dist/mcp/server.json +2 -2
  271. package/dist/mcp/server.mjs +48 -6
  272. package/dist/scripts/_lib/agent_settings.js +8 -0
  273. package/dist/scripts/_lib/agent_settings.js.map +1 -1
  274. package/dist/server/schemas/settings.js +3 -4
  275. package/dist/server/schemas/settings.js.map +1 -1
  276. package/dist/ui/assets/{index-5fXOHoVh.js → index-B0aMJnuz.js} +2 -2
  277. package/dist/ui/assets/{index-5fXOHoVh.js.map → index-B0aMJnuz.js.map} +1 -1
  278. package/dist/ui/index.html +1 -1
  279. package/docs/MIGRATION.md +1 -0
  280. package/docs/contracts/settings-classes.md +53 -9
  281. package/package.json +1 -1
  282. package/src/config/agent-settings.template.yml +49 -18
  283. package/src/config/gate-coverage.yml +13 -3
  284. package/src/config/gate-violation-baselines.json +4 -4
  285. package/src/config/pack-size-budget.json +3 -2
  286. package/src/scripts/_dispatch.bash +42 -5
  287. package/src/scripts/_lib/agent_settings.ts +8 -0
  288. package/src/scripts/audit_command_surface.ts +21 -15
  289. package/src/scripts/build_catalog_index.ts +1 -1
  290. package/src/scripts/build_discovery_manifest.ts +30 -34
  291. package/src/scripts/check_branch_freshness.ts +393 -12
  292. package/src/scripts/external_sources_denylist.json +7 -2
  293. package/src/scripts/gen_discovery_baseline.ts +3 -3
  294. package/src/scripts/hook_manifest.yaml +20 -0
  295. package/src/scripts/hooks/subagent_ledger_hook.ts +17 -4
  296. package/src/scripts/lint_command_tiers.ts +29 -75
  297. package/src/scripts/lint_originality.ts +101 -14
  298. package/src/scripts/schemas/command.schema.json +4 -9
  299. package/src/scripts/schemas/skill.schema.json +10 -1
  300. package/src/scripts/session_register_hook.ts +120 -10
  301. package/src/scripts/skill_linter.ts +82 -2
  302. package/src/scripts/worktree_cleanup_check.ts +111 -7
  303. package/src/server/schemas/settings.ts +3 -6
@@ -254,6 +254,42 @@ const EXTERNAL_EXECUTION_HANDLERS = new Set(['shell', 'php', 'node']);
254
254
  * span lines and accept a bare key whose value sits somewhere below it.
255
255
  */
256
256
  const RUNTIME_REQUIRES_BLOCK_PATTERN = /^runtime_requires:[ \t]*(\{.*)?$/m;
257
+
258
+ /**
259
+ * The deprecated free-text `compatibility:` key and its structured successor
260
+ * `harness_compat:`, both top-level. Anchored at column 0 so a `compatibility:`
261
+ * nested inside another block (or the word inside a quoted description) is not
262
+ * read as the frontmatter key — the same reason the neighbouring patterns above
263
+ * use `^` rather than a bare substring test. A value is required after the colon
264
+ * so a bare key with the value on the next line is not counted as a declaration.
265
+ */
266
+ const COMPATIBILITY_KEY_PATTERN = /^compatibility:[ \t]*\S/m;
267
+ const HARNESS_COMPAT_KEY_PATTERN = /^harness_compat:[ \t]*\S/m;
268
+
269
+ /**
270
+ * `safety_mode: strict` is a claim made in the frontmatter about a skill whose
271
+ * execution path may mutate something. Nothing checked that the body honours it,
272
+ * so the claim could be pure metadata. These patterns recognise the two shapes
273
+ * the action-reference split allows (`skill-writing` § Action-reference split):
274
+ * an inline precondition that gates the write, or a deferral of the write-path
275
+ * steps into the skill's own `references/`.
276
+ *
277
+ * Deliberately a warning over a phrase list rather than an error over a required
278
+ * section: a skill that gates its write path some third way is doing the right
279
+ * thing, and a hard gate over a corpus of one strict skill would be a gate that
280
+ * mostly cannot fail — the defect class `road-to-skill-ecosystem-gate-integrity`
281
+ * exists to remove.
282
+ */
283
+ const STRICT_WRITE_GATE_PATTERNS = [
284
+ /--dry-run/i,
285
+ /\bnever silent[- ]run/i,
286
+ /\bpropose,? never\b/i,
287
+ /\bconfirms? before\b/i,
288
+ /\bexplicit (?:user )?confirmation\b/i,
289
+ /\basks? (?:the user )?(?:first|before)\b/i,
290
+ ];
291
+ const SKILL_REFERENCE_DEFERRAL_PATTERN = /\]\(\.{0,2}\/?references\//;
292
+
257
293
  const VALID_EXECUTION_FIELDS = new Set([
258
294
  'type',
259
295
  'handler',
@@ -1295,7 +1331,7 @@ function lint_wing4_boundaries(text: string): Issue[] {
1295
1331
  * for an optional parameter — a future caller that forgets it gets a confident
1296
1332
  * error about a declaration it never looked for.
1297
1333
  */
1298
- function lint_execution_metadata(execution: ExecutionBlock, frontmatter: string): Issue[] {
1334
+ function lint_execution_metadata(execution: ExecutionBlock, frontmatter: string, body = ''): Issue[] {
1299
1335
  const issues: Issue[] = [];
1300
1336
 
1301
1337
  const execType = execution.type;
@@ -1370,6 +1406,29 @@ function lint_execution_metadata(execution: ExecutionBlock, frontmatter: string)
1370
1406
  );
1371
1407
  }
1372
1408
 
1409
+ // road-to-skill-ecosystem-executable-payloads Phase 5 — the action-reference
1410
+ // split. A strict-mode skill either gates its write path inline, or says it
1411
+ // does not define the mutating workflow and defers those steps to its own
1412
+ // `references/` behind a precondition. Neither present → the strict claim is
1413
+ // frontmatter only, and the body reads like an ordinary skill.
1414
+ if (
1415
+ safetyMode === 'strict' &&
1416
+ body !== '' &&
1417
+ !STRICT_WRITE_GATE_PATTERNS.some((p) => p.test(body)) &&
1418
+ !SKILL_REFERENCE_DEFERRAL_PATTERN.test(body)
1419
+ ) {
1420
+ issues.push(
1421
+ new Issue(
1422
+ 'warning',
1423
+ 'strict_mode_missing_write_gate',
1424
+ "execution.safety_mode is 'strict' but the body names no precondition on the write " +
1425
+ 'path and defers no write-path steps to the skill\'s references/ — state the gate ' +
1426
+ 'inline (propose-then-confirm, --dry-run) or defer it, per skill-writing ' +
1427
+ '§ Action-reference split',
1428
+ ),
1429
+ );
1430
+ }
1431
+
1373
1432
  const timeout = execution.timeout_seconds;
1374
1433
  if (timeout !== undefined) {
1375
1434
  if (typeof timeout !== 'number' || !Number.isInteger(timeout) || timeout <= 0) {
@@ -1583,9 +1642,30 @@ export function lint_skill(p: string, text: string, absPath: string | null = nul
1583
1642
  }
1584
1643
  }
1585
1644
 
1645
+ // `compatibility:` is deprecated in favour of the structured
1646
+ // `harness_compat:` (schema, 2026-08-14). The field is NOT removed — the
1647
+ // schema still accepts it and both existing users still carry it — so this
1648
+ // is a warning, not an error: its job is to stop NEW adoption during the
1649
+ // window, which is the only thing a deprecation notice with no gate cannot
1650
+ // do. Regex, not a YAML parse, to match the file's existing convention.
1651
+ if (
1652
+ COMPATIBILITY_KEY_PATTERN.test(frontmatter) &&
1653
+ !HARNESS_COMPAT_KEY_PATTERN.test(frontmatter)
1654
+ ) {
1655
+ issues.push(
1656
+ new Issue(
1657
+ 'warning',
1658
+ 'deprecated_compatibility_field',
1659
+ "Frontmatter declares the deprecated free-text 'compatibility:' without the structured " +
1660
+ "'harness_compat:' that supersedes it — add harness_compat (see skill.schema.json and " +
1661
+ 'docs/MIGRATION.md § Scheduled deprecations); compatibility stays accepted until removal',
1662
+ ),
1663
+ );
1664
+ }
1665
+
1586
1666
  const execution = parseExecutionBlock(frontmatter);
1587
1667
  if (execution !== null) {
1588
- issues.push(...lint_execution_metadata(execution, frontmatter));
1668
+ issues.push(...lint_execution_metadata(execution, frontmatter, text.replace(FRONTMATTER_PATTERN, '')));
1589
1669
  }
1590
1670
 
1591
1671
  const tierMatch = TIER_PATTERN.exec(frontmatter);
@@ -34,6 +34,7 @@ import { execFileSync } from 'node:child_process';
34
34
  import * as fs from 'node:fs';
35
35
  import * as path from 'node:path';
36
36
  import { fileURLToPath, pathToFileURL } from 'node:url';
37
+ import { read_live_records, register_dir } from './_lib/session_register.js';
37
38
 
38
39
  export interface CheckResult {
39
40
  allowed: boolean;
@@ -304,8 +305,20 @@ function isAncestor(repoPath: string, branch: string, trunk: string): boolean {
304
305
  }
305
306
  }
306
307
 
307
- export function isStandardLocation(repoPath: string, worktreePath: string): boolean {
308
- const rel = path.relative(canonical(repoPath), canonical(worktreePath));
308
+ /**
309
+ * `basePath` MUST be the main worktree, never the invoking repo path.
310
+ *
311
+ * Measured 2026-08-13, and the failure is total rather than partial: called with
312
+ * a linked worktree as the base, every sibling worktree resolves to `..` and the
313
+ * safe set collapses to empty. Same binary, same repo, same minute — from inside
314
+ * `.claude/worktrees/<branch>`: 304 registered, safe 0, 278 "non-standard"; from
315
+ * the main checkout: safe 181, 81 non-standard. A maintainer who ran the
316
+ * inventory from a worktree would read "nothing to clean" and conclude the
317
+ * estate was fine, which is the worst shape a cleanup tool can fail in — it
318
+ * fails silently, and toward inaction.
319
+ */
320
+ export function isStandardLocation(basePath: string, worktreePath: string): boolean {
321
+ const rel = path.relative(canonical(basePath), canonical(worktreePath));
309
322
  if (rel.startsWith('..') || path.isAbsolute(rel)) return false;
310
323
  return STANDARD_WORKTREE_DIRS.some(
311
324
  (dir) => rel === dir || rel.startsWith(`${dir}${path.sep}`),
@@ -348,16 +361,70 @@ function lastGitActivity(worktreePath: string): Date | null {
348
361
  * Classify every worktree. `now` is injectable so the live-window boundary is
349
362
  * testable rather than wall-clock dependent.
350
363
  */
351
- export function buildInventory(repoPath: string, now: Date = new Date()): Inventory {
364
+ /**
365
+ * Two conditions the `safe` predicate does NOT carry by default, both off unless
366
+ * asked for. They exist because an approval can be stricter than the tool, and
367
+ * silently removing under the looser predicate is the substitution such an
368
+ * approval is written to prevent.
369
+ *
370
+ * `minAgeDays` is a floor on git inactivity, layered ON TOP of the 48-hour live
371
+ * window rather than replacing it: 48h answers "is someone in it right now", a
372
+ * 60-day floor answers "is this abandoned". Different questions.
373
+ *
374
+ * `excludeLiveSessions` reads the session register — real records with a real
375
+ * `worktree` path and a real TTL — instead of inferring occupancy from file
376
+ * mtime, which this module's own header already rules out as a liveness signal.
377
+ */
378
+ export interface InventoryOptions {
379
+ now?: Date;
380
+ minAgeDays?: number | null;
381
+ excludeLiveSessions?: boolean;
382
+ }
383
+
384
+ export function buildInventory(
385
+ repoPath: string,
386
+ nowOrOptions: Date | InventoryOptions = new Date(),
387
+ ): Inventory {
388
+ const opts: InventoryOptions =
389
+ nowOrOptions instanceof Date ? { now: nowOrOptions } : nowOrOptions;
390
+ const now = opts.now ?? new Date();
391
+ const minAgeDays = opts.minAgeDays ?? null;
392
+ const ageCutoff = minAgeDays === null ? null : now.getTime() - minAgeDays * 86400 * 1000;
393
+ return buildInventoryInner(repoPath, now, ageCutoff, minAgeDays, opts.excludeLiveSessions === true);
394
+ }
395
+
396
+ function buildInventoryInner(
397
+ repoPath: string,
398
+ nowArg: Date,
399
+ ageCutoff: number | null,
400
+ minAgeDays: number | null,
401
+ excludeLiveSessions: boolean,
402
+ ): Inventory {
403
+ const now = nowArg;
352
404
  const trunk = resolveTrunk(repoPath);
353
405
  const entries = listWorktrees(repoPath);
354
406
  const mainPath = canonical(entries.length > 0 ? entries[0]!.path : repoPath);
355
407
  const liveCutoff = now.getTime() - LIVE_WINDOW_HOURS * 3600 * 1000;
356
408
 
409
+ // Registered session worktrees, canonicalised so the comparison survives a
410
+ // symlinked checkout root the same way every other path here does. Empty set
411
+ // when the option is off, when no register directory exists (the normal
412
+ // state before any session registers), or when every record has expired.
413
+ const sessionPaths = new Set<string>();
414
+ if (excludeLiveSessions) {
415
+ const dir = register_dir(mainPath);
416
+ if (dir !== null) {
417
+ for (const rec of read_live_records(dir, { now })) {
418
+ sessionPaths.add(canonical(rec.worktree));
419
+ }
420
+ }
421
+ }
422
+
357
423
  const rows: InventoryRow[] = entries.map((e) => {
358
424
  const resolved = canonical(e.path);
359
425
  const isMain = resolved === mainPath;
360
- const standardLocation = isMain ? true : isStandardLocation(repoPath, resolved);
426
+ // `mainPath`, NOT `repoPath` — see isStandardLocation's contract.
427
+ const standardLocation = isMain ? true : isStandardLocation(mainPath, resolved);
361
428
  const reasons: string[] = [];
362
429
 
363
430
  if (!fs.existsSync(resolved)) {
@@ -389,6 +456,20 @@ export function buildInventory(repoPath: string, now: Date = new Date()): Invent
389
456
  if (e.branch === null) {
390
457
  reasons.push('detached HEAD — no branch to judge reachability for');
391
458
  }
459
+ if (sessionPaths.has(resolved)) {
460
+ reasons.push('a live agent session is registered in this worktree');
461
+ }
462
+ if (ageCutoff !== null && (activity === null || activity.getTime() >= ageCutoff)) {
463
+ // `activity === null` disqualifies rather than passes: an unreadable
464
+ // git-dir mtime is absence of evidence, and under an explicit
465
+ // minimum-age floor that has to read as "cannot show it is old
466
+ // enough", never as "old enough".
467
+ reasons.push(
468
+ activity === null
469
+ ? `git activity unreadable — cannot prove ${minAgeDays}+ days of inactivity`
470
+ : `git activity within the last ${minAgeDays} days`,
471
+ );
472
+ }
392
473
  if (!standardLocation) {
393
474
  reasons.push('non-standard location — outside the conventional worktree roots');
394
475
  }
@@ -465,7 +546,7 @@ export function removalPlan(inv: Inventory): string[] {
465
546
  function usage(): never {
466
547
  process.stderr.write(
467
548
  'usage: worktree_cleanup_check check <worktree-path> | scope-overlap [repo-path] | ' +
468
- 'inventory [repo-path] [--json|--plan]\n',
549
+ 'inventory [repo-path] [--json|--plan] [--min-age-days=N] [--exclude-live-sessions]\n',
469
550
  );
470
551
  process.exit(2);
471
552
  }
@@ -509,9 +590,32 @@ export function main(argv: readonly string[] = process.argv.slice(2)): number {
509
590
  const rest = argv.slice(1);
510
591
  const flags = rest.filter((a) => a.startsWith('--'));
511
592
  const positional = rest.filter((a) => !a.startsWith('--'));
512
- if (positional.length > 1 || flags.some((f) => f !== '--json' && f !== '--plan')) usage();
593
+ const KNOWN = ['--json', '--plan', '--exclude-live-sessions'];
594
+ const ageFlag = flags.find((f) => f.startsWith('--min-age-days='));
595
+ if (
596
+ positional.length > 1 ||
597
+ flags.some((f) => !KNOWN.includes(f) && !f.startsWith('--min-age-days='))
598
+ ) {
599
+ usage();
600
+ }
601
+ let minAgeDays: number | null = null;
602
+ if (ageFlag !== undefined) {
603
+ const raw = ageFlag.slice('--min-age-days='.length);
604
+ const n = Number(raw);
605
+ // Refuse rather than silently fall back to null: a typo'd floor that
606
+ // reads as "no floor" would widen the safe set at exactly the moment
607
+ // the caller asked to narrow it.
608
+ if (!Number.isFinite(n) || !Number.isInteger(n) || n < 0) {
609
+ process.stderr.write(`--min-age-days needs a non-negative integer, got '${raw}'\n`);
610
+ return 2;
611
+ }
612
+ minAgeDays = n;
613
+ }
513
614
  const repo = path.resolve(positional[0] ?? '.');
514
- const inv = buildInventory(repo);
615
+ const inv = buildInventory(repo, {
616
+ minAgeDays,
617
+ excludeLiveSessions: flags.includes('--exclude-live-sessions'),
618
+ });
515
619
 
516
620
  if (flags.includes('--json')) {
517
621
  process.stdout.write(`${JSON.stringify(inv, null, 2)}\n`);
@@ -23,7 +23,6 @@ const accessStyle = z.enum(['getters_setters', 'get_attribute', 'magic_propertie
23
23
  const chatFreq = z.enum(['per_turn', 'per_phase', 'per_tool']);
24
24
  const qualityCadence = z.enum(['end_of_roadmap', 'per_phase', 'per_step']);
25
25
  const regenCadence = z.enum(['per_step', 'every_5_steps', 'phase_boundary']);
26
- const worktreeMode = z.enum(['off', 'on', 'ask']);
27
26
  const fidelityMode = z.enum(['strict', 'structural', 'hard-floor']);
28
27
  const crossSourceMode = z.enum(['on', 'auto', 'off']);
29
28
  const richSkillsMode = z.enum(['on', 'ask', 'off']);
@@ -351,11 +350,9 @@ export const settingsSchema = z.object({
351
350
  'Opt-in adversarial-verification-council mode (subagent-orchestration Mode 9, ADR-122). off (default) = never runs; ask = offer it on an explicit high-risk change; on = auto-run on high-risk changes. Advisory only — a panel of distinct-model skeptics red-teams a real change for defect FINDING coverage and NEVER auto-gates it (Hard Floor). Stays default-off until the adversarial-council-finding-coverage claim is backed.',
352
351
  ),
353
352
  }),
354
- worktrees: z.object({
355
- mode: worktreeMode.default('ask').describe(
356
- 'When the agent considers a parallel `git worktree` for risky / large work. ask (default) = surface a numbered option and wait. on = spawn worktrees autonomously. off = never use worktrees, edit in place.',
357
- ),
358
- }),
353
+ // `worktrees.mode` was DELETED (ADR-229). Worktree creation is
354
+ // instruction-only and hardcoded; there is nothing left to configure. A
355
+ // leftover key is ignored with one deprecation line via REMOVED_KEYS.
359
356
  ai_team: z.object({
360
357
  model: z.string().default('auto').describe(
361
358
  "Model handed to the codex CLI. 'auto' (default) = pass no --model flag so the CLI's own default applies — tracks the subscription's current strongest model instead of pinning a stale ID. Any other value passes through verbatim as `--model <value>`.",