session-orchestrator 3.21.0 → 3.23.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 (345) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.codex-plugin/plugin.json +1 -1
  4. package/.cursor/commands/autopilot-multi.md +14 -0
  5. package/.cursor/commands/autopilot.md +14 -0
  6. package/.cursor/commands/bootstrap.md +14 -0
  7. package/.cursor/commands/brainstorm.md +14 -0
  8. package/.cursor/commands/close.md +13 -0
  9. package/.cursor/commands/contract-version-bump.md +14 -0
  10. package/.cursor/commands/debug.md +14 -0
  11. package/.cursor/commands/discovery.md +14 -0
  12. package/.cursor/commands/dispatcher.md +14 -0
  13. package/.cursor/commands/eli5.md +14 -0
  14. package/.cursor/commands/eval.md +14 -0
  15. package/.cursor/commands/evolve.md +14 -0
  16. package/.cursor/commands/go.md +14 -0
  17. package/.cursor/commands/grill.md +14 -0
  18. package/.cursor/commands/harness-audit.md +13 -0
  19. package/.cursor/commands/journey-audit.md +14 -0
  20. package/.cursor/commands/memory-cleanup.md +14 -0
  21. package/.cursor/commands/persona-panel.md +14 -0
  22. package/.cursor/commands/plan.md +14 -0
  23. package/.cursor/commands/portfolio.md +14 -0
  24. package/.cursor/commands/reconcile.md +14 -0
  25. package/.cursor/commands/release.md +14 -0
  26. package/.cursor/commands/repo-audit.md +13 -0
  27. package/.cursor/commands/session.md +14 -0
  28. package/.cursor/commands/spinout.md +14 -0
  29. package/.cursor/commands/sunset-review.md +14 -0
  30. package/.cursor/commands/templates-ack.md +14 -0
  31. package/.cursor/commands/test.md +14 -0
  32. package/.cursor/hooks.json +60 -0
  33. package/.cursor/rules/000-session-orchestrator.mdc +11 -2
  34. package/.cursor/rules/010-session-workflow.mdc +9 -1
  35. package/.cursor/rules/020-quality-gates.mdc +1 -1
  36. package/.cursor/rules/030-wave-execution.mdc +1 -1
  37. package/.cursor/rules/040-discovery.mdc +6 -6
  38. package/.cursor/rules/050-plan.mdc +10 -10
  39. package/.cursor/rules/070-gitlab-ops.mdc +73 -57
  40. package/.cursor/rules/080-ecosystem-health.mdc +7 -7
  41. package/.cursor/skills/architecture/SKILL.md +13 -0
  42. package/.cursor/skills/autopilot/SKILL.md +12 -0
  43. package/.cursor/skills/bootstrap/SKILL.md +12 -0
  44. package/.cursor/skills/brainstorm/SKILL.md +13 -0
  45. package/.cursor/skills/claude-md-drift-check/SKILL.md +13 -0
  46. package/.cursor/skills/contract-version-bump/SKILL.md +12 -0
  47. package/.cursor/skills/convergence-monitoring/SKILL.md +12 -0
  48. package/.cursor/skills/daily/SKILL.md +12 -0
  49. package/.cursor/skills/debug/SKILL.md +13 -0
  50. package/.cursor/skills/discovery/SKILL.md +13 -0
  51. package/.cursor/skills/dispatcher/SKILL.md +13 -0
  52. package/.cursor/skills/docs-orchestrator/SKILL.md +13 -0
  53. package/.cursor/skills/domain-model/SKILL.md +13 -0
  54. package/.cursor/skills/ecosystem-health/SKILL.md +13 -0
  55. package/.cursor/skills/eli5/SKILL.md +13 -0
  56. package/.cursor/skills/eval/SKILL.md +12 -0
  57. package/.cursor/skills/evolve/SKILL.md +13 -0
  58. package/.cursor/skills/frontmatter-guard/SKILL.md +13 -0
  59. package/.cursor/skills/gitlab-ops/SKILL.md +13 -0
  60. package/.cursor/skills/gitlab-portfolio/SKILL.md +13 -0
  61. package/.cursor/skills/grill/SKILL.md +13 -0
  62. package/.cursor/skills/hook-development/SKILL.md +13 -0
  63. package/.cursor/skills/journey-audit/SKILL.md +13 -0
  64. package/.cursor/skills/mcp-builder/SKILL.md +13 -0
  65. package/.cursor/skills/memory-cleanup/SKILL.md +12 -0
  66. package/.cursor/skills/mode-selector/SKILL.md +13 -0
  67. package/.cursor/skills/npm-publish/SKILL.md +12 -0
  68. package/.cursor/skills/peekaboo-driver/SKILL.md +13 -0
  69. package/.cursor/skills/persona-panel/SKILL.md +12 -0
  70. package/.cursor/skills/plan/SKILL.md +13 -0
  71. package/.cursor/skills/playwright-driver/SKILL.md +13 -0
  72. package/.cursor/skills/quality-gates/SKILL.md +13 -0
  73. package/.cursor/skills/reconcile/SKILL.md +12 -0
  74. package/.cursor/skills/repo-audit/SKILL.md +13 -0
  75. package/.cursor/skills/session-end/SKILL.md +13 -0
  76. package/.cursor/skills/session-plan/SKILL.md +13 -0
  77. package/.cursor/skills/session-start/SKILL.md +13 -0
  78. package/.cursor/skills/skill-creator/SKILL.md +13 -0
  79. package/.cursor/skills/spinout/SKILL.md +12 -0
  80. package/.cursor/skills/sunset-review/SKILL.md +13 -0
  81. package/.cursor/skills/test-runner/SKILL.md +13 -0
  82. package/.cursor/skills/tmux-layout/SKILL.md +13 -0
  83. package/.cursor/skills/ubiquitous-language/SKILL.md +13 -0
  84. package/.cursor/skills/using-orchestrator/SKILL.md +13 -0
  85. package/.cursor/skills/vault-mirror/SKILL.md +13 -0
  86. package/.cursor/skills/vault-sync/SKILL.md +13 -0
  87. package/.cursor/skills/wave-executor/SKILL.md +13 -0
  88. package/.cursor/skills/write-executable-plan/SKILL.md +13 -0
  89. package/.mcp.json +4 -1
  90. package/CHANGELOG.md +269 -0
  91. package/README.md +18 -15
  92. package/agents/AGENTS.md +23 -4
  93. package/agents/code-implementer.md +2 -1
  94. package/agents/db-specialist.md +2 -1
  95. package/agents/docs-writer.md +3 -1
  96. package/agents/eval-judge.md +1 -1
  97. package/agents/memory-proposal-collector.md +6 -4
  98. package/agents/session-reviewer.md +7 -1
  99. package/agents/test-writer.md +2 -1
  100. package/agents/ui-developer.md +2 -1
  101. package/commands/bootstrap.md +2 -2
  102. package/commands/close.md +3 -1
  103. package/commands/eli5.md +33 -0
  104. package/commands/go.md +1 -1
  105. package/commands/journey-audit.md +43 -0
  106. package/commands/release.md +5 -3
  107. package/commands/test.md +2 -2
  108. package/docs/USER-GUIDE.md +2 -2
  109. package/docs/ci-setup.md +14 -0
  110. package/docs/codex-setup.md +64 -0
  111. package/docs/components.md +7 -6
  112. package/docs/cursor-setup.md +26 -47
  113. package/docs/events-schema.md +76 -4
  114. package/docs/github-mirror-protection.md +197 -0
  115. package/docs/pi-setup.md +2 -0
  116. package/docs/rule-authoring.md +3 -1
  117. package/docs/scope-collision-guard.md +52 -5
  118. package/docs/session-config-reference.md +57 -12
  119. package/docs/session-config-template.md +4 -3
  120. package/docs/telemetry.md +22 -0
  121. package/hooks/_lib/lock-bootstrap.mjs +26 -16
  122. package/hooks/_lib/vcs-create-matcher.mjs +397 -38
  123. package/hooks/enforce-scope.mjs +64 -0
  124. package/hooks/hooks-codex.json +1 -1
  125. package/hooks/hooks-cursor.json +201 -20
  126. package/hooks/hooks-pi.json +1 -1
  127. package/hooks/hooks.json +12 -2
  128. package/hooks/on-session-end.mjs +237 -104
  129. package/hooks/on-session-start.mjs +404 -110
  130. package/hooks/on-stop.mjs +48 -9
  131. package/hooks/post-subagent-discovery-validator.mjs +34 -3
  132. package/hooks/post-tool-batch-wave-signal.mjs +11 -2
  133. package/hooks/pre-auq-clarity.mjs +787 -0
  134. package/hooks/pre-bash-issue-budget.mjs +133 -21
  135. package/hooks/pre-bash-sessions-ledger-guard.mjs +159 -0
  136. package/hooks/pre-bash-staging-fence.mjs +4 -0
  137. package/hooks/pre-task-scope-disjoint.mjs +368 -35
  138. package/hooks/skill-invocation-telemetry.mjs +21 -10
  139. package/monitors/monitors.json +6 -0
  140. package/package.json +3 -1
  141. package/pi/prompts/eli5.md +12 -0
  142. package/pi/prompts/journey-audit.md +12 -0
  143. package/rules/_index.md +9 -1
  144. package/rules/always-on/ask-via-tool.md +62 -0
  145. package/rules/always-on/bash-harness-pitfalls.md +168 -0
  146. package/rules/always-on/build-value.md +47 -0
  147. package/rules/always-on/cross-session-messaging.md +59 -0
  148. package/rules/always-on/loop-and-monitor.md +221 -0
  149. package/rules/always-on/parallel-sessions.md +142 -12
  150. package/rules/always-on/receiving-review.md +108 -0
  151. package/rules/always-on/test-value.md +40 -0
  152. package/rules/always-on/verification-before-completion.md +77 -0
  153. package/scripts/archive-closed-prds.mjs +258 -18
  154. package/scripts/auq-audit.mjs +825 -0
  155. package/scripts/autopilot.mjs +12 -8
  156. package/scripts/backfill-evidence-digest.mjs +376 -0
  157. package/scripts/cursor-install.mjs +89 -48
  158. package/scripts/export-hw-learnings.mjs +143 -2
  159. package/scripts/express-path.mjs +299 -0
  160. package/scripts/generate-cursor-adapter.mjs +253 -0
  161. package/scripts/github-protection-audit.mjs +358 -0
  162. package/scripts/lib/auq/clarity.mjs +1314 -0
  163. package/scripts/lib/auq/parse.mjs +1006 -0
  164. package/scripts/lib/auq/schema.mjs +1457 -0
  165. package/scripts/lib/autopilot/worktree-pipeline.mjs +240 -16
  166. package/scripts/lib/build-live-signals.mjs +24 -5
  167. package/scripts/lib/ci-status-banner.mjs +221 -68
  168. package/scripts/lib/command-blocker.mjs +70 -0
  169. package/scripts/lib/config/dispatcher-autonomy-capture.mjs +32 -9
  170. package/scripts/lib/config/reconcile.mjs +79 -4
  171. package/scripts/lib/config/section-extractor.mjs +235 -36
  172. package/scripts/lib/config/vault-integration.mjs +12 -1
  173. package/scripts/lib/config-schema.mjs +9 -1
  174. package/scripts/lib/config.mjs +57 -6
  175. package/scripts/lib/convergence-monitor.mjs +13 -2
  176. package/scripts/lib/cursor-hook-bridge.mjs +443 -0
  177. package/scripts/lib/dispatcher/cli.mjs +2 -2
  178. package/scripts/lib/dispatcher/rank.mjs +4 -7
  179. package/scripts/lib/express-path.mjs +327 -0
  180. package/scripts/lib/file-lock.mjs +22 -4
  181. package/scripts/lib/gates/gate-full.mjs +84 -11
  182. package/scripts/lib/gates/gate-helpers.mjs +93 -21
  183. package/scripts/lib/git-config-drift.mjs +134 -5
  184. package/scripts/lib/host-identity.mjs +247 -2
  185. package/scripts/lib/instruction-budget-guard.mjs +31 -1
  186. package/scripts/lib/io.mjs +239 -0
  187. package/scripts/lib/issue-budget.mjs +284 -31
  188. package/scripts/lib/learnings/io.mjs +55 -10
  189. package/scripts/lib/learnings/schema.mjs +95 -28
  190. package/scripts/lib/lock-reaper.mjs +7 -1
  191. package/scripts/lib/locks/staging-fence-lock.mjs +5 -1
  192. package/scripts/lib/locks/state-md-lock.mjs +8 -1
  193. package/scripts/lib/memory-banner.mjs +5 -2
  194. package/scripts/lib/memory-paths.mjs +15 -6
  195. package/scripts/lib/mode-selector/scoring.mjs +53 -6
  196. package/scripts/lib/owner-interview.mjs +78 -32
  197. package/scripts/lib/peer-discovery.mjs +73 -22
  198. package/scripts/lib/platform.mjs +72 -9
  199. package/scripts/lib/plugin-root.mjs +143 -19
  200. package/scripts/lib/project-hygiene.mjs +104 -4
  201. package/scripts/lib/quality-gate.mjs +271 -13
  202. package/scripts/lib/reconcile/emitter.mjs +87 -19
  203. package/scripts/lib/reconcile/engine.mjs +281 -13
  204. package/scripts/lib/reconcile/idempotency.mjs +102 -1
  205. package/scripts/lib/reconcile/renderer.mjs +165 -7
  206. package/scripts/lib/reconcile/sanitize.mjs +40 -17
  207. package/scripts/lib/reconcile/writer.mjs +415 -84
  208. package/scripts/lib/resource-probe/evaluate.mjs +330 -149
  209. package/scripts/lib/resource-probe/probe-platform.mjs +35 -0
  210. package/scripts/lib/resource-probe.mjs +18 -2
  211. package/scripts/lib/rule-loader.mjs +37 -2
  212. package/scripts/lib/rules-sync.mjs +51 -8
  213. package/scripts/lib/scope-gate.mjs +90 -0
  214. package/scripts/lib/session-close-backfill.mjs +369 -28
  215. package/scripts/lib/session-discovery.mjs +13 -3
  216. package/scripts/lib/session-end/phase-skip.mjs +37 -4
  217. package/scripts/lib/session-end/worktree-cleanup.mjs +154 -7
  218. package/scripts/lib/session-id.mjs +30 -14
  219. package/scripts/lib/session-identity/own-session.mjs +159 -0
  220. package/scripts/lib/session-lock.mjs +85 -30
  221. package/scripts/lib/session-schema/normalizer.mjs +70 -3
  222. package/scripts/lib/session-schema/validator.mjs +40 -0
  223. package/scripts/lib/session-start-probes.mjs +608 -0
  224. package/scripts/lib/session-transition.mjs +277 -0
  225. package/scripts/lib/sessions-staleness-banner.mjs +124 -57
  226. package/scripts/lib/spiral-carryover.mjs +111 -9
  227. package/scripts/lib/state-md/frontmatter-mutators.mjs +41 -8
  228. package/scripts/lib/state-md/mission-status.mjs +467 -72
  229. package/scripts/lib/state-md/yaml-parser.mjs +145 -16
  230. package/scripts/lib/state-md.mjs +12 -2
  231. package/scripts/lib/telemetry/sync.mjs +46 -8
  232. package/scripts/lib/validate/check-agents.mjs +66 -0
  233. package/scripts/lib/validate/check-auq-clarity.mjs +274 -0
  234. package/scripts/lib/validate/check-cursor-adapter.mjs +102 -0
  235. package/scripts/lib/validate/check-dead-bridge.mjs +24 -2
  236. package/scripts/lib/validate/check-doc-cli-commands.mjs +16 -32
  237. package/scripts/lib/validate/check-hooks-symmetry.mjs +59 -63
  238. package/scripts/lib/validate/check-playwright-mcp-canary.mjs +13 -22
  239. package/scripts/lib/validate/check-plugin-monitors.mjs +10 -4
  240. package/scripts/lib/validate/check-rules.mjs +153 -9
  241. package/scripts/lib/validate/check-test-value-bans.mjs +165 -17
  242. package/scripts/lib/validate/check-unwired-features.mjs +340 -32
  243. package/scripts/lib/validate/repo-files.mjs +275 -0
  244. package/scripts/lib/validate-vendored-rules.mjs +229 -7
  245. package/scripts/lib/vault-backfill/glab.mjs +91 -58
  246. package/scripts/lib/vault-backfill/manifest.mjs +28 -8
  247. package/scripts/lib/vault-mirror/process.mjs +99 -43
  248. package/scripts/lib/vault-mirror/telemetry.mjs +210 -0
  249. package/scripts/lib/vault-staleness-banner.mjs +76 -6
  250. package/scripts/lib/vault-status/board-writer.mjs +211 -10
  251. package/scripts/lib/vault-status/narrative-mirror.mjs +188 -8
  252. package/scripts/lib/vcs-repo-spec.mjs +182 -13
  253. package/scripts/lib/wave-executor/foreign-dispatch.mjs +832 -0
  254. package/scripts/lib/wave-resource-gate.mjs +67 -73
  255. package/scripts/lib/wave-transcript-tail.mjs +869 -0
  256. package/scripts/materialize-wave-scope.mjs +478 -0
  257. package/scripts/mcp-server.sh +11 -2
  258. package/scripts/parse-config.mjs +65 -0
  259. package/scripts/release.mjs +443 -122
  260. package/scripts/run-quality-gate.mjs +14 -0
  261. package/scripts/token-audit.sh +9 -2
  262. package/scripts/validate-plugin.mjs +6 -0
  263. package/scripts/validate-wave-scope.mjs +73 -1
  264. package/scripts/vault-backfill.mjs +32 -5
  265. package/scripts/vault-mirror.mjs +203 -34
  266. package/skills/_shared/monitor-patterns.md +31 -5
  267. package/skills/_shared/parallel-aware-auq.md +31 -25
  268. package/skills/_shared/parallel-aware-preamble.md +35 -4
  269. package/skills/_shared/platform-tools.md +11 -5
  270. package/skills/_shared/state-ownership.md +61 -8
  271. package/skills/autopilot/SKILL.md +5 -1
  272. package/skills/bootstrap/SKILL.md +5 -4
  273. package/skills/bootstrap/_shared-template.md +18 -10
  274. package/skills/bootstrap/deep-template.md +10 -6
  275. package/skills/bootstrap/fast-template.md +15 -8
  276. package/skills/bootstrap/standard-template.md +10 -6
  277. package/skills/brainstorm/SKILL.md +18 -18
  278. package/skills/brainstorm/soul.md +12 -0
  279. package/skills/claude-md-drift-check/checker.mjs +39 -11
  280. package/skills/discovery/SKILL.md +28 -24
  281. package/skills/dispatcher/SKILL.md +1 -1
  282. package/skills/eli5/SKILL.md +43 -0
  283. package/skills/evolve/SKILL.md +8 -9
  284. package/skills/gitlab-ops/SKILL.md +30 -26
  285. package/skills/grill/SKILL.md +6 -6
  286. package/skills/grill/soul.md +16 -0
  287. package/skills/journey-audit/SKILL.md +269 -0
  288. package/skills/memory-cleanup/SKILL.md +2 -2
  289. package/skills/npm-publish/SKILL.md +4 -4
  290. package/skills/peekaboo-driver/SKILL.md +18 -6
  291. package/skills/persona-panel/SKILL.md +1 -1
  292. package/skills/plan/SKILL.md +18 -16
  293. package/skills/plan/mode-feature.md +1 -1
  294. package/skills/plan/mode-new.md +35 -23
  295. package/skills/plan/soul.md +12 -0
  296. package/skills/reconcile/SKILL.md +44 -4
  297. package/skills/session-end/SKILL.md +70 -24
  298. package/skills/session-end/metrics-collection.md +7 -4
  299. package/skills/session-end/phase-3-6-tail.md +48 -5
  300. package/skills/session-end/phase-3-7a-recommendations.md +16 -2
  301. package/skills/session-plan/SKILL.md +6 -1
  302. package/skills/session-plan/wave-template.md +1 -0
  303. package/skills/session-start/SKILL.md +96 -48
  304. package/skills/session-start/phase-2-5-docs-planning.md +8 -8
  305. package/skills/session-start/phase-4-5-resource-health.md +82 -19
  306. package/skills/session-start/phase-7-5-mode-selector.md +15 -3
  307. package/skills/session-start/phase-8-5-express-path.md +77 -12
  308. package/skills/session-start/soul.md +110 -0
  309. package/skills/test-runner/SKILL.md +2 -2
  310. package/skills/using-orchestrator/SKILL.md +1 -1
  311. package/skills/vault-sync/validator.mjs +31 -0
  312. package/skills/wave-executor/SKILL.md +4 -2
  313. package/skills/wave-executor/circuit-breaker.md +34 -9
  314. package/skills/wave-executor/wave-loop.md +129 -24
  315. package/skills/write-executable-plan/SKILL.md +6 -6
  316. package/templates/_shared/journey-manifest.md +110 -0
  317. package/scripts/tests/fixtures/fetch-baseline/sample-rule.md +0 -8
  318. package/skills/vault-sync/tests/fixtures/archive-test-vault/90-archive/bad-archived.md +0 -8
  319. package/skills/vault-sync/tests/fixtures/archive-test-vault/_meta/.gitkeep +0 -0
  320. package/skills/vault-sync/tests/fixtures/archive-test-vault/live-note.md +0 -8
  321. package/skills/vault-sync/tests/fixtures/broken-frontmatter-vault/_meta/.gitkeep +0 -0
  322. package/skills/vault-sync/tests/fixtures/broken-frontmatter-vault/bad-type.md +0 -8
  323. package/skills/vault-sync/tests/fixtures/broken-frontmatter-vault/good-note.md +0 -8
  324. package/skills/vault-sync/tests/fixtures/clean-vault/.obsidian/config.md +0 -8
  325. package/skills/vault-sync/tests/fixtures/clean-vault/01-projects/foo/projects-baseline.md +0 -10
  326. package/skills/vault-sync/tests/fixtures/clean-vault/03-daily/daily-2026-04-13.md +0 -8
  327. package/skills/vault-sync/tests/fixtures/clean-vault/README.md +0 -3
  328. package/skills/vault-sync/tests/fixtures/clean-vault/hello-world.md +0 -11
  329. package/skills/vault-sync/tests/fixtures/dangling-link-vault/_meta/.gitkeep +0 -0
  330. package/skills/vault-sync/tests/fixtures/dangling-link-vault/has-dangling.md +0 -9
  331. package/skills/vault-sync/tests/fixtures/dangling-link-vault/real-target.md +0 -8
  332. package/skills/vault-sync/tests/fixtures/empty-vault/_meta/.gitkeep +0 -0
  333. package/skills/vault-sync/tests/fixtures/missing-field-vault/_meta/.gitkeep +0 -0
  334. package/skills/vault-sync/tests/fixtures/missing-field-vault/missing-id.md +0 -7
  335. package/skills/vault-sync/tests/fixtures/nested-tag-vault/03-daily/daily-2026-04-13.md +0 -9
  336. package/skills/vault-sync/tests/fixtures/nested-tag-vault/_meta/.gitkeep +0 -0
  337. package/skills/vault-sync/tests/fixtures/nested-tag-vault/nested-tags-note.md +0 -11
  338. package/skills/vault-sync/tests/fixtures/no-frontmatter-vault/README.md +0 -3
  339. package/skills/vault-sync/tests/fixtures/no-frontmatter-vault/_MOC.md +0 -3
  340. package/skills/vault-sync/tests/fixtures/no-frontmatter-vault/_meta/.gitkeep +0 -0
  341. package/skills/vault-sync/tests/fixtures/with-moc-vault/_MOC.md +0 -11
  342. package/skills/vault-sync/tests/fixtures/with-moc-vault/_meta/.gitkeep +0 -0
  343. package/skills/vault-sync/tests/fixtures/with-moc-vault/hello-world.md +0 -11
  344. package/skills/vault-sync/tests/schema-drift.test.mjs +0 -133
  345. package/templates/_shared/rules/parallel-sessions.md +0 -77
@@ -0,0 +1,269 @@
1
+ ---
2
+ name: journey-audit
3
+ description: >
4
+ Use this skill when the user wants the PRODUCT audited from the outside in — what the website
5
+ promises vs what the code does vs what a real user experiences vs what actually arrives by mail
6
+ vs what the data says is used. Runs a 7-role read-only wave (R5 writes only under an explicit
7
+ SAFETY block) against a per-repo `.orchestrator/journey-manifest.md` and writes a dossier to
8
+ docs/audits/. Distinct from /discovery, which checks code quality inside-out — this checks
9
+ product truth outside-in; they complement, neither replaces the other. Triggers "journey audit",
10
+ "Nutzersicht-Audit", "audit the product from the user's side", "/journey-audit".
11
+ model: inherit
12
+ color: purple
13
+ tools: Read, Grep, Glob, Bash, Write, Task
14
+ ---
15
+
16
+ # Journey Audit
17
+
18
+ > Outside-in product audit as a repeatable deep session. Code review checks code against code;
19
+ > this checks the product against the user's experience. Quarterly, never a CI component.
20
+
21
+ ## Purpose
22
+
23
+ The most expensive defects of the first run (EventDrop `main-2026-08-28-a6`: a core feature with no
24
+ entry point anywhere in the UI, burned free quota, a plan gate that could be bypassed, a
25
+ claim-vs-code contradiction, EUR copy in a USD context) are **invisible to every code-centric
26
+ check**. They are not bugs in a function; they are gaps between five surfaces — marketing copy,
27
+ code constants, live UI, outbound mail, real usage data — that no single surface can reveal.
28
+
29
+ This skill dispatches seven roles that each own one surface, then makes the coordinator personally
30
+ re-verify every P0 before it is written down. The re-verification is the value, not the fan-out:
31
+ the first run caught 2 agent errors that way and confirmed 3 real P0s.
32
+
33
+ ## Phase 0: Gates
34
+
35
+ ### 0.1 Bootstrap Gate
36
+
37
+ Read `skills/_shared/bootstrap-gate.md` and execute the gate check. GATE_CLOSED → invoke
38
+ `skills/bootstrap/SKILL.md` first. GATE_OPEN → continue.
39
+
40
+ ### 0.2 Manifest HARD-GATE
41
+
42
+ <HARD-GATE>
43
+ Read `.orchestrator/journey-manifest.md` in the target repo (or the path passed as `$ARGUMENTS`).
44
+
45
+ **A — File missing or empty → REFUSE the whole run.** Say exactly this, then stop:
46
+
47
+ > `/journey-audit` needs `.orchestrator/journey-manifest.md` in this repo and it is not there.
48
+ > The audit is repo-specific: without personas, entry points, truth-SSOTs, the chat-interview key
49
+ > and the SAFETY block, seven agents would invent their own definition of "correct" and every
50
+ > finding would be unfalsifiable.
51
+ > Copy the template — `templates/_shared/journey-manifest.md` in the session-orchestrator plugin —
52
+ > to `.orchestrator/journey-manifest.md`, fill it in, then re-run `/journey-audit`.
53
+
54
+ **B — Manifest present, `## SAFETY` heading absent or its body empty → REFUSE R5 ONLY.** R5 is the
55
+ only role that touches production with a real account. Say:
56
+
57
+ > The manifest has no filled `## SAFETY` block, so R5 (real end-to-end run against production) is
58
+ > NOT dispatched. Running as dry-run: R1–R4 + R7 (R6 additionally needs the read-only DB
59
+ > credentials named in the manifest). Fill in allowed accounts/events, no-go actions, the checkout
60
+ > limit and the cleanup rule to enable R5.
61
+
62
+ Do NOT infer a SAFETY block from other sections, do NOT ask the operator to dictate one into chat,
63
+ do NOT dispatch R5 "read-only, just this once". A production write without a written, committed
64
+ safety envelope is the one thing this skill never does.
65
+ </HARD-GATE>
66
+
67
+ Both gates are cheap and mechanical:
68
+
69
+ ```bash
70
+ MANIFEST="${1:-.orchestrator/journey-manifest.md}"
71
+ [ -s "$MANIFEST" ] || { echo "GATE-A: no manifest"; exit 1; }
72
+ awk '/^## SAFETY/{f=1;next} /^## /{f=0} f&&NF{c++} END{exit c>0?0:1}' "$MANIFEST" \
73
+ || echo "GATE-B: SAFETY block absent or empty → R5 disabled"
74
+ ```
75
+
76
+ ### 0.3 Peer-session check (before dispatch, not after)
77
+
78
+ Run `ListAgents` / read `.orchestrator/` session locks and check for peer sessions in this working
79
+ copy per `.claude/rules/parallel-sessions.md`. A journey audit reads wide and R5 writes to
80
+ production — a peer holding the same files must know before the wave starts, not from the diff.
81
+ Announce the audit and the file scope you will touch; the audit itself claims almost no write
82
+ scope, which is exactly why it is easy to forget.
83
+
84
+ ## Phase 1: Read the manifest
85
+
86
+ Parse the manifest into `$MANIFEST` and derive per-role inputs. Every role prompt below is filled
87
+ from these fields — an empty field is reported to the operator, never guessed:
88
+
89
+ `personas` · `entry_points` · `truth_ssots` · `touchpoints` (template dir, send path, cron sources,
90
+ render idiom) · `chat_interview` (question → expected answer → SSOT) · `safety` · `credentials`
91
+ (env-var NAMES) · `realdata_queries` · `platform_expectation` · `known_exceptions`.
92
+
93
+ ## Phase 2: The wave — R1–R7
94
+
95
+ All roles are **read-only** except R5. All run in parallel in one wave; none depends on another's
96
+ output (the coordinator, not an agent, joins their findings).
97
+
98
+ | R | Rolle | Generisch | Aus dem Manifest |
99
+ |---|-------|-----------|------------------|
100
+ | R1 | Flow-Zensus | Trigger→Empfänger→Zeitpunkt→Dedupe map of every outbound touchpoint (mail/push/webhook) | Template dir, send path, cron sources |
101
+ | R2 | Artefakt-Rendering | Render templates to HTML, screenshots desktop/mobile/dark, consistency matrix | Render idiom, example props |
102
+ | R3 | Claim-vs-Code-Matrix | Every marketing/FAQ/chat claim against the SSOT constants; feature inventory × surfaces | SSOT files, i18n namespaces, chat fact source |
103
+ | R4 | Anonymer Live-Rundgang | agent-browser desktop+mobile, chat interview against the truth key, dead links, console | Route list, chat questions + expected answers |
104
+ | R5 | Echter E2E-Durchstich | Prod, real account, actually execute each core flow, DB counter-check, mail-log reconciliation | **SAFETY block (mandatory)** |
105
+ | R6 | Realdaten-Funnel | Usage funnel, never-fired flows, delivery defects, name what is not measurable | Read-only DB access, identity rules, mail-provider API |
106
+ | R7 | Plattform-Ausnutzung | Self-built vs platform matrix (hosting/DB/realtime/queues/CDN/WAF), limits at 10× | CLI logins, expected plan, open perf issues |
107
+
108
+ ### Shared prompt preamble (prepend to every role)
109
+
110
+ > You are role `<R#>` of a journey audit of `<repo>`. Manifest: `.orchestrator/journey-manifest.md`
111
+ > — read it first; it is your only definition of "correct". You are **read-only**: no `Edit`, no
112
+ > `Write` outside your own report, no git write operations (PSA-007), no production writes.
113
+ > Every distributional claim ("all N routes", "no template does X") carries the executed command
114
+ > and its output (PSA-006). A finding you cannot reproduce with a quoted command is a suspicion —
115
+ > label it as one. Findings listed under `Bekannte Ausnahmen` in the manifest are reported as
116
+ > `known-exception`, never as new. Severity: **P0** = money, data loss, or a core flow unreachable ·
117
+ > **P1** = a broken flow or a UX dead end · **P2** = content/platform. Return the FULL report as
118
+ > your last message.
119
+
120
+ ### Role prompt skeletons
121
+
122
+ Each is self-contained; fill the `<…>` from `$MANIFEST`.
123
+
124
+ **R1 — Flow-Zensus.** Inputs: template dir `<…>`, send path `<…>`, cron sources `<…>`.
125
+ Task: enumerate every outbound touchpoint and produce one row per flow: trigger (code location) →
126
+ recipient (which persona) → timing → dedupe/idempotency → is it reachable at all. Grep the send
127
+ path for callers; a template with zero callers is a P1 finding, a caller with no dedupe on a
128
+ money-relevant flow is P0. Output: Markdown table + a list of `never-fired` candidates with the
129
+ grep that proves zero callers.
130
+
131
+ **R2 — Artefakt-Rendering.** Inputs: render idiom `<…>`, example props `<…>`.
132
+ Task: render every template found by R1's directory to HTML, screenshot desktop + mobile + dark,
133
+ and build a consistency matrix (logo, sender, footer, legal block, CTA, language, currency).
134
+ Output: matrix table + the artifact paths under `.orchestrator/journey-audit/<date>/`, plus every
135
+ divergence as a finding. Do not fix a template; report it.
136
+
137
+ **R3 — Claim-vs-Code-Matrix.** Inputs: SSOT files `<…>`, i18n namespaces `<…>`, chat fact source `<…>`.
138
+ Task: extract every quantitative or capability claim from marketing pages, FAQ, pricing, chat facts
139
+ and mail copy; compare each against the SSOT constant. One row: claim · where it is said · SSOT
140
+ value · verdict (`match` / `drift` / `unbacked`). Then a feature inventory × surfaces grid: a
141
+ feature that exists in code but appears on no surface is a P0 candidate ("no entry point").
142
+ **i18n files are owned by R3 alone** — no other role opens them.
143
+ Output: two tables + findings.
144
+
145
+ **R4 — Anonymer Live-Rundgang.** Inputs: route list `<…>`, chat questions + expected answers `<…>`.
146
+ Task: `agent-browser`, logged OUT, desktop and mobile viewport. Walk every route: dead links,
147
+ console errors, layout breaks, CTA that goes nowhere. Then run the chat interview verbatim and
148
+ score each answer against the expected answer from the manifest (`match` / `drift` / `refused` /
149
+ `hallucinated`). Output: route table (status, console, findings), interview table, screenshots.
150
+ Read-only: never submit a form that creates data, never sign up.
151
+
152
+ **R5 — Echter E2E-Durchstich.** Inputs: SAFETY block `<…>`, credentials by env-var NAME `<…>`.
153
+ Task: with the allowed account only, actually execute each core flow end to end in production;
154
+ counter-check in the DB read-only that the expected records exist; reconcile against the mail log.
155
+ **Before every step, re-read the SAFETY block and state which rule permits this step.** Stop at the
156
+ first no-go, do not improvise around a block, honour the checkout limit exactly, and run the
157
+ cleanup rule at the end and prove it ran. Output: per-flow trace (step → observed → expected →
158
+ verdict), the DB counter-check output, the cleanup proof.
159
+
160
+ **R6 — Realdaten-Funnel.** Inputs: read-only queries `<…>`, identity rules `<…>`, mail-provider API `<…>`.
161
+ Task: run the manifest's `SELECT`s only. Build the funnel per persona, list flows that never fired
162
+ in production, and pull delivery defects from the mail provider (bounces, suppressions, a
163
+ permanently silenced owner address). Then name explicitly what the data CANNOT answer — an unnamed
164
+ blind spot reads as a zero. Output: funnel table, never-fired list, delivery-defect list,
165
+ `not-measurable` list. No writes, no schema changes, no query outside the manifest.
166
+
167
+ **R7 — Plattform-Ausnutzung.** Inputs: CLI logins `<…>`, expected plan/tier `<…>`, open perf issues `<…>`.
168
+ Task: self-built vs platform matrix across hosting, DB, realtime, queues, CDN, WAF, cron, mail:
169
+ what does the repo hand-roll that the paid platform already provides, and what breaks at 10× today's
170
+ load (quote the actual limit from the provider CLI/API, not from memory). Output: matrix
171
+ (capability · self-built? · platform feature · effort to switch · limit at 10×) + findings.
172
+
173
+ ## Phase 3: Koordinator-Disziplin
174
+
175
+ Numbered MUSTs. This phase is the skill; the wave is only its input.
176
+
177
+ 1. **Every P0 claim is re-verified by the coordinator, individually, with its OWN grep/curl/DB read,
178
+ before it enters the dossier.** Not "the agent quoted a command" — you run one yourself, and the
179
+ dossier carries YOUR command and output. An unreproduced P0 is downgraded to P1 with the note
180
+ `agent claim, not reproduced`, or dropped. First run: 2 of 5 P0 claims were agent errors
181
+ ("instantly unreachable" — it was selectable in the UI; "USD on prod" — a session artifact).
182
+ 2. **A finding is attributed.** Every dossier row names the role that found it and the command that
183
+ proves it — the reader must be able to re-run it without asking anyone.
184
+ 3. **i18n files are owned by exactly ONE agent (R3).** They were the known contention point in the
185
+ first run: many roles want to quote them, and a second reader turns into a second writer the
186
+ moment a fix is suggested. Same rule for any other file two roles both want.
187
+ 4. **Peer-session check before the wave starts** (Phase 0.3), not after the diff.
188
+ 5. **The coordinator never lets an agent write the dossier.** Agents return reports; the joining,
189
+ de-duplication and severity decision are the coordinator's, because contradictions between two
190
+ agents are only visible in one place.
191
+ 6. **Contradictions are reported as contradictions.** Two roles disagreeing is a finding about the
192
+ product, not a merge conflict to smooth over.
193
+ 7. **No fixes during the audit.** Findings only. The fix wave is Phase 5 and is a separate decision.
194
+
195
+ ## Phase 4: Dossier
196
+
197
+ Write `docs/audits/YYYY-MM-DD-user-journey-audit.md` with this fixed section order:
198
+
199
+ 1. `## P0 — Geld & Kern-Flows` (each: symptom · evidence (coordinator's own command + output) ·
200
+ impact · suggested fix · role)
201
+ 2. `## P1 — Flows`
202
+ 3. `## P1 — UX`
203
+ 4. `## P2 — Inhalt`
204
+ 5. `## P2 — Plattform`
205
+ 6. `## Realdaten` (funnel, never-fired flows, delivery defects, explicitly not-measurable)
206
+ 7. `## Marketing-Hebel` (what the product does well and says nowhere)
207
+
208
+ Header carries: date, repo, HEAD SHA, roles dispatched (and which were skipped, with the reason —
209
+ "R5 skipped: no SAFETY block" is a result, not a gap), manifest path, artifact directory.
210
+
211
+ ## Phase 5: Closing AskUserQuestion
212
+
213
+ One `AskUserQuestion` call, per `.claude/rules/ask-via-tool.md` (option 1 `(Recommended)`, every
214
+ description carries reason + cost + consequence, `header` ≤ 12 codepoints):
215
+
216
+ ```
217
+ AskUserQuestion({ questions: [
218
+ { question: "Which fix packages should the follow-up wave carry?",
219
+ header: "Fix-Wellen", multiSelect: true,
220
+ options: [
221
+ { label: "P0 money+core (Recommended)", description: "The <N> P0s I re-verified myself. Blocks revenue/core flow today; ~<X>h; freezes nothing else." },
222
+ { label: "P1 flows", description: "<N> broken/undedupliced flows. ~<X>h; needs the R1 map as input." },
223
+ { label: "P1 UX", description: "<N> dead ends. Cheap individually, touches i18n — one owner." },
224
+ { label: "P2 content+platform", description: "<N> items. No user impact today; do in cooldown." } ] },
225
+ { question: "Create issues for the selected packages?",
226
+ header: "Issues", multiSelect: false,
227
+ options: [
228
+ { label: "Yes, batch now (Recommended)", description: "One issue per finding via gitlab-ops; labels priority::critical|high|medium + area:* + type:bug/feature. ~<N> issues; respects issue-budget." },
229
+ { label: "Dossier only", description: "No issues; the dossier stays the record. Choose when the backlog is already over budget." } ] } ] })
230
+ ```
231
+
232
+ Issue creation follows `skills/gitlab-ops/SKILL.md` § Label Taxonomy: `priority::critical` for P0,
233
+ `priority::high` for P1, `priority::medium` for P2, plus the repo's `area:` and `type:` axes. Each
234
+ issue links back to the dossier section that produced it.
235
+
236
+ ## Offload note (R6/R7)
237
+
238
+ R6 and R7 are pure CLI/API roles — no browser, no repo writes — so they can run headless on a
239
+ second machine (`claude -p "<prompt>"`, see the `m5-offload` skill). Two rules from the first run,
240
+ both learned the hard way:
241
+
242
+ - **`claude -p` prints only the LAST message.** The prompt MUST end with: *"Return the complete
243
+ report in your last message — not a summary, not a pointer to a file. Nothing you say before the
244
+ last message will be read."*
245
+ - **No background processes.** The prompt MUST forbid `&`, `run_in_background`, and any "I'll keep
246
+ it running" pattern: the process is killed when `-p` returns, and a half-finished role looks
247
+ identical to a clean one.
248
+
249
+ ## Cadence & Abgrenzung
250
+
251
+ - **Quarterly, or after a large feature drop.** Deliberately **not a CI component** — it is
252
+ expensive and judgment-heavy, and a judgment-heavy gate that runs on every pipeline becomes a
253
+ rubber stamp.
254
+ - **Optional monthly light variant:** R3 + R4 only, as a scheduled cloud session.
255
+ - **vs `/discovery`:** discovery checks code quality inside-out (probes over the tree);
256
+ journey-audit checks product truth outside-in (five user-facing surfaces against each other).
257
+ Neither replaces the other; a repo needs both.
258
+ - **Follow-through:** after each run, freeze the mechanizable parts per repo — a `report:*` script,
259
+ a claim-drift test pinned to the SSOT constant — so the next run is cheaper. The audit's job is
260
+ to find what no test knows how to look for yet.
261
+
262
+ ## Anti-Patterns
263
+
264
+ - Dispatching R5 without a SAFETY block "because the operator said it's fine in chat" — the block
265
+ is a committed artifact for a reason.
266
+ - Copying an agent's P0 into the dossier because its command looked convincing (Phase 3.1).
267
+ - Two roles both editing/owning the i18n files (Phase 3.3).
268
+ - Running the audit as a CI job to "keep it honest" — it turns into a stamp nobody reads.
269
+ - Fixing findings mid-audit, so the later roles measure a moving product.
@@ -246,8 +246,8 @@ const peerWarning = wt.activePeer
246
246
 
247
247
  AskUserQuestion({
248
248
  questions: [{
249
- question: `Stale auto-promoted worktree found: ${path.basename(wt.wtPath)} (age ${ageDays}d, branch=${wt.branch}).${peerWarning} Remove?`,
250
- header: "Stale-Worktree",
249
+ question: `Auto-promoted worktree ${path.basename(wt.wtPath)} is ${ageDays}d old (branch ${wt.branch}).${peerWarning} Remove?`,
250
+ header: "Worktree",
251
251
  multiSelect: false,
252
252
  options: [
253
253
  {
@@ -7,7 +7,7 @@ description: Use when publishing this package to npm — a version release (npm
7
7
 
8
8
  # npm-publish — token auth, and the calls the script cannot make
9
9
 
10
- > **The release itself is `/release` → `scripts/release.mjs`.** That script mechanizes the whole sequence: version surfaces, CHANGELOG gate, drift sweep, tag/registry collision, CI, leakage gate, publish, tag-after-publish, push to both remotes, live-site poll. This skill does not restate it.
10
+ > **The release itself is `/release` → `scripts/release.mjs`.** That script mechanizes the whole sequence: version surfaces, CHANGELOG gate, drift sweep, tag/registry collision, CI, leakage gate, publish, the target-confirmed npm receipt boundary, tag-after-receipt, push to both remotes, GitHub-release handling, and live-site poll. This skill does not restate it.
11
11
  >
12
12
  > What lives here is the half a script cannot own: the **token setup**, the **auth failure diagnosis**, and the **judgement calls** — which version, what a leak means, when to abort rather than repair.
13
13
 
@@ -39,7 +39,7 @@ The script gates mechanics. These three are yours, and it will not make them for
39
39
 
40
40
  **2. What a leak means when one is found.** A hit from the leakage gate is not a pattern to silence. Decide which of two it is: a real leak (fix `package.json` `files`, re-pack, re-check) or genuine over-matching (fix `LEAKAGE_PATTERNS` in `scripts/release.mjs` **with a test**). There is no third option, and neither is "publish anyway and clean it up in the next version" — an npm publish is not revocable, and unpublishing burns the version number permanently. Operator handling detail: `docs/distribution/npm-publish-checklist.md` § 3.
41
41
 
42
- **3. When to abort instead of repair.** Abort — do not patch forward — when the failure is upstream of the publish: a red preflight row, a lagging `github` mirror, CI not green on the exact commit, a dead token. These are cheap to fix and re-run from the top. Repair-in-place is only ever appropriate *after* a verified publish, where the version is already immutable: a missing GitHub release or a lagging site deploy can be reconciled, because npm already has the correct artifact. The dividing line is whether the registry has accepted the tarball before that point, restart; after it, reconcile. `commands/release.md` § Abort criteria is the operative list.
42
+ **3. When to abort instead of repair.** Abort — do not patch forward — when the failure is upstream of the target-confirmed npm receipt: a red preflight row, a lagging `github` mirror, CI not green on the exact commit, a dead token, or a publish that did not issue the target receipt. These are cheap to fix and re-run from the top. Repair-in-place is only appropriate *after* that receipt, where the version is already immutable: registry propagation, a missing GitHub release, or a lagging site deploy can be reconciled because npm already has the correct artifact. When `--publish` reports **Post-publish reconciliation required**, **do not rerun `--publish`**; repair the listed state directly. `commands/release.md` § Abort criteria is the operative list.
43
43
 
44
44
  ## Failure-mode table
45
45
 
@@ -48,13 +48,13 @@ The script gates mechanics. These three are yours, and it will not make them for
48
48
  | `E403 ... Two-factor authentication or granular access token with bypass 2fa enabled is required` — no OTP prompt | Account has no 2FA enrolled AND token (if any) lacks Bypass-2FA | Create granular token with all four requirements above, or enroll 2FA |
49
49
  | Same E403 despite a fresh token | Token created without the Bypass-2FA checkbox, or Read-only, or package-scoped on a first publish | Re-create: RW + All packages + Bypass-2FA |
50
50
  | `npm whoami` silent or non-zero | Token expired, or `.env.local` missing | Re-create the token; do not proceed — the preflight fails this row on purpose |
51
- | `E404` on `npm view` after publish | Registry propagation (rare, seconds) or publish actually failed | Re-check the publish output for `+ <name>@<version>` |
51
+ | `E404` on `npm view` after a target-confirmed publish receipt | Registry propagation (rare, seconds) | Let the script finish its tag/push/GitHub/site tail, then reconcile the registry result; do **not** rerun `--publish` |
52
52
  | `ENEEDAUTH` | No login/token at all | Token flow above, or `npm login` |
53
53
  | OTP prompt appears but flow is non-interactive (`!`-prefix, script) | No TTY for the prompt | Use the token flow, or a real terminal |
54
54
 
55
55
  ## Post-publish — the human half
56
56
 
57
- `--publish` verifies the registry and polls the live site itself, and prints the rest. What still needs a person:
57
+ `--publish` attempts registry verification and polls the live site itself. A target-confirmed receipt plus a delayed registry result is a reconciliation outcome, not a failed publish or a retry instruction. What still needs a person:
58
58
 
59
59
  1. **Rotate/delete the token** at https://www.npmjs.com/settings/<user>/tokens. A token that ever transited a conversation, a screenshot, or any log is burned — rotate immediately.
60
60
  2. **pi.dev gallery**: indexing is asynchronous — check https://pi.dev/packages later; do not block on it.
@@ -96,10 +96,10 @@ For each `${PERM_NAME}` in `$MISSING`:
96
96
  ```
97
97
  AskUserQuestion({
98
98
  questions: [{
99
- question: `${PERM_NAME} permission is required but not granted. Open System Settings > Privacy & Security > ${PERM_NAME}, enable the terminal entry, then confirm here.`,
100
- header: `Missing Permission: ${PERM_NAME}`,
99
+ question: `${PERM_NAME} is not granted. Enable the terminal entry under System Settings > Privacy & Security, then confirm.`,
100
+ header: "Zugriff",
101
101
  options: [
102
- { label: "Granted — continue (Recommended)", description: `I have enabled ${PERM_NAME} in System Settings.` },
102
+ { label: "Granted — continue (Recommended)", description: "I enabled the terminal entry in that pane — the driver then checks again and carries on if the grant took effect." },
103
103
  { label: "Skip this run", description: "Abort peekaboo-driver. Test-runner will record a framework-error finding." }
104
104
  ],
105
105
  multiSelect: false
@@ -156,11 +156,15 @@ For SwiftUI 26+ targets (projects with `Package.swift` declaring `.iOS("26")` or
156
156
  ```bash
157
157
  # Gate: glass-modifiers emit is opt-in per the active profile's rubric_features flag (v1 rubric does not consume).
158
158
  PROFILES_FILE=".orchestrator/policy/test-profiles.json"
159
- HAS_GLASS_V2="false"
159
+ HAS_GLASS_V2="false" # preconditions unmet (no PROFILE / no file / no jq) = feature not requested
160
160
  if [ -n "${PROFILE:-}" ] && [ -f "$PROFILES_FILE" ] && command -v jq >/dev/null 2>&1; then
161
- HAS_GLASS_V2=$(jq -r --arg p "$PROFILE" '(.[$p].rubric_features // []) | contains(["glass-v2"])' "$PROFILES_FILE" 2>/dev/null || echo false)
161
+ # Fallback is `unknown`, NOT `false`: false is jq's legitimate "feature off" answer,
162
+ # so a jq crash on a malformed profiles file would read as a deliberate opt-out.
163
+ HAS_GLASS_V2=$(jq -r --arg p "$PROFILE" '(.[$p].rubric_features // []) | contains(["glass-v2"])' "$PROFILES_FILE" 2>/dev/null || echo unknown)
162
164
  fi
163
- if [ "$HAS_GLASS_V2" = "true" ]; then
165
+ if [ "$HAS_GLASS_V2" = "unknown" ]; then
166
+ echo "WARN: glass-v2 probe failed (jq could not read $PROFILES_FILE) — no conformance artifact emitted" >&2
167
+ elif [ "$HAS_GLASS_V2" = "true" ]; then
164
168
  cat > "${RUN_DIR}/ax-snapshots/glass-modifiers-$(date +%s%3N).json" <<EOF
165
169
  {
166
170
  "schema_version": "v1",
@@ -175,6 +179,14 @@ EOF
175
179
  fi
176
180
  ```
177
181
 
182
+ `HAS_GLASS_V2` has **three** states, and the third is the reason the fallback is not `false`:
183
+
184
+ | Value | Meaning | Driver action |
185
+ |---|---|---|
186
+ | `true` | The active profile lists `glass-v2` in `rubric_features` | Emit the conformance artifact |
187
+ | `false` | The profile does not list it — a real answer from a readable file, or preconditions unmet (no `PROFILE`, no profiles file, no `jq`) | Skip the artifact silently |
188
+ | `unknown` | The probe itself failed — `jq` could not read/parse `$PROFILES_FILE` | WARN on stderr, skip the artifact. **Never** collapsed into `false`: a crashed probe is not an opt-out, and ux-evaluator Check 4 would otherwise report screenshot-only fallback as if the profile had chosen it |
189
+
178
190
  The ux-evaluator Check 4 reads this file. `glassEffect_frames` = compliant (uses `.glassEffect()`). `legacy_material_frames` = non-compliant (uses `.background(.thinMaterial)` etc.). `blur_modifier_frames` = non-compliant (uses `.blur(radius:)` as background). In v1 the arrays are always empty — the evaluator falls back to screenshot-only analysis. Do NOT emit a bare `{}` — use the full schema structure with empty arrays.
179
191
 
180
192
  ## Composability Contract
@@ -334,7 +334,7 @@ result. If `final_verdict == "warn"`: exit 0 with a warning line on stderr. If
334
334
  - **NEVER** dispatch more than 20 personas per panel (security M2 cap).
335
335
  - **NEVER** write a sidecar that fails schema validation — validate BEFORE write (security M3).
336
336
  - **NEVER** skip `validatePathInsideProject` for the target path OR the sidecar output path (H1).
337
- - **NEVER** use `run_in_background: true` for persona agents — lose coordination ability.
337
+ - **NEVER** use `run_in_background: true` for persona agents — the panel synthesis needs every reviewer's findings before Phase 4; background dispatch would add turn-juggling with no consumer for early results.
338
338
  - **ALWAYS** validate `model:` fields from the catalog against `MODEL_ID_RE` + aliases (H2).
339
339
  - **ALWAYS** run `output_contract` structural pre-check before `ajv.compile()` (H3).
340
340
  - **ALWAYS** emit the `aggregator_warning` to BOTH stderr and sidecar when using
@@ -281,17 +281,17 @@ If any criterion is FAIL:
281
281
  2. Revise the affected PRD sections
282
282
  3. Re-submit to the reviewer
283
283
 
284
- Maximum 3 iterations. After 3 iterations with remaining issues, present them to the user via AskUserQuestion:
284
+ Maximum 3 iterations. After 3 iterations with remaining issues, list the flagged points in plain text (they are context, not a choice), then ask via AskUserQuestion:
285
285
 
286
286
  ```
287
287
  AskUserQuestion({
288
288
  questions: [{
289
- question: "The PRD reviewer flagged these remaining issues after 3 revision rounds:\n\n[list issues]\n\nHow do you want to proceed?",
289
+ question: "The reviewer still flags [N] points after 3 revision rounds. Proceed anyway?",
290
290
  header: "PRD Review",
291
291
  options: [
292
- { label: "Accept as-is (Recommended)", description: "Issues are minor, proceed with current PRD." },
293
- { label: "Manual edit", description: "I'll edit the PRD myself before continuing." },
294
- { label: "Re-run review", description: "Try one more revision round." }
292
+ { label: "Accept as-is (Recommended)", description: "Three rounds did not close them, so a fourth probably will not. The flags then stay in the PRD and travel into the issues filed from it." },
293
+ { label: "Manual edit", description: "You edit the PRD yourself; the flow waits, then re-runs the reviewer on your version." },
294
+ { label: "Re-run review", description: "One more revision round. Cost: another reviewer pass, and the same points may come back unchanged." }
295
295
  ],
296
296
  multiSelect: false
297
297
  }]
@@ -300,16 +300,16 @@ AskUserQuestion({
300
300
 
301
301
  ### 5.3 User Review Gate
302
302
 
303
- After the reviewer passes (or user accepts), present the final PRD:
303
+ After the reviewer passes (or user accepts), present the final PRD in plain text — path plus a short section summary — then ask:
304
304
 
305
305
  ```
306
306
  AskUserQuestion({
307
307
  questions: [{
308
- question: "PRD is ready for your review. It has been saved to [path].\n\nPlease review the document and confirm.",
308
+ question: "Approve the PRD at [path]?",
309
309
  header: "PRD Approval",
310
310
  options: [
311
- { label: "Approve PRD (Recommended)", description: "PRD looks good, proceed to issue creation." },
312
- { label: "Request changes", description: "I have feedback let me describe what to change." }
311
+ { label: "Approve PRD (Recommended)", description: "Nothing further is checked after this: approval commits the PRD to HEAD (Phase 5.5), then issue creation starts." },
312
+ { label: "Request changes", description: "Describe what to change; the PRD is rewritten and comes back here. No limit on rounds." }
313
313
  ],
314
314
  multiSelect: false
315
315
  }]
@@ -395,18 +395,20 @@ Assign labels from the standard taxonomy:
395
395
 
396
396
  ### 6.3 User Review
397
397
 
398
- Present the full issue structure via AskUserQuestion before creating anything:
398
+ Present the full issue structure via AskUserQuestion before creating anything. The table is the text that is about to be filed, so it belongs in `preview` — not in the question:
399
399
 
400
400
  ```
401
401
  AskUserQuestion({
402
402
  questions: [{
403
- question: "Proposed issue structure:\n\n**Epic:** [title]\n\n| # | Sub-Issue | Priority | Labels | Blocked By |\n|---|----------|----------|--------|------------|\n| 1 | [title] | critical | [labels] | — |\n| 2 | [title] | high | [labels] | #1 |\n| ... | ... | ... | ... | ... |\n\nTotal: [N] issues. Confirm or adjust.",
404
- header: "Issue Review",
403
+ question: "Create these [N] issues from the PRD?",
404
+ header: "Issues",
405
405
  options: [
406
- { label: "Create all issues (Recommended)", description: "Proceed with the proposed structure." },
407
- { label: "Adjust priorities", description: "I want to change some priorities before creating." },
408
- { label: "Remove issues", description: "Some issues should not be created." },
409
- { label: "Cancel", description: "Do not create any issues." }
406
+ { label: "Create all [N] (Recommended)",
407
+ description: "Priorities and blocked-by links come straight from the approved PRD. Cost: one API call per issue, ~1s apart.",
408
+ preview: "**Epic:** [title]\n\n| # | Sub-Issue | Priority | Labels | Blocked By |\n|---|----------|----------|--------|------------|\n| 1 | [title] | critical | [labels] | — |\n| 2 | [title] | high | [labels] | #1 |\n| ... | ... | ... | ... | ... |" },
409
+ { label: "Adjust priorities", description: "Same [N] issues, different priority labels. Name them and this question comes back with the table updated." },
410
+ { label: "Remove issues", description: "Name the ones to drop; the rest are created unchanged." },
411
+ { label: "Cancel", description: "Nothing is created. The PRD stays committed, so Phase 6 can run again later." }
410
412
  ],
411
413
  multiSelect: false
412
414
  }]
@@ -127,7 +127,7 @@ Apply per gitlab-ops skill label taxonomy:
127
127
 
128
128
  ### User Review Gate
129
129
 
130
- Present the full issue structure via AskUserQuestion before creation:
130
+ Present the full issue structure via the AskUserQuestion payload in `SKILL.md` § 6.3 — the issue table belongs in the option's `preview` field, not in the question text:
131
131
 
132
132
  - Epic title and description
133
133
  - Each sub-issue: title, priority, labels, dependency links
@@ -38,7 +38,7 @@ Agent({ subagent_type: "Explore", description: "Check ecosystem for conflicts",
38
38
  3. **Target audience** — Options informed by market research agent. User selects or provides custom.
39
39
  4. **User-Story-Schicht** — "User-Story-Schicht für dieses Feature erzeugen?" Immer fragen (kein Audience-Heuristik-Gate). Drei Antwortoptionen: **Ja (Als/möchte/damit)** — klassische Persona-Story-Form; **Ja (job-story)** — job-story-Form ("When [situation], I want [motivation], so I can [outcome]"); **Nein** — byte-identisches Status-quo-Verhalten. Bei einer der beiden "Ja"-Optionen emittiert die PRD eine optionale ## User Stories Sektion (je Story ein ↳ AC-Pointer) in der gewählten Form; bei "Nein" wird die Sektion vollständig weggelassen.
40
40
  5. **Core problem being solved** — Open-ended. Claude suggests structure if answer is vague.
41
- 6. **GitLab group** — Discover available groups dynamically. Run `ls $BASELINE_PATH/templates/` for project types, and check for a groups config in `$BASELINE_PATH/config/` or run `glab api "groups?per_page=100&min_access_level=10"` to discover GitLab groups — read each entry's `full_path` field. (`glab` has no `group` subcommand at all — invoking one exits 1 with `Unknown command "group"`.) Present findings via AskUserQuestion.
41
+ 6. **GitLab group** — Select the GitLab host explicitly, then discover available groups dynamically. Run `ls $BASELINE_PATH/templates/` for project types, and check for a groups config in `$BASELINE_PATH/config/` or run `glab api --hostname "$GITLAB_HOST" "groups?per_page=100&min_access_level=10"` to discover GitLab groups — read each entry's `full_path` field. (`glab` has no `group` subcommand at all — invoking one exits 1 with `Unknown command "group"`.) Present findings via AskUserQuestion.
42
42
 
43
43
  ### Wave 2 — Technical Details (5 questions, dynamic per archetype)
44
44
 
@@ -134,6 +134,12 @@ Map gathered answers to script input choices:
134
134
  # namespace in a separate variable — every later step addresses the project as
135
135
  # "<group-path>/<project>", and a numeric index there silently targets nothing.
136
136
  GROUP_PATH="$(...)" # e.g., "products" — the full_path of the chosen group
137
+
138
+ # These values identify the NEW project, not the directory in which this plan runs.
139
+ # Select the host with the group; do not let glab infer it from an ambient remote.
140
+ GITLAB_HOST="<selected GitLab hostname>"
141
+ PROJECT_PATH="$GROUP_PATH/$PROJECT_NAME"
142
+ ENCODED_PROJECT_PATH="$(node -e 'process.stdout.write(encodeURIComponent(process.argv[1]))' "$PROJECT_PATH")"
137
143
  (
138
144
  echo "$TYPE_CHOICE" # e.g., "1" for nextjs-saas
139
145
  echo "$STYLE_CHOICE" # e.g., "1" for vega (only if nextjs-saas)
@@ -145,10 +151,12 @@ GROUP_PATH="$(...)" # e.g., "products" — the full_path of the chosen group
145
151
 
146
152
  ### Step 2: Verify success
147
153
 
148
- Check exit code. Confirm repo exists:
154
+ Check the setup script exit code. Confirm the selected path exists without fetching a full REST project object:
149
155
 
150
156
  ```bash
151
- glab repo view "$GROUP_PATH/$PROJECT_NAME"
157
+ glab api --hostname "$GITLAB_HOST" graphql \
158
+ -f query='query($fullPath: ID!) { project(fullPath: $fullPath) { fullPath } }' \
159
+ -f fullPath="$PROJECT_PATH" | jq -er '.data.project.fullPath'
152
160
  ```
153
161
 
154
162
  ### Step 3: Adjust visibility
@@ -157,27 +165,29 @@ If visibility is not `internal` (the default):
157
165
 
158
166
  ```bash
159
167
  # There is no `glab repo edit`, and `glab repo update` carries no --visibility
160
- # flag (its FLAGS are --archive/--defaultBranch/-d/--description). Go through the
161
- # API, addressing the project by its URL-encoded path `projects/:id` resolves
162
- # from the CWD remote, which is the wrong project right after scaffolding.
163
- ENCODED="${GROUP_PATH}%2F${PROJECT_NAME}"
164
- glab api -X PUT "projects/${ENCODED}" -f visibility=private # or visibility=public
165
-
166
- # Verify (this GET is the read-only proof the PUT landed). Note `glab api` has
167
- # no --jq flag that is `gh api`'s. Pipe to jq instead.
168
- glab api "projects/${ENCODED}" | jq -r '.visibility'
168
+ # flag (its FLAGS are --archive/--defaultBranch/-d/--description). The encoded
169
+ # endpoint and explicit host target the new project independently of the CWD.
170
+ glab api --silent --hostname "$GITLAB_HOST" -X PUT \
171
+ "projects/${ENCODED_PROJECT_PATH}" \
172
+ -f visibility=private # or visibility=public
173
+
174
+ # Fetch only the scalar needed to verify the mutation, never a full REST object.
175
+ glab api --hostname "$GITLAB_HOST" graphql \
176
+ -f query='query($fullPath: ID!) { project(fullPath: $fullPath) { visibility } }' \
177
+ -f fullPath="$PROJECT_PATH" | jq -er '.data.project.visibility'
169
178
  ```
170
179
 
171
- > The GET path above is verified against glab 1.91.0; the PUT is the documented
172
- > GitLab API shape but was **not** executed during authoring (write operations
173
- > were out of scope). Confirm with the GET before relying on it.
180
+ > The GraphQL verification query is read-only and requests only `visibility`; the
181
+ > PUT's unused response is intentionally suppressed. Confirm the selected host and
182
+ > path before running the mutation.
174
183
 
175
184
  For public/OSS, also configure GitHub mirror if applicable.
176
185
 
177
186
  ### Step 4: Set branch protection
178
187
 
179
188
  ```bash
180
- glab api -X PUT projects/:id/protected_branches \
189
+ glab api --silent --hostname "$GITLAB_HOST" -X POST \
190
+ "projects/${ENCODED_PROJECT_PATH}/protected_branches" \
181
191
  -f name=main \
182
192
  -f push_access_level=30 \
183
193
  -f merge_access_level=30
@@ -282,7 +292,7 @@ Always use the `priority::<level>` format in VCS CLI commands, not P0/P1/P2/P3.
282
292
 
283
293
  ### Step 4: Present for user confirmation
284
294
 
285
- Use AskUserQuestion to present the full issue structure:
295
+ Use the AskUserQuestion payload in `SKILL.md` § 6.3 verbatim — the issue table belongs in the option's `preview` field, not in the question text:
286
296
 
287
297
  - Epic title and description
288
298
  - Sub-issues with: title, priority, labels, dependency links
@@ -292,11 +302,11 @@ Use AskUserQuestion to present the full issue structure:
292
302
 
293
303
  ```bash
294
304
  # Create epic
295
- glab issue create -R "$GROUP_PATH/$PROJECT_NAME" --title "$EPIC_TITLE" --description "$EPIC_DESC" \
305
+ glab issue create -R "https://${GITLAB_HOST}/${PROJECT_PATH}" --title "$EPIC_TITLE" --description "$EPIC_DESC" \
296
306
  --label "type:epic,priority::$PRIORITY" --milestone "$MILESTONE"
297
307
 
298
308
  # Create sub-issues
299
- glab issue create -R "$GROUP_PATH/$PROJECT_NAME" --title "$ISSUE_TITLE" --description "$ISSUE_DESC" \
309
+ glab issue create -R "https://${GITLAB_HOST}/${PROJECT_PATH}" --title "$ISSUE_TITLE" --description "$ISSUE_DESC" \
300
310
  --label "type:feature,priority::$PRIORITY,status:ready,area:$AREA,appetite:$APPETITE"
301
311
  ```
302
312
 
@@ -305,10 +315,12 @@ glab issue create -R "$GROUP_PATH/$PROJECT_NAME" --title "$ISSUE_TITLE" --descri
305
315
  For issues with technical dependencies, set `blocks`/`is-blocked-by` relationships:
306
316
 
307
317
  ```bash
308
- # Issue #2 is blocked by Issue #1
309
- glab api -X POST projects/:id/issues/:issue2_iid/links \
310
- -f target_project_id=:id \
311
- -f target_issue_iid=:issue1_iid \
318
+ # Issue #2 is blocked by Issue #1 in this project. An encoded project path is
319
+ # valid for target_project_id, so no numeric project ID is needed.
320
+ glab api --silent --hostname "$GITLAB_HOST" -X POST \
321
+ "projects/${ENCODED_PROJECT_PATH}/issues/${ISSUE_2_IID}/links" \
322
+ -f target_project_id="$ENCODED_PROJECT_PATH" \
323
+ -f target_issue_iid="$ISSUE_1_IID" \
312
324
  -f link_type=is_blocked_by
313
325
  ```
314
326
 
@@ -69,6 +69,18 @@ The active level is `efficiency.output-level` in `~/.config/session-orchestrator
69
69
  - Shape: name the alternatives you rejected and why, spell out the appetite and the scope cuts, define unfamiliar terms on first use.
70
70
  - Escalation: `expand <topic>` — see § Escalation above.
71
71
 
72
+ ### Register — how a sentence reads
73
+
74
+ The budgets above set *how much* you say; the register sets *how*. It is
75
+ defined once, in `skills/session-start/soul.md` § "Register — how a sentence
76
+ reads", and binds here unchanged: the frame ("write for someone who knows this
77
+ project but has not seen what you just saw"), the plain-words test with its
78
+ five worked cases, and its precedence over § "Never traded for brevity" above.
79
+ Read it there. It is not repeated here on purpose — the § Output Levels intro
80
+ sentence already exists in four copies across the four souls with nothing
81
+ checking their parity, and a fifth copied rule would drift the same way. A
82
+ pointer cannot.
83
+
72
84
  ### Companion dials
73
85
 
74
86
  Same file, same lookup, same fallback-to-default rule: