session-orchestrator 5.1.0 → 5.2.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/.agents/skills/autopilot/SKILL.md +1 -0
  2. package/.agents/skills/bootstrap/SKILL.md +2 -0
  3. package/.agents/skills/brainstorm/SKILL.md +3 -0
  4. package/.agents/skills/close/SKILL.md +17 -0
  5. package/.agents/skills/debug/SKILL.md +2 -0
  6. package/.agents/skills/discovery/SKILL.md +2 -1
  7. package/.agents/skills/dispatcher/SKILL.md +2 -0
  8. package/.agents/skills/eli5/SKILL.md +2 -0
  9. package/.agents/skills/eval/SKILL.md +1 -0
  10. package/.agents/skills/evolve/SKILL.md +2 -1
  11. package/.agents/skills/go/SKILL.md +18 -0
  12. package/.agents/skills/grill/SKILL.md +2 -0
  13. package/.agents/skills/harness-audit/SKILL.md +16 -0
  14. package/.agents/skills/memory-cleanup/SKILL.md +1 -0
  15. package/.agents/skills/persona-panel/SKILL.md +1 -0
  16. package/.agents/skills/plan/SKILL.md +3 -1
  17. package/.agents/skills/portfolio/SKILL.md +17 -0
  18. package/.agents/skills/reconcile/SKILL.md +1 -0
  19. package/.agents/skills/release/SKILL.md +18 -0
  20. package/.agents/skills/repo-audit/SKILL.md +1 -0
  21. package/.agents/skills/spinout/SKILL.md +1 -0
  22. package/.agents/skills/sunset-review/SKILL.md +2 -0
  23. package/.agents/skills/test/SKILL.md +17 -0
  24. package/.agents/skills/ux-grill/SKILL.md +2 -0
  25. package/.claude-plugin/marketplace.json +1 -1
  26. package/.claude-plugin/plugin.json +1 -1
  27. package/.codex-plugin/plugin.json +1 -1
  28. package/.codex-plugin/skills/autopilot/SKILL.md +5 -4
  29. package/.codex-plugin/skills/bootstrap/SKILL.md +8 -4
  30. package/.codex-plugin/skills/brainstorm/SKILL.md +11 -4
  31. package/.codex-plugin/skills/close/SKILL.md +3 -3
  32. package/.codex-plugin/skills/convergence-monitoring/SKILL.md +2 -0
  33. package/.codex-plugin/skills/convergence-monitoring/agents/openai.yaml +5 -0
  34. package/.codex-plugin/skills/debug/SKILL.md +11 -4
  35. package/.codex-plugin/skills/discovery/SKILL.md +8 -4
  36. package/.codex-plugin/skills/dispatcher/SKILL.md +4 -4
  37. package/.codex-plugin/skills/eli5/SKILL.md +9 -4
  38. package/.codex-plugin/skills/eval/SKILL.md +9 -4
  39. package/.codex-plugin/skills/evolve/SKILL.md +9 -4
  40. package/.codex-plugin/skills/go/SKILL.md +3 -3
  41. package/.codex-plugin/skills/grill/SKILL.md +11 -4
  42. package/.codex-plugin/skills/harness-audit/SKILL.md +4 -3
  43. package/.codex-plugin/skills/memory-cleanup/SKILL.md +9 -4
  44. package/.codex-plugin/skills/npm-publish/SKILL.md +2 -0
  45. package/.codex-plugin/skills/npm-publish/agents/openai.yaml +5 -0
  46. package/.codex-plugin/skills/persona-panel/SKILL.md +5 -5
  47. package/.codex-plugin/skills/plan/SKILL.md +8 -4
  48. package/.codex-plugin/skills/portfolio/SKILL.md +3 -3
  49. package/.codex-plugin/skills/reconcile/SKILL.md +9 -4
  50. package/.codex-plugin/skills/release/SKILL.md +3 -3
  51. package/.codex-plugin/skills/repo-audit/SKILL.md +6 -4
  52. package/.codex-plugin/skills/spinout/SKILL.md +4 -4
  53. package/.codex-plugin/skills/sunset-review/SKILL.md +5 -4
  54. package/.codex-plugin/skills/test/SKILL.md +3 -3
  55. package/.codex-plugin/skills/ux-grill/SKILL.md +11 -4
  56. package/.cursor/commands/autopilot.md +4 -4
  57. package/.cursor/commands/bootstrap.md +5 -4
  58. package/.cursor/commands/brainstorm.md +5 -4
  59. package/.cursor/commands/close.md +4 -3
  60. package/.cursor/commands/convergence-monitoring.md +13 -0
  61. package/.cursor/commands/debug.md +4 -4
  62. package/.cursor/commands/discovery.md +4 -4
  63. package/.cursor/commands/dispatcher.md +4 -4
  64. package/.cursor/commands/eli5.md +4 -4
  65. package/.cursor/commands/eval.md +4 -4
  66. package/.cursor/commands/evolve.md +4 -4
  67. package/.cursor/commands/go.md +4 -3
  68. package/.cursor/commands/grill.md +4 -4
  69. package/.cursor/commands/harness-audit.md +3 -3
  70. package/.cursor/commands/memory-cleanup.md +4 -4
  71. package/.cursor/commands/npm-publish.md +13 -0
  72. package/.cursor/commands/persona-panel.md +4 -4
  73. package/.cursor/commands/plan.md +5 -4
  74. package/.cursor/commands/portfolio.md +3 -3
  75. package/.cursor/commands/reconcile.md +4 -4
  76. package/.cursor/commands/release.md +4 -3
  77. package/.cursor/commands/repo-audit.md +4 -4
  78. package/.cursor/commands/spinout.md +4 -4
  79. package/.cursor/commands/sunset-review.md +4 -4
  80. package/.cursor/commands/test.md +3 -3
  81. package/.cursor/commands/ux-grill.md +4 -4
  82. package/.cursor/rules/010-session-workflow.mdc +2 -2
  83. package/.cursor/skills/bootstrap/SKILL.md +1 -0
  84. package/.cursor/skills/close/SKILL.md +13 -0
  85. package/.cursor/skills/debug/SKILL.md +0 -1
  86. package/.cursor/skills/discovery/SKILL.md +0 -1
  87. package/.cursor/skills/dispatcher/SKILL.md +0 -1
  88. package/.cursor/skills/eli5/SKILL.md +0 -1
  89. package/.cursor/skills/evolve/SKILL.md +0 -1
  90. package/.cursor/skills/go/SKILL.md +13 -0
  91. package/.cursor/skills/grill/SKILL.md +0 -1
  92. package/.cursor/skills/harness-audit/SKILL.md +12 -0
  93. package/.cursor/skills/portfolio/SKILL.md +12 -0
  94. package/.cursor/skills/release/SKILL.md +13 -0
  95. package/.cursor/skills/repo-audit/SKILL.md +0 -1
  96. package/.cursor/skills/sunset-review/SKILL.md +0 -1
  97. package/.cursor/skills/test/SKILL.md +12 -0
  98. package/.cursor/skills/ux-grill/SKILL.md +0 -1
  99. package/.cursor-plugin/plugin.json +1 -1
  100. package/.orchestrator/policy/blocked-commands.json +1 -1
  101. package/AGENTS.md +1 -1
  102. package/CHANGELOG.md +61 -0
  103. package/README.md +11 -9
  104. package/commands/session.md +10 -0
  105. package/docs/ci-setup.md +53 -0
  106. package/docs/codex-setup.md +1 -1
  107. package/docs/components.md +11 -6
  108. package/docs/events-schema.md +4 -1
  109. package/docs/install.md +16 -0
  110. package/docs/persona-panel.md +1 -1
  111. package/docs/pi-setup.md +1 -1
  112. package/docs/rule-authoring.md +83 -14
  113. package/docs/scope-collision-guard.md +2 -0
  114. package/docs/session-config-reference.md +6 -4
  115. package/hooks/_lib/hook-import-set.json +46 -6
  116. package/hooks/_lib/subagent-paths.mjs +15 -0
  117. package/hooks/_lib/vcs-create-matcher.mjs +217 -62
  118. package/hooks/hooks-codex.json +1 -1
  119. package/hooks/hooks.json +1 -1
  120. package/hooks/on-session-end.mjs +14 -2
  121. package/hooks/on-stop.mjs +43 -1
  122. package/hooks/post-bash-write-verify.mjs +3 -0
  123. package/hooks/pre-auq-clarity.mjs +3 -0
  124. package/hooks/pre-bash-issue-budget.mjs +103 -17
  125. package/hooks/pre-task-scope-disjoint.mjs +152 -3
  126. package/hooks/skill-invocation-telemetry.mjs +2 -1
  127. package/package.json +2 -1
  128. package/pi/prompts/autopilot.md +3 -3
  129. package/pi/prompts/bootstrap.md +3 -3
  130. package/pi/prompts/brainstorm.md +3 -3
  131. package/pi/prompts/close.md +2 -2
  132. package/pi/prompts/convergence-monitoring.md +11 -0
  133. package/pi/prompts/debug.md +3 -3
  134. package/pi/prompts/discovery.md +3 -3
  135. package/pi/prompts/dispatcher.md +3 -3
  136. package/pi/prompts/eli5.md +3 -3
  137. package/pi/prompts/eval.md +3 -3
  138. package/pi/prompts/evolve.md +3 -3
  139. package/pi/prompts/go.md +2 -2
  140. package/pi/prompts/grill.md +3 -3
  141. package/pi/prompts/harness-audit.md +2 -3
  142. package/pi/prompts/memory-cleanup.md +3 -3
  143. package/pi/prompts/npm-publish.md +11 -0
  144. package/pi/prompts/persona-panel.md +3 -3
  145. package/pi/prompts/plan.md +3 -3
  146. package/pi/prompts/portfolio.md +2 -2
  147. package/pi/prompts/reconcile.md +3 -3
  148. package/pi/prompts/release.md +3 -3
  149. package/pi/prompts/repo-audit.md +3 -4
  150. package/pi/prompts/session.md +1 -1
  151. package/pi/prompts/spinout.md +3 -3
  152. package/pi/prompts/sunset-review.md +3 -3
  153. package/pi/prompts/templates-ack.md +1 -1
  154. package/pi/prompts/test.md +3 -3
  155. package/pi/prompts/ux-grill.md +3 -3
  156. package/scripts/archive-closed-prds.mjs +2 -2
  157. package/scripts/auq-audit.mjs +2 -3
  158. package/scripts/backfill-abandoned-sessions.mjs +57 -3
  159. package/scripts/backfill-evidence-digest.mjs +2 -1
  160. package/scripts/backfill-learnings-from-vault.mjs +2 -2
  161. package/scripts/check-package-manager.mjs +2 -2
  162. package/scripts/ci/assert-vitest-green.mjs +2 -1
  163. package/scripts/emit-session.mjs +2 -3
  164. package/scripts/export-hw-learnings.mjs +2 -1
  165. package/scripts/express-path.mjs +1 -1
  166. package/scripts/gc-stale-worktrees.mjs +2 -1
  167. package/scripts/generate-codex-skills.mjs +48 -4
  168. package/scripts/generate-cursor-adapter.mjs +173 -9
  169. package/scripts/generate-hook-import-set.mjs +12 -27
  170. package/scripts/generate-pi-prompts.mjs +183 -13
  171. package/scripts/github-protection-audit.mjs +2 -3
  172. package/scripts/lib/agent-frontmatter.mjs +23 -1
  173. package/scripts/lib/claude-md-budget-lint.mjs +2 -5
  174. package/scripts/lib/command-blocker.mjs +133 -5
  175. package/scripts/lib/config/drift-check.mjs +19 -0
  176. package/scripts/lib/convergence-monitor.mjs +2 -2
  177. package/scripts/lib/cursor-hook-bridge.mjs +2 -2
  178. package/scripts/lib/description-surface.mjs +2 -5
  179. package/scripts/lib/dispatcher/cli.mjs +2 -1
  180. package/scripts/lib/ecosystem-wizard.mjs +2 -1
  181. package/scripts/lib/fetch-baseline.mjs +3 -8
  182. package/scripts/lib/gitlab-ops/stale-mr-sweep.mjs +2 -1
  183. package/scripts/lib/gitlab-portfolio/cli.mjs +2 -1
  184. package/scripts/lib/instruction-budget-guard.mjs +186 -46
  185. package/scripts/lib/is-main-module.mjs +82 -0
  186. package/scripts/lib/locks/index.mjs +32 -25
  187. package/scripts/lib/maintenance-due-banner.mjs +69 -3
  188. package/scripts/lib/peer-discovery.mjs +2 -5
  189. package/scripts/lib/playwright-driver/runner.mjs +2 -1
  190. package/scripts/lib/reconcile/rule-expiry-sweep.mjs +642 -0
  191. package/scripts/lib/rules-sync.mjs +2 -5
  192. package/scripts/lib/scope-echo.mjs +392 -7
  193. package/scripts/lib/session-close-backfill.mjs +58 -6
  194. package/scripts/lib/state-md.mjs +84 -3
  195. package/scripts/lib/sunset/walker.mjs +31 -4
  196. package/scripts/lib/tests-src-ratio.mjs +2 -6
  197. package/scripts/lib/tmux-layout/telemetry-stats.mjs +2 -1
  198. package/scripts/lib/user-invocable-skills.mjs +185 -0
  199. package/scripts/lib/validate/check-banner-parity.mjs +2 -2
  200. package/scripts/lib/validate/check-cursor-adapter.mjs +2 -2
  201. package/scripts/lib/validate/check-dead-bridge.mjs +2 -2
  202. package/scripts/lib/validate/check-doc-cli-commands.mjs +2 -2
  203. package/scripts/lib/validate/check-entry-guard.mjs +366 -0
  204. package/scripts/lib/validate/check-guard-requires-parity.mjs +2 -2
  205. package/scripts/lib/validate/check-hooks-emit-event-guard.mjs +2 -2
  206. package/scripts/lib/validate/check-learning-provenance.mjs +2 -2
  207. package/scripts/lib/validate/check-skill-links.mjs +27 -6
  208. package/scripts/lib/validate/check-skill-script-paths.mjs +2 -2
  209. package/scripts/lib/validate/check-test-git-config-target.mjs +2 -2
  210. package/scripts/lib/validate/check-unicode-safety.mjs +2 -2
  211. package/scripts/lib/validate/check-untracked-test-deps.mjs +2 -2
  212. package/scripts/lib/validate/check-unwired-features.mjs +91 -7
  213. package/scripts/lib/validate/check-validator-registration.mjs +2 -2
  214. package/scripts/lib/validate/check-vcs-repo-flag.mjs +2 -2
  215. package/scripts/lib/validate-vendored-rules.mjs +35 -9
  216. package/scripts/lib/wave-transcript-tail.mjs +2 -2
  217. package/scripts/lock-reaper.mjs +2 -1
  218. package/scripts/materialize-wave-scope.mjs +87 -4
  219. package/scripts/migrate-sessions-jsonl.mjs +2 -1
  220. package/scripts/migrate-vault-paths.mjs +2 -3
  221. package/scripts/release.mjs +80 -35
  222. package/scripts/relocate-vault-corpus.mjs +2 -3
  223. package/scripts/repair-invalid-sessions.mjs +2 -2
  224. package/scripts/session-shape.mjs +2 -2
  225. package/scripts/site-numbers.mjs +35 -11
  226. package/scripts/sweep-expired-rules.mjs +216 -0
  227. package/scripts/validate-plugin.mjs +9 -0
  228. package/scripts/vault-consolidate.mjs +2 -2
  229. package/scripts/vault-mirror.mjs +2 -3
  230. package/scripts/wave-scope-binding.mjs +2 -3
  231. package/skills/_shared/bootstrap-gate.md +1 -1
  232. package/skills/_shared/monitor-patterns.md +1 -1
  233. package/skills/_shared/research-evidence.md +53 -0
  234. package/skills/_shared/state-ownership.md +3 -0
  235. package/skills/autopilot/SKILL.md +58 -4
  236. package/skills/bootstrap/SKILL.md +51 -1
  237. package/skills/brainstorm/SKILL.md +16 -0
  238. package/skills/claude-md-drift-check/checker.mjs +49 -11
  239. package/{commands/close.md → skills/close/SKILL.md} +9 -3
  240. package/skills/debug/SKILL.md +10 -0
  241. package/skills/discovery/SKILL.md +24 -1
  242. package/skills/discovery/probes-session.md +2 -2
  243. package/skills/dispatcher/SKILL.md +38 -7
  244. package/skills/eli5/SKILL.md +11 -0
  245. package/skills/eval/SKILL.md +14 -0
  246. package/skills/evolve/SKILL.md +8 -1
  247. package/skills/evolve/references/evolve-dialectic-mode.md +6 -2
  248. package/{commands/go.md → skills/go/SKILL.md} +9 -1
  249. package/skills/grill/SKILL.md +19 -0
  250. package/{commands/harness-audit.md → skills/harness-audit/SKILL.md} +7 -2
  251. package/skills/hook-development/SKILL.md +46 -41
  252. package/skills/memory-cleanup/SKILL.md +7 -0
  253. package/skills/npm-publish/SKILL.md +1 -1
  254. package/skills/persona-panel/SKILL.md +56 -1
  255. package/skills/persona-panel/persona-format.md +1 -1
  256. package/skills/plan/SKILL.md +28 -1
  257. package/{commands/portfolio.md → skills/portfolio/SKILL.md} +8 -2
  258. package/skills/reconcile/SKILL.md +10 -0
  259. package/{commands/release.md → skills/release/SKILL.md} +16 -2
  260. package/skills/repo-audit/SKILL.md +7 -0
  261. package/skills/session-end/plan-verification.md +2 -2
  262. package/skills/session-plan/SKILL.md +1 -1
  263. package/skills/session-start/SKILL.md +5 -4
  264. package/skills/session-start/phase-8-5-express-path.md +6 -6
  265. package/skills/session-start/references/phase-1-5-session-continuity.md +1 -1
  266. package/skills/session-start/references/phase-2-7-portfolio-snapshot.md +1 -1
  267. package/skills/session-start/references/phase-4-ssot-environment-check.md +4 -3
  268. package/skills/spinout/SKILL.md +12 -1
  269. package/skills/sunset-review/SKILL.md +13 -0
  270. package/{commands/test.md → skills/test/SKILL.md} +10 -4
  271. package/skills/ux-grill/SKILL.md +19 -1
  272. package/skills/wave-executor/SKILL.md +7 -4
  273. package/skills/wave-executor/references/wave-executor-state-init.md +13 -1
  274. package/skills/wave-executor/references/wave-loop-dispatch.md +3 -1
  275. package/skills/wave-executor/references/wave-loop-review.md +17 -1
  276. package/commands/autopilot.md +0 -80
  277. package/commands/bootstrap.md +0 -56
  278. package/commands/brainstorm.md +0 -48
  279. package/commands/debug.md +0 -36
  280. package/commands/discovery.md +0 -32
  281. package/commands/dispatcher.md +0 -59
  282. package/commands/eli5.md +0 -33
  283. package/commands/eval.md +0 -28
  284. package/commands/evolve.md +0 -10
  285. package/commands/grill.md +0 -45
  286. package/commands/memory-cleanup.md +0 -26
  287. package/commands/persona-panel.md +0 -121
  288. package/commands/plan.md +0 -15
  289. package/commands/reconcile.md +0 -23
  290. package/commands/repo-audit.md +0 -24
  291. package/commands/spinout.md +0 -15
  292. package/commands/sunset-review.md +0 -27
  293. package/commands/ux-grill.md +0 -51
@@ -1,12 +1,11 @@
1
1
  ---
2
- description: Run a 9-category baseline compliance audit on the current repository
3
- argument-hint: ""
2
+ description: "Use this skill when the user wants to audit a repository for baseline compliance, check code quality, security posture, CI/CD setup, testing, documentation, and ecosystem configuration. Runs 9 checklist categories and emits a Markdown report plus JSON sidecar at .orchestrator/metrics/repo-audit-<timestamp>.json. <example>Context: User is in a project repo and wants a baseline compliance check. user: \"/repo-audit\" assistant: \"Running repo-audit across 9 categories — Configuration, Code Quality, Git Hygiene, CI/CD, Testing, Security, Documentation, Clank Integration (optional), and MCP Configuration. Will produce a Markdown checklist report and JSON sidecar.\" <commentary>The user wants a compliance check; this skill is appropriate because it runs all 9 categories with pass/fail/warn/skipped statuses and writes structured output.</commentary></example>"
4
3
  ---
5
4
 
6
5
  # /repo-audit
7
6
 
8
- Use the Session Orchestrator command definition at `commands/repo-audit.md`.
7
+ Use the Session Orchestrator skill definition at `skills/repo-audit/SKILL.md`.
9
8
 
10
9
  Arguments: $@
11
10
 
12
- Read that command file and follow it exactly. When it references `$ARGUMENTS`, substitute the arguments above. Keep all Session Orchestrator platform fallbacks intact.
11
+ Read that skill file and follow it exactly. When it references `$ARGUMENTS`, substitute the arguments above. Keep all Session Orchestrator platform fallbacks intact.
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: Start a development session (housekeeping, feature, deep; ultradeep = deep + profile)
2
+ description: "Start a development session (housekeeping, feature, deep; ultradeep = deep + profile)"
3
3
  argument-hint: "[housekeeping|feature|deep|ultradeep]"
4
4
  ---
5
5
 
@@ -1,12 +1,12 @@
1
1
  ---
2
- description: Guided 5-step venture-spinout / sanitized-fork runbook (copy + fresh-init + SNAPSHOT-FREEZE) interactive, not scripted
2
+ description: "Use when extracting a project into its own repo — a venture spinout (e.g. a product leaving its incubator repo) or a sanitized content-snapshot fork. Guided 5-step runbook: target sphere + path, confidentiality/sanitize check, copy + fresh git init, SNAPSHOT-FREEZE marker in the source repo, remotes + registration. Trigger on 'spin out X', 'extract this into its own repo', 'fork X sanitized'."
3
3
  argument-hint: "[--type venture|snapshot] [--dry-run]"
4
4
  ---
5
5
 
6
6
  # /spinout
7
7
 
8
- Use the Session Orchestrator command definition at `commands/spinout.md`.
8
+ Use the Session Orchestrator skill definition at `skills/spinout/SKILL.md`.
9
9
 
10
10
  Arguments: $@
11
11
 
12
- Read that command file and follow it exactly. When it references `$ARGUMENTS`, substitute the arguments above. Keep all Session Orchestrator platform fallbacks intact.
12
+ Read that skill file and follow it exactly. When it references `$ARGUMENTS`, substitute the arguments above. Keep all Session Orchestrator platform fallbacks intact.
@@ -1,12 +1,12 @@
1
1
  ---
2
- description: Identify unused / near-zero-use / stale skills, agents, and commands as Demote or Retire candidates (read-only; never deletes)
2
+ description: "Use this skill when the user wants to identify unused, near-zero-use, or stale skills/agents/commands in the plugin surface so they can be demoted or retired. Combines agent-dispatch telemetry (start-events only) with static reference scanning, classifies every surface item into Active / Investigate / Demote / Retire, and emits a Markdown report plus JSON sidecar. NEVER auto-deletes — surfaces candidates for human decision. Quarterly cadence. <example>Context: The plugin surface has grown and the maintainer wants to prune dead weight. user: \"/sunset-review\" assistant: \"Running the sunset walk — classifying skills, agents, and commands by usage telemetry + static refs, grouped by Retire / Demote / Investigate / Active. No item is deleted automatically; I'll surface Retire/Demote candidates for your decision.\" <commentary>The user wants a usage-driven prune candidate list; this skill runs the read-only walker, presents grouped verdicts, and writes a sidecar — it never deletes.</commentary></example>"
3
3
  argument-hint: "[--kind skill|agent|command] [--window-days N]"
4
4
  ---
5
5
 
6
6
  # /sunset-review
7
7
 
8
- Use the Session Orchestrator command definition at `commands/sunset-review.md`.
8
+ Use the Session Orchestrator skill definition at `skills/sunset-review/SKILL.md`.
9
9
 
10
10
  Arguments: $@
11
11
 
12
- Read that command file and follow it exactly. When it references `$ARGUMENTS`, substitute the arguments above. Keep all Session Orchestrator platform fallbacks intact.
12
+ Read that skill file and follow it exactly. When it references `$ARGUMENTS`, substitute the arguments above. Keep all Session Orchestrator platform fallbacks intact.
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: Acknowledge templates-first policy for the current session — bypasses the pre-bash-templates-first hook for the remainder of the session
2
+ description: "Acknowledge templates-first policy for the current session — bypasses the pre-bash-templates-first hook for the remainder of the session"
3
3
  argument-hint: "[optional-reason]"
4
4
  ---
5
5
 
@@ -1,12 +1,12 @@
1
1
  ---
2
- description: Agentic end-to-end test orchestrator — drive web/macOS flows, evaluate UX rubric, reconcile issues
2
+ description: "Agentic end-to-end test orchestrator — drive web/macOS flows, evaluate UX rubric, reconcile issues"
3
3
  argument-hint: "[scope|profile-name] [--since <git-ref>] [--full]"
4
4
  ---
5
5
 
6
6
  # /test
7
7
 
8
- Use the Session Orchestrator command definition at `commands/test.md`.
8
+ Use the Session Orchestrator skill definition at `skills/test/SKILL.md`.
9
9
 
10
10
  Arguments: $@
11
11
 
12
- Read that command file and follow it exactly. When it references `$ARGUMENTS`, substitute the arguments above. Keep all Session Orchestrator platform fallbacks intact.
12
+ Read that skill file and follow it exactly. When it references `$ARGUMENTS`, substitute the arguments above. Keep all Session Orchestrator platform fallbacks intact.
@@ -1,12 +1,12 @@
1
1
  ---
2
- description: Grill a running web app's UX — a deterministic mechanical pass (axe, target size, overflow, journeys) followed by a screenshot-grounded interrogation of the operator.
2
+ description: "Use when a running web app's UX has to be audited reproducibly rather than by feel — a deterministic mechanical pass over routes and viewports (axe, target size, horizontal overflow, page title, scripted journeys) followed by a screenshot-grounded interrogation of the operator, journey by journey, with two persona lenses from the target repo's manifest. Triggered by \"grill the UX\", \"roast the dashboard\", \"UX-Audit\", \"/ux-grill\". Bootstraps its own manifest from a loopback URL on the first run, so it never requires a hand-written file to start."
3
3
  argument-hint: "[url | manifest-path]"
4
4
  ---
5
5
 
6
6
  # /ux-grill
7
7
 
8
- Use the Session Orchestrator command definition at `commands/ux-grill.md`.
8
+ Use the Session Orchestrator skill definition at `skills/ux-grill/SKILL.md`.
9
9
 
10
10
  Arguments: $@
11
11
 
12
- Read that command file and follow it exactly. When it references `$ARGUMENTS`, substitute the arguments above. Keep all Session Orchestrator platform fallbacks intact.
12
+ Read that skill file and follow it exactly. When it references `$ARGUMENTS`, substitute the arguments above. Keep all Session Orchestrator platform fallbacks intact.
@@ -41,7 +41,6 @@
41
41
 
42
42
  import { readFileSync } from 'node:fs';
43
43
  import { spawnSync } from 'node:child_process';
44
- import { pathToFileURL } from 'node:url';
45
44
  import { join } from 'node:path';
46
45
 
47
46
  import { findProjectRoot, resolveInstructionFile, warn } from './lib/common.mjs';
@@ -52,6 +51,7 @@ import { defaultGlabRepo } from './lib/vcs-repo-spec.mjs';
52
51
  import { readLock } from './lib/session-lock.mjs';
53
52
  import { resolveStateMdPath } from './lib/state-md/frontmatter-mutators.mjs';
54
53
  import { parseStateMd } from './lib/state-md/yaml-parser.mjs';
54
+ import { isMainModule } from './lib/is-main-module.mjs';
55
55
 
56
56
  const DEFAULT_PRD_DIR = 'docs/prd';
57
57
  const DEFAULT_VAULT_SUBDIR = '01-projects/session-orchestrator/prd';
@@ -635,7 +635,7 @@ export function main({
635
635
  // CLI guard — prevents process.exit during test-time imports
636
636
  // ---------------------------------------------------------------------------
637
637
 
638
- if (process.argv[1] !== undefined && import.meta.url === pathToFileURL(process.argv[1]).href) {
638
+ if (isMainModule(import.meta.url)) {
639
639
  try {
640
640
  const { code } = main();
641
641
  process.exit(code ?? 0);
@@ -76,6 +76,7 @@ import {
76
76
  } from './lib/auq/schema.mjs';
77
77
  import { corpusKindOf, parseRepo } from './lib/auq/parse.mjs';
78
78
  import { writeStdoutLineSync } from './lib/io.mjs';
79
+ import { isMainModule } from './lib/is-main-module.mjs';
79
80
 
80
81
  const HERE = path.dirname(fileURLToPath(import.meta.url));
81
82
  const REPO_ROOT_DEFAULT = path.resolve(HERE, '..');
@@ -818,8 +819,6 @@ function pkgVersion() {
818
819
  }
819
820
  }
820
821
 
821
- const invokedDirectly =
822
- process.argv[1] !== undefined &&
823
- path.resolve(process.argv[1]) === path.resolve(fileURLToPath(import.meta.url));
822
+ const invokedDirectly =isMainModule(import.meta.url);
824
823
 
825
824
  if (invokedDirectly) main();
@@ -39,11 +39,13 @@
39
39
  import fs from 'node:fs';
40
40
  import path from 'node:path';
41
41
  import { parseArgs } from 'node:util';
42
- import { fileURLToPath } from 'node:url';
43
42
 
44
43
  import { backfillAbandonedSession, isUuid } from './lib/session-close-backfill.mjs';
45
44
  import { emitEvent } from './lib/events.mjs';
46
45
  import { getProjectDir } from './lib/platform.mjs';
46
+ import { isMainModule } from './lib/is-main-module.mjs';
47
+ import { isLockLive, readLock } from './lib/session-lock.mjs';
48
+ import { readProcessLocalSessionIds } from './lib/session-identity/own-session.mjs';
47
49
 
48
50
  const LOCK_ACQUIRED = 'orchestrator.session.lock.acquired';
49
51
  const SESSION_STARTED = 'orchestrator.session.started';
@@ -101,6 +103,24 @@ function readJsonl(filePath) {
101
103
  * session.started UUID, each bridged to its semantic id via lock.acquired
102
104
  * where one exists. Preserves first-seen order.
103
105
  *
106
+ * THIS VERY PROCESS is excluded (#1376). The shared core's own
107
+ * `skipped-own-live-lock` branch used to carry that job alone, but it is now
108
+ * defeasible: `ownSessionIsEnding` lets the SessionEnd hook record its own
109
+ * session, so the CLI must not depend on a branch whose meaning the caller
110
+ * chooses. The exclusion needs THREE conjuncts, and dropping any one of them
111
+ * breaks it in a different direction:
112
+ * 1. the candidate names the lock (by either id, including the #863 (d)
113
+ * lock shape that stores the semantic id in `session_id`),
114
+ * 2. the lock is LIVE — a stale lock names a session nobody is running, and
115
+ * reconstructing it is exactly this CLI's job, and
116
+ * 3. a PROCESS-LOCAL id (hook payload / harness env, never the repo-global
117
+ * lock — see `readProcessLocalSessionIds`) matches the lock, which is
118
+ * what distinguishes THIS process from a PEER's running session in the
119
+ * same working copy. Without it the repo-global lock would vouch for
120
+ * itself and a peer's live session would read as "me".
121
+ * A peer's live session is NOT excluded here and does not need to be: the core
122
+ * still rejects it through the untouched own/foreign live-lock guards.
123
+ *
104
124
  * @param {{ repoRoot: string }} args
105
125
  * @returns {Array<{ sessionId: string, semanticSessionId: string|null }>}
106
126
  */
@@ -124,17 +144,51 @@ export function planSessions({ repoRoot }) {
124
144
  }
125
145
  const semanticByUuid = new Map([...semanticFromEnded, ...semanticFromLock]);
126
146
 
147
+ const runningIds = readRunningSessionIds(repoRoot);
148
+
127
149
  const seen = new Set();
128
150
  const plan = [];
129
151
  for (const ev of events) {
130
152
  if (ev.event !== SESSION_STARTED || typeof ev.session_id !== 'string') continue;
131
153
  if (seen.has(ev.session_id)) continue;
132
154
  seen.add(ev.session_id);
133
- plan.push({ sessionId: ev.session_id, semanticSessionId: semanticByUuid.get(ev.session_id) ?? null });
155
+ const semanticSessionId = semanticByUuid.get(ev.session_id) ?? null;
156
+ if (runningIds.has(ev.session_id)
157
+ || (semanticSessionId !== null && runningIds.has(semanticSessionId))) continue;
158
+ plan.push({ sessionId: ev.session_id, semanticSessionId });
134
159
  }
135
160
  return plan;
136
161
  }
137
162
 
163
+ /**
164
+ * The id(s) naming the session THIS process is, when that session holds the
165
+ * live lock — else the empty set (#1376). Never throws: an unreadable lock,
166
+ * an absent one, or an env without any process-local id all degrade to "no
167
+ * exclusion", which is the pre-#1376 behaviour.
168
+ *
169
+ * @param {string} repoRoot
170
+ * @returns {Set<string>}
171
+ */
172
+ function readRunningSessionIds(repoRoot) {
173
+ const ids = new Set();
174
+ try {
175
+ const lock = readLock({ repoRoot });
176
+ if (!lock || !isLockLive(lock)) return ids;
177
+ const lockIds = [lock.session_id, lock.semantic_session_id]
178
+ .filter((id) => typeof id === 'string' && id.length > 0);
179
+ const processLocal = new Set(readProcessLocalSessionIds());
180
+ // Conjunct 3 — only a PROCESS-LOCAL witness may promote the repo-global
181
+ // lock to "this is me". Membership is tested against the lock's ids, not
182
+ // the other way round, so an env var that happens to name some other
183
+ // session never widens the exclusion.
184
+ if (!lockIds.some((id) => processLocal.has(id))) return ids;
185
+ for (const id of lockIds) ids.add(id);
186
+ } catch {
187
+ /* readLock is no-throw by contract; the contract is not ours to trust */
188
+ }
189
+ return ids;
190
+ }
191
+
138
192
  /**
139
193
  * Cheap pre-filter (#926): the set of session ids ALREADY present in
140
194
  * sessions.jsonl.
@@ -527,7 +581,7 @@ async function main() {
527
581
  process.exit(0);
528
582
  }
529
583
 
530
- const isDirectRun = process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1];
584
+ const isDirectRun = isMainModule(import.meta.url);
531
585
  if (isDirectRun) {
532
586
  main().catch((err) => {
533
587
  process.stderr.write(`backfill-abandoned-sessions: unexpected error: ${err?.stack ?? err}\n`);
@@ -50,6 +50,7 @@ import { existsSync, readFileSync, readdirSync, writeFileSync } from 'node:fs';
50
50
  import { join, relative, resolve } from 'node:path';
51
51
 
52
52
  import { computeEvidenceDigest } from './lib/reconcile/renderer.mjs';
53
+ import { isMainModule } from './lib/is-main-module.mjs';
53
54
 
54
55
  /** ISO-8601 instant — mirrors the renderer's `EVIDENCE_RECORDED_AT_RE`. */
55
56
  const EVIDENCE_RECORDED_AT_RE = /^\d{4}-\d{2}-\d{2}T[0-9:.]+(?:Z|[+-]\d{2}:\d{2})$/;
@@ -373,4 +374,4 @@ function main(argv) {
373
374
  process.exit(unsealable === 0 ? 0 : 1);
374
375
  }
375
376
 
376
- if (import.meta.url === `file://${process.argv[1]}`) main(process.argv.slice(2));
377
+ if (isMainModule(import.meta.url)) main(process.argv.slice(2));
@@ -64,7 +64,6 @@
64
64
 
65
65
  import { readFileSync, readdirSync, existsSync } from 'node:fs';
66
66
  import { join, resolve, dirname, basename, relative } from 'node:path';
67
- import { pathToFileURL } from 'node:url';
68
67
 
69
68
  import { findProjectRoot, resolveInstructionFile, expandTilde } from './lib/common.mjs';
70
69
  import { parseSessionConfig } from './lib/config.mjs';
@@ -72,6 +71,7 @@ import { subjectToSlug, parseFrontmatter } from './lib/vault-mirror/utils.mjs';
72
71
  import { kebab } from './lib/learnings/kebab.mjs';
73
72
  import { validateLearning } from './lib/learnings/schema.mjs';
74
73
  import { appendLearning, isBackupOf } from './lib/learnings/io.mjs';
74
+ import { isMainModule } from './lib/is-main-module.mjs';
75
75
 
76
76
  const DEFAULT_RULES_DIR = '.claude/rules';
77
77
  const DEFAULT_STORE = '.orchestrator/metrics/learnings.jsonl';
@@ -962,7 +962,7 @@ export async function main(argv = [], deps = {}) {
962
962
  }
963
963
 
964
964
  /* c8 ignore start — CLI entrypoint */
965
- if (import.meta.url === pathToFileURL(process.argv[1] ?? '').href) {
965
+ if (isMainModule(import.meta.url)) {
966
966
  main(process.argv.slice(2))
967
967
  .then(({ code }) => process.exit(code))
968
968
  .catch((err) => {
@@ -67,6 +67,7 @@ import { existsSync, lstatSync, readFileSync } from 'node:fs';
67
67
  import { dirname, join, resolve } from 'node:path';
68
68
  import { spawnSync } from 'node:child_process';
69
69
  import { fileURLToPath } from 'node:url';
70
+ import { isMainModule } from './lib/is-main-module.mjs';
70
71
 
71
72
  const SELF_DIR = dirname(fileURLToPath(import.meta.url));
72
73
 
@@ -388,8 +389,7 @@ function parseArgs(argv) {
388
389
  }
389
390
 
390
391
  // CLI entry — only when run directly, not when imported (e.g. by tests).
391
- const isMain =
392
- process.argv[1] !== undefined && resolve(process.argv[1]) === fileURLToPath(import.meta.url);
392
+ const isMain =isMainModule(import.meta.url);
393
393
 
394
394
  if (isMain) {
395
395
  const { opts, unknown } = parseArgs(process.argv.slice(2));
@@ -50,6 +50,7 @@
50
50
  // the existing bare message and the exit-code contract is unchanged.
51
51
 
52
52
  import { readFileSync } from 'node:fs';
53
+ import { isMainModule } from '../lib/is-main-module.mjs';
53
54
 
54
55
  const DEFAULT_MIN_TESTS = 5000;
55
56
 
@@ -232,7 +233,7 @@ function parseArgs(argv) {
232
233
  }
233
234
 
234
235
  // CLI entry — only when run directly, not when imported by tests.
235
- const isMain = import.meta.url === `file://${process.argv[1]}`;
236
+ const isMain =isMainModule(import.meta.url);
236
237
  if (isMain) {
237
238
  const { path, minTests, logPath } = parseArgs(process.argv.slice(2));
238
239
  if (!path) {
@@ -26,7 +26,6 @@
26
26
 
27
27
  import { existsSync, readFileSync } from 'node:fs';
28
28
  import { dirname, join } from 'node:path';
29
- import { fileURLToPath } from 'node:url';
30
29
  import { appendJsonl } from './lib/common.mjs';
31
30
  import {
32
31
  MEMORY_CLEANUP_EVENT,
@@ -42,6 +41,7 @@ import {
42
41
  clampTimestampsMonotonic,
43
42
  aliasLegacyEndedAt,
44
43
  } from './lib/session-schema.mjs';
44
+ import { isMainModule } from './lib/is-main-module.mjs';
45
45
 
46
46
  export { serializeSessionLineChecked };
47
47
 
@@ -277,8 +277,7 @@ async function main() {
277
277
  // not when imported as a module (e.g. by tests that exercise the exported
278
278
  // serializeSessionLineChecked seam — #662). Without this guard, importing the
279
279
  // module would block on stdin / exit the test process.
280
- const _isDirectRun =
281
- process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1];
280
+ const _isDirectRun =isMainModule(import.meta.url);
282
281
 
283
282
  if (_isDirectRun) {
284
283
  main().catch((err) => {
@@ -63,6 +63,7 @@ import { parseSessionConfig } from './lib/config.mjs';
63
63
  import { createSecretValueMasker } from './lib/secret-masker.mjs';
64
64
  import { stableHostname, readHostAliases } from './lib/host-identity.mjs';
65
65
  import { emitEvent, sessionAttribution } from './lib/events.mjs';
66
+ import { isMainModule } from './lib/is-main-module.mjs';
66
67
 
67
68
  // Vault-relative default write target (Epic #774 — docs Public-Split removed
68
69
  // the prior in-repo generated telemetry doc in favor of the private Meta-Vault).
@@ -724,7 +725,7 @@ export async function exportHwLearnings(opts) {
724
725
  }
725
726
 
726
727
  // Run as CLI when invoked directly
727
- const isMain = import.meta.url === `file://${process.argv[1]}`;
728
+ const isMain =isMainModule(import.meta.url);
728
729
  if (isMain) {
729
730
  const opts = parseArgs(process.argv.slice(2));
730
731
 
@@ -281,7 +281,7 @@ async function main() {
281
281
 
282
282
  // The banner the coordinator echoes into the transcript — `/go` and
283
283
  // session-plan's Express Path Short-Circuit both key off this EXACT line
284
- // (`commands/go.md` § Express Path Detection), so it is written verbatim,
284
+ // (`skills/go/SKILL.md` § Express Path Detection), so it is written verbatim,
285
285
  // without the `express-path:` diagnostic prefix. Still stderr: stdout belongs
286
286
  // to the verdict.
287
287
  if (verdict.activated) {
@@ -26,6 +26,7 @@ import os from 'node:os';
26
26
  import path from 'node:path';
27
27
 
28
28
  import { validateWorkspacePath } from './lib/worktree/lifecycle.mjs';
29
+ import { isMainModule } from './lib/is-main-module.mjs';
29
30
 
30
31
  // ---------------------------------------------------------------------------
31
32
  // Constants
@@ -658,7 +659,7 @@ EXIT CODES
658
659
  // CLI guard — prevents process.exit during test-time imports (#368)
659
660
  // ---------------------------------------------------------------------------
660
661
 
661
- if (import.meta.url === `file://${process.argv[1]}`) {
662
+ if (isMainModule(import.meta.url)) {
662
663
  main().catch((err) => {
663
664
  process.stderr.write(`gc-stale-worktrees: unexpected error: ${err?.stack ?? err}\n`);
664
665
  process.exit(2);
@@ -9,6 +9,7 @@ import { dirname, join, resolve } from 'node:path';
9
9
  import { fileURLToPath } from 'node:url';
10
10
  import yaml from 'js-yaml';
11
11
  import { toPortableFrontmatter } from './generate-agents-skills.mjs';
12
+ import { isUserInvocableValue } from './lib/user-invocable-skills.mjs';
12
13
 
13
14
  const OUTPUT = '.codex-plugin/skills';
14
15
  const MARKER = 'Generated by scripts/generate-codex-skills.mjs; do not edit.';
@@ -26,8 +27,19 @@ function validateFrontmatter(fm, name, path) {
26
27
  if (typeof fm.description !== 'string' || !fm.description.trim() || fm.description.trim().length > 1024) {
27
28
  fail('description must be a non-empty string of at most 1024 characters');
28
29
  }
29
- for (const key of ['disable-model-invocation', 'user-invocable']) {
30
- if (Object.hasOwn(fm, key) && typeof fm[key] !== 'boolean') fail(`${key} must be a boolean`);
30
+ if (Object.hasOwn(fm, 'disable-model-invocation') && typeof fm['disable-model-invocation'] !== 'boolean') {
31
+ fail('disable-model-invocation must be a boolean');
32
+ }
33
+ // `user-invocable` is deliberately NOT a hard fail on a non-boolean: a quoted
34
+ // or cased value (`"true"`, `True`) used to crash this generator while the
35
+ // Cursor and Pi generators emitted a wrapper for it and the counters ignored
36
+ // it — four readings of one key. `isUserInvocableValue` is now the single
37
+ // normaliser; a value it cannot read as `true` demotes the skill (with its own
38
+ // WARN for the truthy-looking cases) instead of stopping the build.
39
+ if (Object.hasOwn(fm, 'user-invocable')
40
+ && typeof fm['user-invocable'] !== 'boolean'
41
+ && typeof fm['user-invocable'] !== 'string') {
42
+ fail('user-invocable must be a boolean (or the string form `"true"`/`"false"`)');
31
43
  }
32
44
  for (const key of ['argument-hint', 'license', 'compatibility']) {
33
45
  if (Object.hasOwn(fm, key) && typeof fm[key] !== 'string') fail(`${key} must be a string`);
@@ -42,6 +54,19 @@ function validateFrontmatter(fm, name, path) {
42
54
  }
43
55
  }
44
56
 
57
+ /**
58
+ * The repo-wide marker for "operator-facing slash command" — delegated to
59
+ * `isUserInvocableValue`, the ONE normaliser, so this generator, the Cursor and
60
+ * Pi generators and the counters cannot disagree about a quoted or cased value.
61
+ *
62
+ * @param {Record<string, unknown>} fm
63
+ * @param {string} [path] named in the shared WARN when a truthy-looking value is demoted
64
+ * @returns {boolean}
65
+ */
66
+ function isUserInvocable(fm, path) {
67
+ return isUserInvocableValue(fm?.['user-invocable'], path);
68
+ }
69
+
45
70
  /** Existing native policy is meaningful; Claude's user-invocable flag is not a substitute. */
46
71
  function readNativePolicy(root, name) {
47
72
  const path = `skills/${name}/agents/openai.yaml`;
@@ -80,7 +105,14 @@ function readSources(root) {
80
105
  try { fm = yaml.load(match[1], { schema: yaml.CORE_SCHEMA }); }
81
106
  catch (error) { throw new Error(`${path}: invalid YAML: ${error.message}`, { cause: error }); }
82
107
  validateFrontmatter(fm, name, path);
83
- sources.push({ name, path, command, fm, policy: command ? fm['disable-model-invocation'] !== true : readNativePolicy(root, name) });
108
+ // Policy precedence for a skill: a native `agents/openai.yaml` wins; else
109
+ // an explicitly user-invocable skill (a slash command that used to be a
110
+ // `commands/*.md` file) derives it from `disable-model-invocation` exactly
111
+ // as command sources do; a library skill emits no policy.
112
+ const policy = command
113
+ ? fm['disable-model-invocation'] !== true
114
+ : (readNativePolicy(root, name) ?? (isUserInvocable(fm, path) ? fm['disable-model-invocation'] !== true : undefined));
115
+ sources.push({ name, path, command, fm, policy });
84
116
  }
85
117
  }
86
118
  return sources;
@@ -128,9 +160,21 @@ function renderSkill(source, warnings) {
128
160
  '',
129
161
  'Resolve this link relative to this SKILL.md, not the project working directory. The plugin root is three directories above this file. Resolve package paths such as `skills/` and `scripts/` from that root; resolve relative links inside the canonical document from its own directory. Keep the user’s project as the target of project operations.',
130
162
  ];
131
- if (source.command) lines.push(
163
+ // `$ARGUMENTS` semantics belong to every OPERATOR-FACING document — a
164
+ // `commands/*.md`, and equally a skill that declares `user-invocable: true`
165
+ // and references `$ARGUMENTS` in its own body. Gating them on `source.command`
166
+ // alone silently dropped the argument-handling contract from every command
167
+ // body that was folded into its same-named skill.
168
+ if (source.command || isUserInvocable(source.fm)) lines.push(
132
169
  '',
133
170
  '`$ARGUMENTS` means the trailing user input after the selected command skill, or an empty string when absent. Preserve flags, quoted text, and Unicode as data. Do not perform global substitution in the command document, shell expansion on the argument string, or execution of that string as shell code. When the workflow needs a command, pass its arguments through structured tool parameters or safely quoted individual arguments.',
171
+ );
172
+ // The redispatch warning is only TRUE for a command source: it exists because
173
+ // a same-named command and internal skill are two distinct documents. A
174
+ // user-invocable SKILL is already the canonical document, so telling it not to
175
+ // redispatch "the public command adapter" would describe a file that does not
176
+ // exist.
177
+ if (source.command) lines.push(
134
178
  '',
135
179
  'Read the full command before invoking an internal skill. An instruction to invoke a skill (including `session-orchestrator:<name>` or the `Skill` tool) means read and follow the canonical `skills/<name>/SKILL.md` beneath the plugin root. Do not redispatch the public command adapter: a same-named command and internal skill are distinct documents, and redispatch would recurse.',
136
180
  );