kenaz 0.0.0-stage → 0.3.2

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 (1641) hide show
  1. package/bin/kenaz.js +3 -0
  2. package/core/.agents/skills/remotion-best-practices/SKILL.md +61 -0
  3. package/core/.agents/skills/remotion-best-practices/rules/3d.md +86 -0
  4. package/core/.agents/skills/remotion-best-practices/rules/animations.md +27 -0
  5. package/core/.agents/skills/remotion-best-practices/rules/assets/charts-bar-chart.tsx +173 -0
  6. package/core/.agents/skills/remotion-best-practices/rules/assets/text-animations-typewriter.tsx +100 -0
  7. package/core/.agents/skills/remotion-best-practices/rules/assets/text-animations-word-highlight.tsx +103 -0
  8. package/core/.agents/skills/remotion-best-practices/rules/assets.md +78 -0
  9. package/core/.agents/skills/remotion-best-practices/rules/audio-visualization.md +198 -0
  10. package/core/.agents/skills/remotion-best-practices/rules/audio.md +169 -0
  11. package/core/.agents/skills/remotion-best-practices/rules/calculate-metadata.md +134 -0
  12. package/core/.agents/skills/remotion-best-practices/rules/can-decode.md +81 -0
  13. package/core/.agents/skills/remotion-best-practices/rules/charts.md +120 -0
  14. package/core/.agents/skills/remotion-best-practices/rules/compositions.md +154 -0
  15. package/core/.agents/skills/remotion-best-practices/rules/display-captions.md +184 -0
  16. package/core/.agents/skills/remotion-best-practices/rules/extract-frames.md +229 -0
  17. package/core/.agents/skills/remotion-best-practices/rules/ffmpeg.md +38 -0
  18. package/core/.agents/skills/remotion-best-practices/rules/fonts.md +152 -0
  19. package/core/.agents/skills/remotion-best-practices/rules/get-audio-duration.md +58 -0
  20. package/core/.agents/skills/remotion-best-practices/rules/get-video-dimensions.md +68 -0
  21. package/core/.agents/skills/remotion-best-practices/rules/get-video-duration.md +60 -0
  22. package/core/.agents/skills/remotion-best-practices/rules/gifs.md +141 -0
  23. package/core/.agents/skills/remotion-best-practices/rules/images.md +134 -0
  24. package/core/.agents/skills/remotion-best-practices/rules/import-srt-captions.md +69 -0
  25. package/core/.agents/skills/remotion-best-practices/rules/light-leaks.md +73 -0
  26. package/core/.agents/skills/remotion-best-practices/rules/lottie.md +70 -0
  27. package/core/.agents/skills/remotion-best-practices/rules/maps.md +412 -0
  28. package/core/.agents/skills/remotion-best-practices/rules/measuring-dom-nodes.md +34 -0
  29. package/core/.agents/skills/remotion-best-practices/rules/measuring-text.md +140 -0
  30. package/core/.agents/skills/remotion-best-practices/rules/parameters.md +109 -0
  31. package/core/.agents/skills/remotion-best-practices/rules/sequencing.md +118 -0
  32. package/core/.agents/skills/remotion-best-practices/rules/sfx.md +30 -0
  33. package/core/.agents/skills/remotion-best-practices/rules/subtitles.md +36 -0
  34. package/core/.agents/skills/remotion-best-practices/rules/tailwind.md +11 -0
  35. package/core/.agents/skills/remotion-best-practices/rules/text-animations.md +20 -0
  36. package/core/.agents/skills/remotion-best-practices/rules/timing.md +179 -0
  37. package/core/.agents/skills/remotion-best-practices/rules/transcribe-captions.md +70 -0
  38. package/core/.agents/skills/remotion-best-practices/rules/transitions.md +197 -0
  39. package/core/.agents/skills/remotion-best-practices/rules/transparent-videos.md +106 -0
  40. package/core/.agents/skills/remotion-best-practices/rules/trimming.md +51 -0
  41. package/core/.agents/skills/remotion-best-practices/rules/videos.md +171 -0
  42. package/core/.agents/skills/remotion-best-practices/rules/voiceover.md +99 -0
  43. package/core/.agents/skills/supabase-postgres-best-practices/AGENTS.md +90 -0
  44. package/core/.agents/skills/supabase-postgres-best-practices/CLAUDE.md +1 -0
  45. package/core/.agents/skills/supabase-postgres-best-practices/SKILL.md +64 -0
  46. package/core/.agents/skills/supabase-postgres-best-practices/references/advanced-full-text-search.md +55 -0
  47. package/core/.agents/skills/supabase-postgres-best-practices/references/advanced-jsonb-indexing.md +49 -0
  48. package/core/.agents/skills/supabase-postgres-best-practices/references/conn-idle-timeout.md +46 -0
  49. package/core/.agents/skills/supabase-postgres-best-practices/references/conn-limits.md +44 -0
  50. package/core/.agents/skills/supabase-postgres-best-practices/references/conn-pooling.md +41 -0
  51. package/core/.agents/skills/supabase-postgres-best-practices/references/conn-prepared-statements.md +46 -0
  52. package/core/.agents/skills/supabase-postgres-best-practices/references/data-batch-inserts.md +54 -0
  53. package/core/.agents/skills/supabase-postgres-best-practices/references/data-n-plus-one.md +53 -0
  54. package/core/.agents/skills/supabase-postgres-best-practices/references/data-pagination.md +50 -0
  55. package/core/.agents/skills/supabase-postgres-best-practices/references/data-upsert.md +50 -0
  56. package/core/.agents/skills/supabase-postgres-best-practices/references/lock-advisory.md +56 -0
  57. package/core/.agents/skills/supabase-postgres-best-practices/references/lock-deadlock-prevention.md +68 -0
  58. package/core/.agents/skills/supabase-postgres-best-practices/references/lock-short-transactions.md +50 -0
  59. package/core/.agents/skills/supabase-postgres-best-practices/references/lock-skip-locked.md +54 -0
  60. package/core/.agents/skills/supabase-postgres-best-practices/references/monitor-explain-analyze.md +45 -0
  61. package/core/.agents/skills/supabase-postgres-best-practices/references/monitor-pg-stat-statements.md +55 -0
  62. package/core/.agents/skills/supabase-postgres-best-practices/references/monitor-vacuum-analyze.md +55 -0
  63. package/core/.agents/skills/supabase-postgres-best-practices/references/query-composite-indexes.md +44 -0
  64. package/core/.agents/skills/supabase-postgres-best-practices/references/query-covering-indexes.md +40 -0
  65. package/core/.agents/skills/supabase-postgres-best-practices/references/query-index-types.md +45 -0
  66. package/core/.agents/skills/supabase-postgres-best-practices/references/query-missing-indexes.md +43 -0
  67. package/core/.agents/skills/supabase-postgres-best-practices/references/query-partial-indexes.md +45 -0
  68. package/core/.agents/skills/supabase-postgres-best-practices/references/schema-data-types.md +46 -0
  69. package/core/.agents/skills/supabase-postgres-best-practices/references/schema-foreign-key-indexes.md +59 -0
  70. package/core/.agents/skills/supabase-postgres-best-practices/references/schema-lowercase-identifiers.md +55 -0
  71. package/core/.agents/skills/supabase-postgres-best-practices/references/schema-partitioning.md +55 -0
  72. package/core/.agents/skills/supabase-postgres-best-practices/references/schema-primary-keys.md +61 -0
  73. package/core/.agents/skills/supabase-postgres-best-practices/references/security-privileges.md +54 -0
  74. package/core/.agents/skills/supabase-postgres-best-practices/references/security-rls-basics.md +50 -0
  75. package/core/.agents/skills/supabase-postgres-best-practices/references/security-rls-performance.md +57 -0
  76. package/core/.agents/skills/typesafe-ai/LICENSE +21 -0
  77. package/core/.agents/skills/typesafe-ai/SKILL.md +149 -0
  78. package/core/.agents/skills/vercel-react-best-practices/AGENTS.md +2934 -0
  79. package/core/.agents/skills/vercel-react-best-practices/SKILL.md +136 -0
  80. package/core/.agents/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  81. package/core/.agents/skills/vercel-react-best-practices/rules/advanced-init-once.md +42 -0
  82. package/core/.agents/skills/vercel-react-best-practices/rules/advanced-use-latest.md +39 -0
  83. package/core/.agents/skills/vercel-react-best-practices/rules/async-api-routes.md +38 -0
  84. package/core/.agents/skills/vercel-react-best-practices/rules/async-defer-await.md +80 -0
  85. package/core/.agents/skills/vercel-react-best-practices/rules/async-dependencies.md +51 -0
  86. package/core/.agents/skills/vercel-react-best-practices/rules/async-parallel.md +28 -0
  87. package/core/.agents/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +99 -0
  88. package/core/.agents/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +59 -0
  89. package/core/.agents/skills/vercel-react-best-practices/rules/bundle-conditional.md +31 -0
  90. package/core/.agents/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +49 -0
  91. package/core/.agents/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  92. package/core/.agents/skills/vercel-react-best-practices/rules/bundle-preload.md +50 -0
  93. package/core/.agents/skills/vercel-react-best-practices/rules/client-event-listeners.md +74 -0
  94. package/core/.agents/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +71 -0
  95. package/core/.agents/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +48 -0
  96. package/core/.agents/skills/vercel-react-best-practices/rules/client-swr-dedup.md +56 -0
  97. package/core/.agents/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +107 -0
  98. package/core/.agents/skills/vercel-react-best-practices/rules/js-cache-function-results.md +80 -0
  99. package/core/.agents/skills/vercel-react-best-practices/rules/js-cache-property-access.md +28 -0
  100. package/core/.agents/skills/vercel-react-best-practices/rules/js-cache-storage.md +70 -0
  101. package/core/.agents/skills/vercel-react-best-practices/rules/js-combine-iterations.md +32 -0
  102. package/core/.agents/skills/vercel-react-best-practices/rules/js-early-exit.md +50 -0
  103. package/core/.agents/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +45 -0
  104. package/core/.agents/skills/vercel-react-best-practices/rules/js-index-maps.md +37 -0
  105. package/core/.agents/skills/vercel-react-best-practices/rules/js-length-check-first.md +49 -0
  106. package/core/.agents/skills/vercel-react-best-practices/rules/js-min-max-loop.md +82 -0
  107. package/core/.agents/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +24 -0
  108. package/core/.agents/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +57 -0
  109. package/core/.agents/skills/vercel-react-best-practices/rules/rendering-activity.md +26 -0
  110. package/core/.agents/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  111. package/core/.agents/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +40 -0
  112. package/core/.agents/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +38 -0
  113. package/core/.agents/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  114. package/core/.agents/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  115. package/core/.agents/skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
  116. package/core/.agents/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +28 -0
  117. package/core/.agents/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md +75 -0
  118. package/core/.agents/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +39 -0
  119. package/core/.agents/skills/vercel-react-best-practices/rules/rerender-dependencies.md +45 -0
  120. package/core/.agents/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
  121. package/core/.agents/skills/vercel-react-best-practices/rules/rerender-derived-state.md +29 -0
  122. package/core/.agents/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +74 -0
  123. package/core/.agents/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  124. package/core/.agents/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
  125. package/core/.agents/skills/vercel-react-best-practices/rules/rerender-memo.md +44 -0
  126. package/core/.agents/skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
  127. package/core/.agents/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
  128. package/core/.agents/skills/vercel-react-best-practices/rules/rerender-transitions.md +40 -0
  129. package/core/.agents/skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
  130. package/core/.agents/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +73 -0
  131. package/core/.agents/skills/vercel-react-best-practices/rules/server-auth-actions.md +96 -0
  132. package/core/.agents/skills/vercel-react-best-practices/rules/server-cache-lru.md +41 -0
  133. package/core/.agents/skills/vercel-react-best-practices/rules/server-cache-react.md +76 -0
  134. package/core/.agents/skills/vercel-react-best-practices/rules/server-dedup-props.md +65 -0
  135. package/core/.agents/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +83 -0
  136. package/core/.agents/skills/vercel-react-best-practices/rules/server-serialization.md +38 -0
  137. package/core/.claude/agents/pcb-reviewer.md +146 -0
  138. package/core/.claude/commands/Amelia.md +5 -0
  139. package/core/.claude/commands/Ansuz.md +38 -0
  140. package/core/.claude/commands/Huginn.md +25 -0
  141. package/core/.claude/commands/agent-worker.md +168 -0
  142. package/core/.claude/commands/architect.md +24 -0
  143. package/core/.claude/commands/archive.md +24 -0
  144. package/core/.claude/commands/canary.md +17 -0
  145. package/core/.claude/commands/incident.md +15 -0
  146. package/core/.claude/commands/init.md +112 -0
  147. package/core/.claude/commands/legacy_dev.md +18 -0
  148. package/core/.claude/commands/product-review.md +131 -0
  149. package/core/.claude/commands/review.md +14 -0
  150. package/core/.claude/commands/security.md +15 -0
  151. package/core/.claude/commands/spec.md +22 -0
  152. package/core/.claude/commands/strategy.md +141 -0
  153. package/core/.claude/commands/sunny.md +1 -0
  154. package/core/.claude/commands//347/224/242/345/223/201.md +15 -0
  155. package/core/.claude/commands//347/224/242/345/223/201/346/252/242/350/246/226.md +129 -0
  156. package/core/.claude/commands//350/250/255/350/250/210.md +14 -0
  157. package/core/.claude/commands//350/251/225/344/274/260.md +16 -0
  158. package/core/.claude/commands//351/200/262/345/272/246.md +15 -0
  159. package/core/.claude/hooks/__tests__/substrate.test.js +122 -0
  160. package/core/.claude/hooks/__tests__/task-1866-cli-guard.test.js +193 -0
  161. package/core/.claude/hooks/__tests__/task-1977-dedupe-guard.test.js +125 -0
  162. package/core/.claude/hooks/__tests__/task-2087-mark-landed-idempotent.test.js +128 -0
  163. package/core/.claude/hooks/__tests__/task-2253-null-tip-marker-reuse.test.js +84 -0
  164. package/core/.claude/hooks/__tests__/task-2381-project-guard-walkup.test.js +53 -0
  165. package/core/.claude/hooks/_ansuz-conversation.js +183 -0
  166. package/core/.claude/hooks/_ansuz-conversation.test.js +90 -0
  167. package/core/.claude/hooks/_dedupe-guard.js +75 -0
  168. package/core/.claude/hooks/_peer-project-root.js +113 -0
  169. package/core/.claude/hooks/_peer-project-root.test.js +121 -0
  170. package/core/.claude/hooks/_peer-waiting-line.js +27 -0
  171. package/core/.claude/hooks/_project-guard.js +45 -0
  172. package/core/.claude/hooks/_run-user-prompt.js +134 -0
  173. package/core/.claude/hooks/_run-user-prompt.test.js +80 -0
  174. package/core/.claude/hooks/_session-identity.js +62 -0
  175. package/core/.claude/hooks/_session-pin.js +34 -0
  176. package/core/.claude/hooks/_session-pin.test.js +89 -0
  177. package/core/.claude/hooks/_signal-fence.js +17 -0
  178. package/core/.claude/hooks/_substrate-paths.js +95 -0
  179. package/core/.claude/hooks/_user-scope.js +23 -0
  180. package/core/.claude/hooks/ansuz-session-pin-via-turn-context.test.js +52 -0
  181. package/core/.claude/hooks/ansuz-session-pin.js +171 -0
  182. package/core/.claude/hooks/ansuz-session-pin.test.js +140 -0
  183. package/core/.claude/hooks/context-check.js +51 -0
  184. package/core/.claude/hooks/core-resolve.js +230 -0
  185. package/core/.claude/hooks/daemon-outbox-hook.js +139 -0
  186. package/core/.claude/hooks/fatigue-check.js +52 -0
  187. package/core/.claude/hooks/handoff-snapshot-on-commit.js +154 -0
  188. package/core/.claude/hooks/handoff-snapshot-on-decision.js +188 -0
  189. package/core/.claude/hooks/handoff-snapshot-on-question.js +158 -0
  190. package/core/.claude/hooks/handoff-staleness.js +197 -0
  191. package/core/.claude/hooks/jev-thalamus-context.js +17 -0
  192. package/core/.claude/hooks/jev-thalamus-context.test.js +41 -0
  193. package/core/.claude/hooks/lease-release.js +119 -0
  194. package/core/.claude/hooks/lease-touch.js +96 -0
  195. package/core/.claude/hooks/memory-guard.js +723 -0
  196. package/core/.claude/hooks/memory-guard.test.js +574 -0
  197. package/core/.claude/hooks/reflex-feedback.js +5 -0
  198. package/core/.claude/hooks/session-init.ps1 +49 -0
  199. package/core/.claude/hooks/sound-event.js +70 -0
  200. package/core/.claude/hooks/sound-event.sh +37 -0
  201. package/core/.claude/hooks/stream-delta.js +169 -0
  202. package/core/.claude/hooks/synapse-first-investigation.js +326 -0
  203. package/core/.claude/hooks/synapse-first-investigation.test.js +126 -0
  204. package/core/.claude/hooks/task-bridge.js +33 -0
  205. package/core/.claude/hooks/turn-context-peer.test.js +115 -0
  206. package/core/.claude/hooks/turn-context-session-line.test.js +69 -0
  207. package/core/.claude/hooks/turn-context.js +215 -0
  208. package/core/.claude/hooks/worktree-create.js +1232 -0
  209. package/core/.claude/hooks/worktree-remove.js +181 -0
  210. package/core/.claude/no-hooks.settings.json +3 -0
  211. package/core/.claude/settings.json +180 -0
  212. package/core/.claude/skills/adapt/SKILL.md +199 -0
  213. package/core/.claude/skills/animate/SKILL.md +190 -0
  214. package/core/.claude/skills/architect_agent/SKILL.md +408 -0
  215. package/core/.claude/skills/assessment_agent/SKILL.md +289 -0
  216. package/core/.claude/skills/audit/SKILL.md +129 -0
  217. package/core/.claude/skills/backend_agent/SKILL.md +407 -0
  218. package/core/.claude/skills/backend_engineer/SKILL.md +788 -0
  219. package/core/.claude/skills/bolder/SKILL.md +132 -0
  220. package/core/.claude/skills/clarify/SKILL.md +180 -0
  221. package/core/.claude/skills/code_reviewer/SKILL.md +305 -0
  222. package/core/.claude/skills/code_reviewer/patterns.yaml +85 -0
  223. package/core/.claude/skills/colorize/SKILL.md +158 -0
  224. package/core/.claude/skills/critique/SKILL.md +118 -0
  225. package/core/.claude/skills/delight/SKILL.md +317 -0
  226. package/core/.claude/skills/designer/SKILL.md +845 -0
  227. package/core/.claude/skills/dev_agent/SKILL.md +503 -0
  228. package/core/.claude/skills/developer/SKILL.md +792 -0
  229. package/core/.claude/skills/distill/SKILL.md +137 -0
  230. package/core/.claude/skills/extract/SKILL.md +95 -0
  231. package/core/.claude/skills/feature_agent/SKILL.md +303 -0
  232. package/core/.claude/skills/frontend-design/SKILL.md +127 -0
  233. package/core/.claude/skills/frontend-design/reference/color-and-contrast.md +132 -0
  234. package/core/.claude/skills/frontend-design/reference/interaction-design.md +123 -0
  235. package/core/.claude/skills/frontend-design/reference/motion-design.md +99 -0
  236. package/core/.claude/skills/frontend-design/reference/responsive-design.md +114 -0
  237. package/core/.claude/skills/frontend-design/reference/spatial-design.md +100 -0
  238. package/core/.claude/skills/frontend-design/reference/typography.md +131 -0
  239. package/core/.claude/skills/frontend-design/reference/ux-writing.md +107 -0
  240. package/core/.claude/skills/frontend_agent/SKILL.md +327 -0
  241. package/core/.claude/skills/harden/SKILL.md +358 -0
  242. package/core/.claude/skills/heimdall/SKILL.md +84 -0
  243. package/core/.claude/skills/huginn/SKILL.md +208 -0
  244. package/core/.claude/skills/incident_response/SKILL.md +315 -0
  245. package/core/.claude/skills/legacy_dev/SKILL.md +202 -0
  246. package/core/.claude/skills/normalize/SKILL.md +67 -0
  247. package/core/.claude/skills/onboard/SKILL.md +243 -0
  248. package/core/.claude/skills/optimization_agent/SKILL.md +340 -0
  249. package/core/.claude/skills/optimize/SKILL.md +269 -0
  250. package/core/.claude/skills/pcb-review/SKILL.md +39 -0
  251. package/core/.claude/skills/polish/SKILL.md +202 -0
  252. package/core/.claude/skills/product_manager/SKILL.md +1091 -0
  253. package/core/.claude/skills/qa_engineer/SKILL.md +1269 -0
  254. package/core/.claude/skills/quieter/SKILL.md +118 -0
  255. package/core/.claude/skills/remotion-best-practices/SKILL.md +61 -0
  256. package/core/.claude/skills/remotion-best-practices/rules/3d.md +86 -0
  257. package/core/.claude/skills/remotion-best-practices/rules/animations.md +27 -0
  258. package/core/.claude/skills/remotion-best-practices/rules/assets/charts-bar-chart.tsx +173 -0
  259. package/core/.claude/skills/remotion-best-practices/rules/assets/text-animations-typewriter.tsx +100 -0
  260. package/core/.claude/skills/remotion-best-practices/rules/assets/text-animations-word-highlight.tsx +103 -0
  261. package/core/.claude/skills/remotion-best-practices/rules/assets.md +78 -0
  262. package/core/.claude/skills/remotion-best-practices/rules/audio-visualization.md +198 -0
  263. package/core/.claude/skills/remotion-best-practices/rules/audio.md +169 -0
  264. package/core/.claude/skills/remotion-best-practices/rules/calculate-metadata.md +134 -0
  265. package/core/.claude/skills/remotion-best-practices/rules/can-decode.md +81 -0
  266. package/core/.claude/skills/remotion-best-practices/rules/charts.md +120 -0
  267. package/core/.claude/skills/remotion-best-practices/rules/compositions.md +154 -0
  268. package/core/.claude/skills/remotion-best-practices/rules/display-captions.md +184 -0
  269. package/core/.claude/skills/remotion-best-practices/rules/extract-frames.md +229 -0
  270. package/core/.claude/skills/remotion-best-practices/rules/ffmpeg.md +38 -0
  271. package/core/.claude/skills/remotion-best-practices/rules/fonts.md +152 -0
  272. package/core/.claude/skills/remotion-best-practices/rules/get-audio-duration.md +58 -0
  273. package/core/.claude/skills/remotion-best-practices/rules/get-video-dimensions.md +68 -0
  274. package/core/.claude/skills/remotion-best-practices/rules/get-video-duration.md +60 -0
  275. package/core/.claude/skills/remotion-best-practices/rules/gifs.md +141 -0
  276. package/core/.claude/skills/remotion-best-practices/rules/images.md +134 -0
  277. package/core/.claude/skills/remotion-best-practices/rules/import-srt-captions.md +69 -0
  278. package/core/.claude/skills/remotion-best-practices/rules/light-leaks.md +73 -0
  279. package/core/.claude/skills/remotion-best-practices/rules/lottie.md +70 -0
  280. package/core/.claude/skills/remotion-best-practices/rules/maps.md +412 -0
  281. package/core/.claude/skills/remotion-best-practices/rules/measuring-dom-nodes.md +34 -0
  282. package/core/.claude/skills/remotion-best-practices/rules/measuring-text.md +140 -0
  283. package/core/.claude/skills/remotion-best-practices/rules/parameters.md +109 -0
  284. package/core/.claude/skills/remotion-best-practices/rules/sequencing.md +118 -0
  285. package/core/.claude/skills/remotion-best-practices/rules/sfx.md +30 -0
  286. package/core/.claude/skills/remotion-best-practices/rules/subtitles.md +36 -0
  287. package/core/.claude/skills/remotion-best-practices/rules/tailwind.md +11 -0
  288. package/core/.claude/skills/remotion-best-practices/rules/text-animations.md +20 -0
  289. package/core/.claude/skills/remotion-best-practices/rules/timing.md +179 -0
  290. package/core/.claude/skills/remotion-best-practices/rules/transcribe-captions.md +70 -0
  291. package/core/.claude/skills/remotion-best-practices/rules/transitions.md +197 -0
  292. package/core/.claude/skills/remotion-best-practices/rules/transparent-videos.md +106 -0
  293. package/core/.claude/skills/remotion-best-practices/rules/trimming.md +51 -0
  294. package/core/.claude/skills/remotion-best-practices/rules/videos.md +171 -0
  295. package/core/.claude/skills/remotion-best-practices/rules/voiceover.md +99 -0
  296. package/core/.claude/skills/security_agent/SKILL.md +312 -0
  297. package/core/.claude/skills/spec_optimizer/SKILL.md +299 -0
  298. package/core/.claude/skills/sre_agent/SKILL.md +1347 -0
  299. package/core/.claude/skills/sunny/SKILL.md +74 -0
  300. package/core/.claude/skills/supabase-postgres-best-practices/AGENTS.md +90 -0
  301. package/core/.claude/skills/supabase-postgres-best-practices/CLAUDE.md +1 -0
  302. package/core/.claude/skills/supabase-postgres-best-practices/SKILL.md +64 -0
  303. package/core/.claude/skills/supabase-postgres-best-practices/references/advanced-full-text-search.md +55 -0
  304. package/core/.claude/skills/supabase-postgres-best-practices/references/advanced-jsonb-indexing.md +49 -0
  305. package/core/.claude/skills/supabase-postgres-best-practices/references/conn-idle-timeout.md +46 -0
  306. package/core/.claude/skills/supabase-postgres-best-practices/references/conn-limits.md +44 -0
  307. package/core/.claude/skills/supabase-postgres-best-practices/references/conn-pooling.md +41 -0
  308. package/core/.claude/skills/supabase-postgres-best-practices/references/conn-prepared-statements.md +46 -0
  309. package/core/.claude/skills/supabase-postgres-best-practices/references/data-batch-inserts.md +54 -0
  310. package/core/.claude/skills/supabase-postgres-best-practices/references/data-n-plus-one.md +53 -0
  311. package/core/.claude/skills/supabase-postgres-best-practices/references/data-pagination.md +50 -0
  312. package/core/.claude/skills/supabase-postgres-best-practices/references/data-upsert.md +50 -0
  313. package/core/.claude/skills/supabase-postgres-best-practices/references/lock-advisory.md +56 -0
  314. package/core/.claude/skills/supabase-postgres-best-practices/references/lock-deadlock-prevention.md +68 -0
  315. package/core/.claude/skills/supabase-postgres-best-practices/references/lock-short-transactions.md +50 -0
  316. package/core/.claude/skills/supabase-postgres-best-practices/references/lock-skip-locked.md +54 -0
  317. package/core/.claude/skills/supabase-postgres-best-practices/references/monitor-explain-analyze.md +45 -0
  318. package/core/.claude/skills/supabase-postgres-best-practices/references/monitor-pg-stat-statements.md +55 -0
  319. package/core/.claude/skills/supabase-postgres-best-practices/references/monitor-vacuum-analyze.md +55 -0
  320. package/core/.claude/skills/supabase-postgres-best-practices/references/query-composite-indexes.md +44 -0
  321. package/core/.claude/skills/supabase-postgres-best-practices/references/query-covering-indexes.md +40 -0
  322. package/core/.claude/skills/supabase-postgres-best-practices/references/query-index-types.md +45 -0
  323. package/core/.claude/skills/supabase-postgres-best-practices/references/query-missing-indexes.md +43 -0
  324. package/core/.claude/skills/supabase-postgres-best-practices/references/query-partial-indexes.md +45 -0
  325. package/core/.claude/skills/supabase-postgres-best-practices/references/schema-data-types.md +46 -0
  326. package/core/.claude/skills/supabase-postgres-best-practices/references/schema-foreign-key-indexes.md +59 -0
  327. package/core/.claude/skills/supabase-postgres-best-practices/references/schema-lowercase-identifiers.md +55 -0
  328. package/core/.claude/skills/supabase-postgres-best-practices/references/schema-partitioning.md +55 -0
  329. package/core/.claude/skills/supabase-postgres-best-practices/references/schema-primary-keys.md +61 -0
  330. package/core/.claude/skills/supabase-postgres-best-practices/references/security-privileges.md +54 -0
  331. package/core/.claude/skills/supabase-postgres-best-practices/references/security-rls-basics.md +50 -0
  332. package/core/.claude/skills/supabase-postgres-best-practices/references/security-rls-performance.md +57 -0
  333. package/core/.claude/skills/synapse_maintain/SKILL.md +84 -0
  334. package/core/.claude/skills/ui-ux-pro-max/SKILL.md +377 -0
  335. package/core/.claude/skills/ui-ux-pro-max/data/charts.csv +26 -0
  336. package/core/.claude/skills/ui-ux-pro-max/data/colors.csv +97 -0
  337. package/core/.claude/skills/ui-ux-pro-max/data/icons.csv +101 -0
  338. package/core/.claude/skills/ui-ux-pro-max/data/landing.csv +31 -0
  339. package/core/.claude/skills/ui-ux-pro-max/data/products.csv +97 -0
  340. package/core/.claude/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
  341. package/core/.claude/skills/ui-ux-pro-max/data/stacks/astro.csv +54 -0
  342. package/core/.claude/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  343. package/core/.claude/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  344. package/core/.claude/skills/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
  345. package/core/.claude/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  346. package/core/.claude/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  347. package/core/.claude/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  348. package/core/.claude/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  349. package/core/.claude/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
  350. package/core/.claude/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  351. package/core/.claude/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  352. package/core/.claude/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  353. package/core/.claude/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  354. package/core/.claude/skills/ui-ux-pro-max/data/styles.csv +68 -0
  355. package/core/.claude/skills/ui-ux-pro-max/data/typography.csv +58 -0
  356. package/core/.claude/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
  357. package/core/.claude/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  358. package/core/.claude/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
  359. package/core/.claude/skills/ui-ux-pro-max/scripts/core.py +253 -0
  360. package/core/.claude/skills/ui-ux-pro-max/scripts/design_system.py +1067 -0
  361. package/core/.claude/skills/ui-ux-pro-max/scripts/search.py +106 -0
  362. package/core/.claude/skills/vercel-react-best-practices/AGENTS.md +2934 -0
  363. package/core/.claude/skills/vercel-react-best-practices/SKILL.md +136 -0
  364. package/core/.claude/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  365. package/core/.claude/skills/vercel-react-best-practices/rules/advanced-init-once.md +42 -0
  366. package/core/.claude/skills/vercel-react-best-practices/rules/advanced-use-latest.md +39 -0
  367. package/core/.claude/skills/vercel-react-best-practices/rules/async-api-routes.md +38 -0
  368. package/core/.claude/skills/vercel-react-best-practices/rules/async-defer-await.md +80 -0
  369. package/core/.claude/skills/vercel-react-best-practices/rules/async-dependencies.md +51 -0
  370. package/core/.claude/skills/vercel-react-best-practices/rules/async-parallel.md +28 -0
  371. package/core/.claude/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +99 -0
  372. package/core/.claude/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +59 -0
  373. package/core/.claude/skills/vercel-react-best-practices/rules/bundle-conditional.md +31 -0
  374. package/core/.claude/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +49 -0
  375. package/core/.claude/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  376. package/core/.claude/skills/vercel-react-best-practices/rules/bundle-preload.md +50 -0
  377. package/core/.claude/skills/vercel-react-best-practices/rules/client-event-listeners.md +74 -0
  378. package/core/.claude/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +71 -0
  379. package/core/.claude/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +48 -0
  380. package/core/.claude/skills/vercel-react-best-practices/rules/client-swr-dedup.md +56 -0
  381. package/core/.claude/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +107 -0
  382. package/core/.claude/skills/vercel-react-best-practices/rules/js-cache-function-results.md +80 -0
  383. package/core/.claude/skills/vercel-react-best-practices/rules/js-cache-property-access.md +28 -0
  384. package/core/.claude/skills/vercel-react-best-practices/rules/js-cache-storage.md +70 -0
  385. package/core/.claude/skills/vercel-react-best-practices/rules/js-combine-iterations.md +32 -0
  386. package/core/.claude/skills/vercel-react-best-practices/rules/js-early-exit.md +50 -0
  387. package/core/.claude/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +45 -0
  388. package/core/.claude/skills/vercel-react-best-practices/rules/js-index-maps.md +37 -0
  389. package/core/.claude/skills/vercel-react-best-practices/rules/js-length-check-first.md +49 -0
  390. package/core/.claude/skills/vercel-react-best-practices/rules/js-min-max-loop.md +82 -0
  391. package/core/.claude/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +24 -0
  392. package/core/.claude/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +57 -0
  393. package/core/.claude/skills/vercel-react-best-practices/rules/rendering-activity.md +26 -0
  394. package/core/.claude/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  395. package/core/.claude/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +40 -0
  396. package/core/.claude/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +38 -0
  397. package/core/.claude/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  398. package/core/.claude/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  399. package/core/.claude/skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
  400. package/core/.claude/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +28 -0
  401. package/core/.claude/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md +75 -0
  402. package/core/.claude/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +39 -0
  403. package/core/.claude/skills/vercel-react-best-practices/rules/rerender-dependencies.md +45 -0
  404. package/core/.claude/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
  405. package/core/.claude/skills/vercel-react-best-practices/rules/rerender-derived-state.md +29 -0
  406. package/core/.claude/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +74 -0
  407. package/core/.claude/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  408. package/core/.claude/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
  409. package/core/.claude/skills/vercel-react-best-practices/rules/rerender-memo.md +44 -0
  410. package/core/.claude/skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
  411. package/core/.claude/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
  412. package/core/.claude/skills/vercel-react-best-practices/rules/rerender-transitions.md +40 -0
  413. package/core/.claude/skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
  414. package/core/.claude/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +73 -0
  415. package/core/.claude/skills/vercel-react-best-practices/rules/server-auth-actions.md +96 -0
  416. package/core/.claude/skills/vercel-react-best-practices/rules/server-cache-lru.md +41 -0
  417. package/core/.claude/skills/vercel-react-best-practices/rules/server-cache-react.md +76 -0
  418. package/core/.claude/skills/vercel-react-best-practices/rules/server-dedup-props.md +65 -0
  419. package/core/.claude/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +83 -0
  420. package/core/.claude/skills/vercel-react-best-practices/rules/server-serialization.md +38 -0
  421. package/core/.collaboration/README.md +258 -0
  422. package/core/.collaboration/cli/commands/assign.js +39 -0
  423. package/core/.collaboration/cli/commands/claim.js +33 -0
  424. package/core/.collaboration/cli/commands/complete.js +44 -0
  425. package/core/.collaboration/cli/commands/create.js +110 -0
  426. package/core/.collaboration/cli/commands/get.js +83 -0
  427. package/core/.collaboration/cli/commands/index.js +52 -0
  428. package/core/.collaboration/cli/commands/list.js +51 -0
  429. package/core/.collaboration/cli/commands/lock.js +45 -0
  430. package/core/.collaboration/cli/commands/rebuild.js +39 -0
  431. package/core/.collaboration/cli/commands/search.js +61 -0
  432. package/core/.collaboration/cli/commands/stats.js +61 -0
  433. package/core/.collaboration/cli/commands/transfer.js +41 -0
  434. package/core/.collaboration/cli/commands/unlock.js +48 -0
  435. package/core/.collaboration/cli/formatters/help-formatter.js +70 -0
  436. package/core/.collaboration/cli/formatters/index.js +7 -0
  437. package/core/.collaboration/cli/task-cli.js +46 -0
  438. package/core/.collaboration/cli/utils/arg-parser.js +74 -0
  439. package/core/.collaboration/cli/utils/git-user.js +25 -0
  440. package/core/.collaboration/cli/utils/index.js +9 -0
  441. package/core/.collaboration/cli/utils/output.js +10 -0
  442. package/core/.collaboration/config/default.yaml +189 -0
  443. package/core/.collaboration/core/conflict-resolver.js +461 -0
  444. package/core/.collaboration/core/conflict-resolver.test.js +389 -0
  445. package/core/.collaboration/core/id-generator.js +303 -0
  446. package/core/.collaboration/core/migrate-legacy.js +260 -0
  447. package/core/.collaboration/core/package.json +1 -0
  448. package/core/.collaboration/core/task-2257-estimated-hours.test.js +72 -0
  449. package/core/.collaboration/core/task-2260-dir-layout-move.test.js +60 -0
  450. package/core/.collaboration/core/task-2264-single-after-capture.test.js +61 -0
  451. package/core/.collaboration/core/task-2288-followups.test.js +121 -0
  452. package/core/.collaboration/core/task-api-json.js +211 -0
  453. package/core/.collaboration/core/task-api.js +3729 -0
  454. package/core/.collaboration/core/task-api.test.js +1268 -0
  455. package/core/.collaboration/docs/API.md +787 -0
  456. package/core/.collaboration/docs/ARCHITECTURE.md +596 -0
  457. package/core/.collaboration/docs/CLI.md +821 -0
  458. package/core/.collaboration/docs/FAQ.md +695 -0
  459. package/core/.collaboration/docs/MIGRATION.md +804 -0
  460. package/core/.collaboration/docs/examples/README.md +320 -0
  461. package/core/.collaboration/docs/examples/advanced-queries.js +261 -0
  462. package/core/.collaboration/docs/examples/basic-usage.js +184 -0
  463. package/core/.collaboration/docs/examples/team-workflow.js +352 -0
  464. package/core/.collaboration/hooks/README.md +70 -0
  465. package/core/.collaboration/hooks/config.json +10 -0
  466. package/core/.collaboration/hooks/install.js +400 -0
  467. package/core/.collaboration/hooks/post-merge.js +163 -0
  468. package/core/.collaboration/hooks/pre-commit.js +264 -0
  469. package/core/.collaboration/hooks/synapse-hook.js +486 -0
  470. package/core/.collaboration/hooks/synapse-hook.test.js +69 -0
  471. package/core/.failure/INDEX.yaml +231 -0
  472. package/core/.failure/agent-execution/FAIL-001-agent-no-output.yaml +391 -0
  473. package/core/.failure/agent-execution/FAIL-004_agent_platform_specific_commands.md +194 -0
  474. package/core/.failure/agent-execution/FAIL-005_background_agent_permission_denied.md +204 -0
  475. package/core/.failure/agent-execution/FAIL-007-pm-lead-wrong-team-invocation.yaml +0 -0
  476. package/core/.failure/agent-execution/FAIL-008-bypass-api-direct-yaml-write.yaml +94 -0
  477. package/core/.failure/agent-execution/FAIL-010-phase0-poem-format-skipped.yaml +28 -0
  478. package/core/.failure/agent-execution/FAIL-010-skipping-cognitive-checkpoint-after-verification.yaml +59 -0
  479. package/core/.failure/agent-execution/FAIL-012-grep-shortcut-during-investigation.yaml +85 -0
  480. package/core/.failure/agent-execution/FAIL-013-search-cwd-drift-and-case-mismatch.yaml +103 -0
  481. package/core/.failure/agent-execution/FAIL-014-shared-worktree-premature-death-verdict.yaml +35 -0
  482. package/core/.failure/agent-execution/FAIL-AUTO-TASK_1413.yaml +31 -0
  483. package/core/.failure/agent-execution/FAIL-AUTO-TASK_1427.yaml +41 -0
  484. package/core/.failure/agent-execution/FAIL-AUTO-TASK_904.yaml +30 -0
  485. package/core/.failure/agent-execution/README.md +68 -0
  486. package/core/.failure/architecture/FAIL-004_session_based_skill_recognition.md +128 -0
  487. package/core/.failure/architecture/FAIL-006-python-version-compatibility.yaml +445 -0
  488. package/core/.failure/architecture/README.md +87 -0
  489. package/core/.failure/code-quality/README.md +89 -0
  490. package/core/.failure/data-integrity/FAIL-002-json-bom.yaml +220 -0
  491. package/core/.failure/data-integrity/README.md +141 -0
  492. package/core/.failure/pipeline/FAIL-003-queue-pollution.yaml +335 -0
  493. package/core/.failure/pipeline/README.md +95 -0
  494. package/core/.failure/retired/FAIL-009-skipping-synapse-pulse-before-code-change.yaml +49 -0
  495. package/core/.failure/tools/README.md +230 -0
  496. package/core/.failure/tools/USAGE_GUIDE.md +323 -0
  497. package/core/.failure/tools/check_bom.js +101 -0
  498. package/core/.failure/tools/check_failures.ps1 +387 -0
  499. package/core/.failure/tools/fix_json.js +58 -0
  500. package/core/.failure/tools/log_failure.ps1 +474 -0
  501. package/core/.failure/tools/remove_bom.js +46 -0
  502. package/core/.failure/tools/validate_json.js +50 -0
  503. package/core/.formation/.episode-input.json +10 -0
  504. package/core/.formation/README.md +188 -0
  505. package/core/.formation/bifrost/CGDD_hook_lifecycle.js +575 -0
  506. package/core/.formation/bifrost/HOOK_PARITY_VERIFICATION.md +241 -0
  507. package/core/.formation/bifrost/README.md +71 -0
  508. package/core/.formation/bifrost/codex-doctor.js +106 -0
  509. package/core/.formation/bifrost/codex-doctor.test.js +51 -0
  510. package/core/.formation/bifrost/launch.js +510 -0
  511. package/core/.formation/bifrost/launch.test.js +217 -0
  512. package/core/.formation/bifrost/openai/codex-hook-shim.js +171 -0
  513. package/core/.formation/bifrost/openai/codex-hook-shim.test.js +107 -0
  514. package/core/.formation/bifrost/openai/models.json +36 -0
  515. package/core/.formation/bifrost/openai/relay.js +781 -0
  516. package/core/.formation/bifrost/openai/relay.test.js +71 -0
  517. package/core/.formation/bifrost/session.js +382 -0
  518. package/core/.formation/bifrost/session.test.js +121 -0
  519. package/core/.formation/bifrost/setup-codex.js +685 -0
  520. package/core/.formation/bifrost/setup-codex.test.js +102 -0
  521. package/core/.formation/bifrost/shared/ansuz-boot-policy.js +31 -0
  522. package/core/.formation/bifrost/shared/ansuz-boot-policy.test.js +40 -0
  523. package/core/.formation/bifrost/shared/boot-context.js +68 -0
  524. package/core/.formation/bifrost/shared/boot-context.test.js +67 -0
  525. package/core/.formation/bifrost/shared/codex-appserver.js +191 -0
  526. package/core/.formation/bifrost/shared/codex-injection.js +126 -0
  527. package/core/.formation/bifrost/shared/codex-session-registry.js +105 -0
  528. package/core/.formation/bifrost/shared/codex-session-registry.test.js +126 -0
  529. package/core/.formation/bifrost/shared/consolidate.js +286 -0
  530. package/core/.formation/bifrost/shared/stream-json.js +103 -0
  531. package/core/.formation/bifrost/shared/tools.js +278 -0
  532. package/core/.formation/bifrost/sync.js +142 -0
  533. package/core/.formation/briefs/scheduler-evolution.md +209 -0
  534. package/core/.formation/lead.yaml +118 -0
  535. package/core/.formation/legacy.bak/designer.yaml +57 -0
  536. package/core/.formation/legacy.bak/pm.yaml +57 -0
  537. package/core/.formation/legacy.bak/qa.yaml +57 -0
  538. package/core/.formation/legacy.bak/review.yaml +62 -0
  539. package/core/.formation/legacy.bak/scheduler.yaml +129 -0
  540. package/core/.formation/legacy.bak/sre.yaml +57 -0
  541. package/core/.formation/legion/forge.yaml +299 -0
  542. package/core/.formation/legion/hive.yaml +238 -0
  543. package/core/.formation/native/claude/README.md +61 -0
  544. package/core/.formation/native/claude/models.json +42 -0
  545. package/core/.formation/role-map.yaml +274 -0
  546. package/core/.formation/roles/_shared/modules/code_review.yaml +98 -0
  547. package/core/.formation/roles/_shared/modules/security.yaml +103 -0
  548. package/core/.formation/roles/_shared/modules/testing.yaml +14 -0
  549. package/core/.formation/roles/backend/role.yaml +93 -0
  550. package/core/.formation/roles/code_reviewer/role.yaml +102 -0
  551. package/core/.formation/roles/database_optimizer/role.yaml +107 -0
  552. package/core/.formation/roles/designer/role.yaml +66 -0
  553. package/core/.formation/roles/developer/role.yaml +75 -0
  554. package/core/.formation/roles/frontend/role.yaml +134 -0
  555. package/core/.formation/roles/incident_response/role.yaml +89 -0
  556. package/core/.formation/roles/qa/role.yaml +89 -0
  557. package/core/.formation/roles/security/role.yaml +87 -0
  558. package/core/.formation/roles/sre/role.yaml +66 -0
  559. package/core/.formation/skills/coordinator.yaml +52 -0
  560. package/core/.formation/solo/diagnosis.yaml +78 -0
  561. package/core/.formation/solo/strategy.yaml +121 -0
  562. package/core/.formation/spec/task_operations.parity.test.js +426 -0
  563. package/core/.formation/spec/task_operations.yaml +291 -0
  564. package/core/.formation/squad/blitz.yaml +192 -0
  565. package/core/.formation/squad/strategy-tribunal.yaml +354 -0
  566. package/core/.formation/squad/strategy.yaml +349 -0
  567. package/core/.formation/squad/sweep.yaml +208 -0
  568. package/core/.formation/tests/hello.txt +2 -0
  569. package/core/.formation/tools/__tests__/m1-claim-gate.test.js +175 -0
  570. package/core/.formation/tools/__tests__/m1-hmap-convid.test.js +216 -0
  571. package/core/.formation/tools/__tests__/release-lock.test.js +176 -0
  572. package/core/.formation/tools/__tests__/subagent-bifrost-guard.test.js +234 -0
  573. package/core/.formation/tools/__tests__/subagent-codex-harness.test.js +96 -0
  574. package/core/.formation/tools/__tests__/task-1863-claim-late-release.test.js +160 -0
  575. package/core/.formation/tools/__tests__/task-2265-singleton-identity.test.js +134 -0
  576. package/core/.formation/tools/__tests__/task-2281-singleton-readers.test.js +64 -0
  577. package/core/.formation/tools/__tests__/task2030-worktree-node-modules.test.js +221 -0
  578. package/core/.formation/tools/__tests__/task2067-worktree-branch-reuse.test.js +148 -0
  579. package/core/.formation/tools/alaya-gate.js +198 -0
  580. package/core/.formation/tools/analytics.js +172 -0
  581. package/core/.formation/tools/broadcast.js +103 -0
  582. package/core/.formation/tools/commit-sync.js +154 -0
  583. package/core/.formation/tools/coordinator.js +350 -0
  584. package/core/.formation/tools/dashboard-models-chain.test.js +60 -0
  585. package/core/.formation/tools/dispatch-cortex-context.test.js +52 -0
  586. package/core/.formation/tools/dispatch-detail/cross-project-worktree.md +40 -0
  587. package/core/.formation/tools/dispatch-detail/testing-module.md +53 -0
  588. package/core/.formation/tools/dispatch-detail/worktree-subagent-mode.md +72 -0
  589. package/core/.formation/tools/dispatch-dryrun.test.js +54 -0
  590. package/core/.formation/tools/dispatch-model-policy.test.js +165 -0
  591. package/core/.formation/tools/dispatch-notifier.js +84 -0
  592. package/core/.formation/tools/dispatch-registry.js +346 -0
  593. package/core/.formation/tools/dispatch.js +1931 -0
  594. package/core/.formation/tools/formations.js +1203 -0
  595. package/core/.formation/tools/forseti-verify.js +1170 -0
  596. package/core/.formation/tools/git-salvage.js +269 -0
  597. package/core/.formation/tools/guard-attribution.js +224 -0
  598. package/core/.formation/tools/headless-branch-recovery.test.js +64 -0
  599. package/core/.formation/tools/headless-dryrun.test.js +79 -0
  600. package/core/.formation/tools/headless-v2.js +659 -0
  601. package/core/.formation/tools/headless.js +1071 -0
  602. package/core/.formation/tools/integration.js +528 -0
  603. package/core/.formation/tools/jev-correction.js +214 -0
  604. package/core/.formation/tools/jev-correction.test.js +178 -0
  605. package/core/.formation/tools/legacy-scheduler.js +1994 -0
  606. package/core/.formation/tools/lib/exec-tree.js +92 -0
  607. package/core/.formation/tools/lib/exec-tree.test.js +82 -0
  608. package/core/.formation/tools/loader.js +190 -0
  609. package/core/.formation/tools/log-reader.js +232 -0
  610. package/core/.formation/tools/logger.js +273 -0
  611. package/core/.formation/tools/mcp-allowlist.test.js +40 -0
  612. package/core/.formation/tools/memory-loader.js +422 -0
  613. package/core/.formation/tools/merge-lock-heartbeat.test.js +35 -0
  614. package/core/.formation/tools/no-hooks.settings.json +3 -0
  615. package/core/.formation/tools/pool-status-push.js +121 -0
  616. package/core/.formation/tools/pool-status-push.test.js +165 -0
  617. package/core/.formation/tools/post-complete/bounded-http.js +102 -0
  618. package/core/.formation/tools/post-complete/bounded-http.test.js +130 -0
  619. package/core/.formation/tools/post-complete/cognitive.js +270 -0
  620. package/core/.formation/tools/post-complete/git-merge.js +2845 -0
  621. package/core/.formation/tools/post-complete/health.js +464 -0
  622. package/core/.formation/tools/post-complete/integration-gaps.js +98 -0
  623. package/core/.formation/tools/post-complete/outcome.js +874 -0
  624. package/core/.formation/tools/post-complete/staging.js +390 -0
  625. package/core/.formation/tools/post-complete/subagent-transcript-stats.js +460 -0
  626. package/core/.formation/tools/post-complete/subagent-transcript-stats.test.js +680 -0
  627. package/core/.formation/tools/post-complete/task1536.test.js +627 -0
  628. package/core/.formation/tools/post-complete/task1543.test.js +261 -0
  629. package/core/.formation/tools/post-complete/task1876.test.js +287 -0
  630. package/core/.formation/tools/post-complete/task1957.test.js +293 -0
  631. package/core/.formation/tools/post-complete/task1997.test.js +401 -0
  632. package/core/.formation/tools/post-complete/task2028.test.js +232 -0
  633. package/core/.formation/tools/post-complete/task2029.test.js +275 -0
  634. package/core/.formation/tools/post-complete/task2036.test.js +330 -0
  635. package/core/.formation/tools/post-complete/task2038.test.js +246 -0
  636. package/core/.formation/tools/post-complete/task2071.test.js +231 -0
  637. package/core/.formation/tools/post-complete/task2233.test.js +100 -0
  638. package/core/.formation/tools/post-complete/task2240.test.js +134 -0
  639. package/core/.formation/tools/post-complete/task2244.test.js +199 -0
  640. package/core/.formation/tools/post-complete/task2255.test.js +28 -0
  641. package/core/.formation/tools/post-complete/task2268.test.js +106 -0
  642. package/core/.formation/tools/post-complete/task2341.test.js +74 -0
  643. package/core/.formation/tools/post-complete/task2345.test.js +38 -0
  644. package/core/.formation/tools/post-complete/testing.js +482 -0
  645. package/core/.formation/tools/post-complete/wish.js +177 -0
  646. package/core/.formation/tools/post-complete/worktree-rescue.test.js +283 -0
  647. package/core/.formation/tools/post-complete.js +3660 -0
  648. package/core/.formation/tools/post-complete.test.js +1002 -0
  649. package/core/.formation/tools/pre-dispatch-snapshot.test.js +328 -0
  650. package/core/.formation/tools/process-state.js +33 -0
  651. package/core/.formation/tools/prompt.js +2183 -0
  652. package/core/.formation/tools/prompt.test.js +875 -0
  653. package/core/.formation/tools/remote-conflict.js +98 -0
  654. package/core/.formation/tools/revert-daemon-state.js +162 -0
  655. package/core/.formation/tools/route-audit.test.js +55 -0
  656. package/core/.formation/tools/runner.js +1332 -0
  657. package/core/.formation/tools/supabase-client.js +104 -0
  658. package/core/.formation/tools/task-sync.js +236 -0
  659. package/core/.formation/tools/task-utils.js +344 -0
  660. package/core/.formation/tools/task2028-headless-worktree.test.js +112 -0
  661. package/core/.formation/tools/test-drift.js +148 -0
  662. package/core/.formation/tools/tests/headless-mcp-args-plumbing.test.js +123 -0
  663. package/core/.formation/tools/tests/relay-mcp-overrides.test.js +112 -0
  664. package/core/.formation/tools/transcript-recorder.js +574 -0
  665. package/core/.formation/tools/utils-claude-cmd.test.js +28 -0
  666. package/core/.formation/tools/utils-worktree-config.test.js +44 -0
  667. package/core/.formation/tools/utils.js +1020 -0
  668. package/core/.formation/tools/verify-acceptance.js +585 -0
  669. package/core/.formation/tools/worktree-leak.test.js +162 -0
  670. package/core/.formation/tools/worktree-reclaim.js +259 -0
  671. package/core/.formation/tools/worktree-reclaim.test.js +182 -0
  672. package/core/.formation/tools/yggdrasil-local.js +97 -0
  673. package/core/.formation/unit/do.yaml +78 -0
  674. package/core/.formation/unit/heimdall.yaml +96 -0
  675. package/core/.formation/unit/plan.yaml +67 -0
  676. package/core/.formation/unit/think.yaml +58 -0
  677. package/core/.kenaz/MUNINN_SNAPSHOT9_EPISODE.json +32 -0
  678. package/core/.kenaz/MUNINN_SNAPSHOT9_RUNE.json +23 -0
  679. package/core/.kenaz/MUNINN_SNAPSHOT9_SUMMARY.md +89 -0
  680. package/core/.kenaz/ash_TASK_1428-20260507.json +14 -0
  681. package/core/.kenaz/cache/native-models/claude.json +42 -0
  682. package/core/.kenaz/claude-hooks-manifest.json +119 -0
  683. package/core/.kenaz/cortex.yaml +100 -0
  684. package/core/.kenaz/curator_state.json +7 -0
  685. package/core/.kenaz/dashboard-quick-prompts.json +9 -0
  686. package/core/.kenaz/designs/METAPLASTICITY_CONFIDENCE_DESIGN.md +537 -0
  687. package/core/.kenaz/designs/REFLEX_INITIATOR_DESIGN.md +501 -0
  688. package/core/.kenaz/designs/TASK_1385_handoff_mcp_design.md +426 -0
  689. package/core/.kenaz/designs/TASK_932_hippocampus_consolidation.md +103 -0
  690. package/core/.kenaz/designs/TASK_934_efe_signal_engine.md +97 -0
  691. package/core/.kenaz/designs/TASK_935_self_evolution_framework.md +154 -0
  692. package/core/.kenaz/designs/VISION_cognitive_architecture_roadmap.md +159 -0
  693. package/core/.kenaz/designs/metaplasticity_simulation_results.json +696 -0
  694. package/core/.kenaz/docs/INDEX.md +214 -0
  695. package/core/.kenaz/docs/README.md +290 -0
  696. package/core/.kenaz/docs/registry.json +962 -0
  697. package/core/.kenaz/docs/schema.json +144 -0
  698. package/core/.kenaz/docs/tools/GIT_HOOK_GUIDE.md +203 -0
  699. package/core/.kenaz/docs/tools/RAG_INTEGRATION_GUIDE.md +306 -0
  700. package/core/.kenaz/docs/tools/README.md +99 -0
  701. package/core/.kenaz/docs/tools/TIME_ESTIMATION_GUIDE.md +299 -0
  702. package/core/.kenaz/docs/tools/package-lock.json +618 -0
  703. package/core/.kenaz/docs/tools/package.json +34 -0
  704. package/core/.kenaz/docs/tools/src/cli.ts +365 -0
  705. package/core/.kenaz/docs/tools/src/field-extractor.ts +152 -0
  706. package/core/.kenaz/docs/tools/src/index.ts +14 -0
  707. package/core/.kenaz/docs/tools/src/registry.ts +664 -0
  708. package/core/.kenaz/docs/tools/src/search.ts +195 -0
  709. package/core/.kenaz/docs/tools/src/types.ts +88 -0
  710. package/core/.kenaz/docs/tools/test-git-hook.sh +79 -0
  711. package/core/.kenaz/docs/tools/tsconfig.json +20 -0
  712. package/core/.kenaz/docs/tools/verify.sh +106 -0
  713. package/core/.kenaz/episodes/SESSION_ansuz-prompt-1785087304784.yaml +68 -0
  714. package/core/.kenaz/huginn-exploration.json +8 -0
  715. package/core/.kenaz/knowledge/ladybug_2c51da1e_shadow_file_frame_group.patch +163 -0
  716. package/core/.kenaz/knowledge/ladybug_30cf85690e_shadow_page_read_during_checkpoint.patch +393 -0
  717. package/core/.kenaz/knowledge/ladybug_7a17858d3a_node_group_delete_lock.patch +102 -0
  718. package/core/.kenaz/knowledge/ladybug_926a0ba1_column_checkpoint.patch +412 -0
  719. package/core/.kenaz/knowledge/ladybug_a346c4c4b6_pk_index_header_pages.patch +144 -0
  720. package/core/.kenaz/knowledge/ladybug_ba5f38815b_csr_node_group.patch +86 -0
  721. package/core/.kenaz/main-memory/README.md +230 -0
  722. package/core/.kenaz/main-memory/kenaz/cortex/001_cortex_overview.md +168 -0
  723. package/core/.kenaz/main-memory/kenaz/cortex/001_rag_engine_overview.md +30 -0
  724. package/core/.kenaz/main-memory/kenaz/memory-system/001_three_tier_architecture.md +361 -0
  725. package/core/.kenaz/main-memory/kenaz/pipeline/001_task_execution_flow.md +117 -0
  726. package/core/.kenaz/main-memory/kenaz/pipeline/001_task_granularity.md +154 -0
  727. package/core/.kenaz/main-memory/kenaz/pipeline/002_team_priority.md +51 -0
  728. package/core/.kenaz/main-memory/kenaz/pipeline/003_feature_id_system.md +46 -0
  729. package/core/.kenaz/main-memory/kenaz/rules/001_gen_007_self_containment.md +108 -0
  730. package/core/.kenaz/main-memory/kenaz/rules/001_rule_priority_system.md +121 -0
  731. package/core/.kenaz/main-memory/kenaz/rules/002_agt_006_pre_check.md +0 -0
  732. package/core/.kenaz/main-memory/kenaz/rules/003_ppl_002_task_archival.md +48 -0
  733. package/core/.kenaz/main-memory/kenaz/system/001_dual_track_task_system.md +197 -0
  734. package/core/.kenaz/main-memory/knowledge/patterns/001_json_bom_issue.md +78 -0
  735. package/core/.kenaz/main-memory/knowledge/patterns/001_leader_worker_pattern.md +0 -0
  736. package/core/.kenaz/main-memory/knowledge/patterns/002_scope_path_conflict.md +115 -0
  737. package/core/.kenaz/main-memory/knowledge/patterns/002_task_dependency_resolution.md +223 -0
  738. package/core/.kenaz/main-memory/knowledge/patterns/003_question_protocol.md +242 -0
  739. package/core/.kenaz/main-memory/knowledge/patterns/004_user_insight_value.md +111 -0
  740. package/core/.kenaz/main-memory/knowledge/patterns/005_file_lock_pattern.md +274 -0
  741. package/core/.kenaz/main-memory/knowledge/references/001_ppl_rules.md +28 -0
  742. package/core/.kenaz/main-memory/knowledge/solutions/001_json_bom_issue.md +137 -0
  743. package/core/.kenaz/main-memory/knowledge/solutions/001_team_invocation.md +0 -0
  744. package/core/.kenaz/main-memory/knowledge/solutions/002_passive_monitoring.md +0 -0
  745. package/core/.kenaz/main-memory/knowledge/solutions/003_windows_file_race_condition.md +239 -0
  746. package/core/.kenaz/main-memory/registry.json +326 -0
  747. package/core/.kenaz/main-memory/version.yaml +58 -0
  748. package/core/.kenaz/muninn_episode_write.ps1 +17 -0
  749. package/core/.kenaz/muninn_snapshot11_rune_candidates.md +63 -0
  750. package/core/.kenaz/muninn_snapshot1_rune_candidates.md +49 -0
  751. package/core/.kenaz/orphan_audit_2026-05.md +181 -0
  752. package/core/.kenaz/ownership.yaml +155 -0
  753. package/core/.kenaz/peer.yaml +72 -0
  754. package/core/.kenaz/project.yaml +62 -0
  755. package/core/.kenaz/rune_ansuz_literature_validation_strategy.md +40 -0
  756. package/core/.kenaz/rune_efe_active_inference_validation.md +36 -0
  757. package/core/.kenaz/rune_yggdrasil_filesystem_scoped_project.md +41 -0
  758. package/core/.kenaz/rune_yggdrasil_project_identity_folder_name.md +41 -0
  759. package/core/.kenaz/rune_yggdrasil_relay_protocol_project_mismatch.md +39 -0
  760. package/core/.kenaz/runes_TASK_1428.json +57 -0
  761. package/core/.kenaz/specialist/ansuz_motivational_state.schema.json +138 -0
  762. package/core/.kenaz/specialist/ansuz_rules.yaml +241 -0
  763. package/core/.kenaz/specialist/ansuz_session_handoff.schema.json +128 -0
  764. package/core/.kenaz/specialist/chart_TASK_1657.json +50 -0
  765. package/core/.kenaz/specialist/cognitive-hub-e2e.test.js +494 -0
  766. package/core/.kenaz/specialist/daemon-manifest.yaml +168 -0
  767. package/core/.kenaz/specialist/empty_ac_audit_report.md +63 -0
  768. package/core/.kenaz/specialist/episode_muninn_completion_1785056865691.json +91 -0
  769. package/core/.kenaz/specialist/field_report_watermark.json +1 -0
  770. package/core/.kenaz/specialist/gc1826_driver.js +118 -0
  771. package/core/.kenaz/specialist/heimdall_proposal_1017c07f.json +13 -0
  772. package/core/.kenaz/specialist/heimdall_proposal_3dfaa8b9.json +12 -0
  773. package/core/.kenaz/specialist/heimdall_proposal_57af18f9.json +15 -0
  774. package/core/.kenaz/specialist/heimdall_proposal_57b1aa1b.json +14 -0
  775. package/core/.kenaz/specialist/heimdall_proposal_5a3c9473.json +13 -0
  776. package/core/.kenaz/specialist/identity_verdicts/TASK_1073.json +75 -0
  777. package/core/.kenaz/specialist/identity_verdicts/TASK_TEST.json +77 -0
  778. package/core/.kenaz/specialist/memory_guard_fired.json +1 -0
  779. package/core/.kenaz/specialist/memory_guard_trigger_cache.json +1 -0
  780. package/core/.kenaz/specialist/memory_source_priority.yaml +260 -0
  781. package/core/.kenaz/specialist/motivational_state.schema.json +62 -0
  782. package/core/.kenaz/specialist/prompt_1775.txt +317 -0
  783. package/core/.kenaz/specialist/prompt_1776.txt +326 -0
  784. package/core/.kenaz/specialist/prompt_1791.txt +320 -0
  785. package/core/.kenaz/specialist/prompt_1792.txt +320 -0
  786. package/core/.kenaz/specialist/prompt_1795.txt +281 -0
  787. package/core/.kenaz/specialist/prompt_1813.txt +332 -0
  788. package/core/.kenaz/specialist/prompt_1814.txt +401 -0
  789. package/core/.kenaz/specialist/prompt_1815.txt +394 -0
  790. package/core/.kenaz/specialist/prompt_1816.txt +437 -0
  791. package/core/.kenaz/specialist/prompt_1818.txt +361 -0
  792. package/core/.kenaz/specialist/prompt_1819.txt +421 -0
  793. package/core/.kenaz/specialist/prompt_1821.txt +345 -0
  794. package/core/.kenaz/specialist/prompt_1822.txt +313 -0
  795. package/core/.kenaz/specialist/prompt_1824.txt +348 -0
  796. package/core/.kenaz/specialist/prompt_1826.txt +388 -0
  797. package/core/.kenaz/specialist/retired_organs/README.md +58 -0
  798. package/core/.kenaz/specialist/rune_calibration_poc.md +175 -0
  799. package/core/.kenaz/specialist/rune_efe_salience_gap.md +21 -0
  800. package/core/.kenaz/specialist/rune_ember_autonomous_dispatch_gate.md +24 -0
  801. package/core/.kenaz/specialist/rune_post_dispatch_verification_pattern.md +31 -0
  802. package/core/.kenaz/specialist/rune_surprise_proxy_improvement.md +28 -0
  803. package/core/.kenaz/specialist/rune_worktree_dispatch_pattern.md +31 -0
  804. package/core/.kenaz/specialist/rune_yaml_filter_desync_fix.md +26 -0
  805. package/core/.kenaz/specialist/rune_yggdrasil_project_identity_folder_name.md +24 -0
  806. package/core/.kenaz/specialist/sessions/chart_TASK_1599.json +41 -0
  807. package/core/.kenaz/specialist/sessions/hmap_028aa781-aad2-48c0-9a61-5540565d4a7f.json +5 -0
  808. package/core/.kenaz/specialist/sessions/hmap_20210387-0c64-400c-9d0a-53042a0cbd89.json +5 -0
  809. package/core/.kenaz/specialist/sessions/hmap_c1375c5d-fd9f-44bd-a83e-353ecbb0392f.json +5 -0
  810. package/core/.kenaz/specialist/sessions/scratch_028aa781-aad2-48c0-9a61-5540565d4a7f.json +6 -0
  811. package/core/.kenaz/specialist/sessions/scratch_0acc0fb3-24f9-453f-9e92-6ef1cdf03a7c.json +6 -0
  812. package/core/.kenaz/specialist/sessions/scratch_20210387-0c64-400c-9d0a-53042a0cbd89.json +6 -0
  813. package/core/.kenaz/specialist/sessions/scratch_2f10623e-b7a1-4647-905e-9dc7c4d99f9c.json +6 -0
  814. package/core/.kenaz/specialist/sessions/scratch_5a38b62d-608a-488c-82f0-7e47e95e0905.json +6 -0
  815. package/core/.kenaz/specialist/sessions/scratch_5d9758ef-d9b6-4ffe-a017-3ed26d0a313b.json +6 -0
  816. package/core/.kenaz/specialist/sessions/scratch_c1375c5d-fd9f-44bd-a83e-353ecbb0392f.json +6 -0
  817. package/core/.kenaz/specialist/sessions/scratch_c9f3c711-b73d-4fcd-ad2a-7b2bc024ee77.json +6 -0
  818. package/core/.kenaz/specialist/sessions/scratch_e72e5274-1c81-4655-a05a-f87d1ecb2917.json +6 -0
  819. package/core/.kenaz/specialist/sessions/scratch_f740cdbe-f756-41fc-98fb-2b1413d51901.json +6 -0
  820. package/core/.kenaz/specialist/t1777_probe.txt +1 -0
  821. package/core/.kenaz/specialist/task1825_update.json +43 -0
  822. package/core/.kenaz/specialist/task1827_update.json +43 -0
  823. package/core/.kenaz/specialist/task1828_update.json +43 -0
  824. package/core/.kenaz/specialist/taskgen/consolidation_i.json +38 -0
  825. package/core/.kenaz/specialist/taskgen/csharp_a.json +44 -0
  826. package/core/.kenaz/specialist/taskgen/csharp_b.json +40 -0
  827. package/core/.kenaz/specialist/taskgen/embedding_e.json +34 -0
  828. package/core/.kenaz/specialist/taskgen/hygiene_fg.json +39 -0
  829. package/core/.kenaz/specialist/taskgen/pathology_h.json +36 -0
  830. package/core/.kenaz/specialist/taskgen/unity_noise_d.json +38 -0
  831. package/core/.kenaz/specialist/taskgen/visibility_c.json +38 -0
  832. package/core/.kenaz/specialist/verify_1837.js +302 -0
  833. package/core/.kenaz/specialist/verify_1838.js +124 -0
  834. package/core/.kenaz/tmp/heimdall_proposal_fc7e0944.json +10 -0
  835. package/core/.kenaz/tmp_heimdall_proposal_8d3e392.json +13 -0
  836. package/core/.kenaz/tmp_props.json +1 -0
  837. package/core/.kenaz/tmp_sounddrop_t1_prompt.txt +371 -0
  838. package/core/.kenaz/user_model.schema.json +107 -0
  839. package/core/.matrix/README.md +257 -0
  840. package/core/.matrix/index.matrix +5 -0
  841. package/core/.mcp.json +8 -0
  842. package/core/.prefrontal/.gitkeep +0 -0
  843. package/core/.prefrontal/proposals/.gitkeep +0 -0
  844. package/core/.rule/INDEX.yaml +99 -0
  845. package/core/.rule/MECHANIZED.md +61 -0
  846. package/core/.rule/code/README.md +211 -0
  847. package/core/.rule/code/backend.yaml +294 -0
  848. package/core/.rule/code/checklist.yaml +258 -0
  849. package/core/.rule/code/maintainability.yaml +227 -0
  850. package/core/.rule/code/naming.yaml +106 -0
  851. package/core/.rule/code/principles.yaml +71 -0
  852. package/core/.rule/code/reusability.yaml +192 -0
  853. package/core/.rule/code/structure.yaml +218 -0
  854. package/core/.rule/code/style.yaml +197 -0
  855. package/core/.rule/design/ui.yaml +79 -0
  856. package/core/.rule/general/agent-workflow.yaml +572 -0
  857. package/core/.rule/general/cortex-memory-recall.yaml +446 -0
  858. package/core/.rule/general/cortex-tools.yaml +181 -0
  859. package/core/.rule/general/cross-platform.yaml +107 -0
  860. package/core/.rule/general/ddx-synapse-stack.yaml +162 -0
  861. package/core/.rule/general/file-size-threshold.yaml +45 -0
  862. package/core/.rule/general/identity-contract.schema.yaml +251 -0
  863. package/core/.rule/general/memory-language.yaml +67 -0
  864. package/core/.rule/general/memory-source-priority.yaml +207 -0
  865. package/core/.rule/general/pipeline.yaml +246 -0
  866. package/core/.rule/general/principles.yaml +77 -0
  867. package/core/.rule/general/project-self-containment.yaml +253 -0
  868. package/core/.rule/general/rust-verify-target.yaml +80 -0
  869. package/core/.rule/general/specialist-identity-contract.yaml +153 -0
  870. package/core/.rule/general/sunny-access-control.yaml +60 -0
  871. package/core/.rule/general/synapse-code-intelligence.yaml +375 -0
  872. package/core/.rule/general/synapse-cognitive-fusion.yaml +301 -0
  873. package/core/.rule/general/system-invariants.yaml +248 -0
  874. package/core/.rule/general/task-pool-routing.yaml +102 -0
  875. package/core/.rule/general/worktree-isolation.yaml +79 -0
  876. package/core/.rule/pipeline/PPL-002-completed-task-archival.yaml +528 -0
  877. package/core/.rule/pipeline/auto-update.yaml +282 -0
  878. package/core/.rule/pipeline/task-execution.yaml +368 -0
  879. package/core/.rule/tools/check-permissions.js +197 -0
  880. package/core/.specialist/Amelia/README.md +329 -0
  881. package/core/.specialist/Amelia/capability.yaml +386 -0
  882. package/core/.specialist/Amelia/knowledge.yaml +217 -0
  883. package/core/.specialist/Amelia/principles.yaml +10 -0
  884. package/core/.specialist/Amelia/rule.yaml +79 -0
  885. package/core/.specialist/Amelia/workflow.yaml +241 -0
  886. package/core/.specialist/Ansuz/HEURISTIC_BOOT_ROUTING.md +39 -0
  887. package/core/.specialist/Ansuz/ROUTING.md +35 -0
  888. package/core/.specialist/Ansuz/RULES.md +79 -0
  889. package/core/.specialist/Ansuz/SYSTEM_DOC.md +611 -0
  890. package/core/.specialist/Ansuz/VERIFY.md +38 -0
  891. package/core/.specialist/Ansuz/capability.yaml +338 -0
  892. package/core/.specialist/Ansuz/cognitive_principles.yaml +62 -0
  893. package/core/.specialist/Ansuz/concepts/agent_types.yaml +22 -0
  894. package/core/.specialist/Ansuz/concepts/autonomous_agenda.yaml +170 -0
  895. package/core/.specialist/Ansuz/concepts/autonomy_contract.yaml +126 -0
  896. package/core/.specialist/Ansuz/concepts/boot_ritual.yaml +107 -0
  897. package/core/.specialist/Ansuz/concepts/boot_rules_summary.yaml +16 -0
  898. package/core/.specialist/Ansuz/concepts/capability_pointers.yaml +21 -0
  899. package/core/.specialist/Ansuz/concepts/cognitive_fluency_contract.yaml +264 -0
  900. package/core/.specialist/Ansuz/concepts/cognitive_systems_competence_map.yaml +14 -0
  901. package/core/.specialist/Ansuz/concepts/cognitive_systems_hippocampus.yaml +14 -0
  902. package/core/.specialist/Ansuz/concepts/cognitive_systems_overview.yaml +27 -0
  903. package/core/.specialist/Ansuz/concepts/cognitive_systems_serendipity.yaml +14 -0
  904. package/core/.specialist/Ansuz/concepts/cognitive_systems_turn_context.yaml +13 -0
  905. package/core/.specialist/Ansuz/concepts/commitment_layer.yaml +150 -0
  906. package/core/.specialist/Ansuz/concepts/completion_tracking.yaml +29 -0
  907. package/core/.specialist/Ansuz/concepts/deep_knowledge_pointers.yaml +28 -0
  908. package/core/.specialist/Ansuz/concepts/evolvable_guardrails.yaml +20 -0
  909. package/core/.specialist/Ansuz/concepts/fatigue_handoff.yaml +84 -0
  910. package/core/.specialist/Ansuz/concepts/formation_quick_ref.yaml +28 -0
  911. package/core/.specialist/Ansuz/concepts/guardrails_immutable.yaml +31 -0
  912. package/core/.specialist/Ansuz/concepts/identity.yaml +48 -0
  913. package/core/.specialist/Ansuz/concepts/interaction_protocol.yaml +42 -0
  914. package/core/.specialist/Ansuz/concepts/meta_evolvable_tier.yaml +28 -0
  915. package/core/.specialist/Ansuz/concepts/mindset.yaml +18 -0
  916. package/core/.specialist/Ansuz/concepts/phase9_verification.yaml +21 -0
  917. package/core/.specialist/Ansuz/concepts/phase_protocol.yaml +66 -0
  918. package/core/.specialist/Ansuz/concepts/principles.yaml +65 -0
  919. package/core/.specialist/Ansuz/concepts/self_evolution_overview.yaml +53 -0
  920. package/core/.specialist/Ansuz/concepts/task_first_protocol.yaml +7 -0
  921. package/core/.specialist/Ansuz/concepts/task_pool.yaml +119 -0
  922. package/core/.specialist/Ansuz/concepts/task_system.yaml +22 -0
  923. package/core/.specialist/Ansuz/concepts/write_verification.yaml +26 -0
  924. package/core/.specialist/Ansuz/core.yaml +224 -0
  925. package/core/.specialist/Ansuz/decisions/ADR-requirement-graph-layer.md +390 -0
  926. package/core/.specialist/Ansuz/elixir.yaml +70 -0
  927. package/core/.specialist/Ansuz/exo_cortex_tools.yaml +13 -0
  928. package/core/.specialist/Ansuz/experiments/boot_ablation_replay.js +197 -0
  929. package/core/.specialist/Ansuz/guards/blind_spot_guards.yaml +28 -0
  930. package/core/.specialist/Ansuz/guards/lesson_guards.yaml +203 -0
  931. package/core/.specialist/Ansuz/identity_contract.yaml +375 -0
  932. package/core/.specialist/Ansuz/knowledge.yaml +284 -0
  933. package/core/.specialist/Ansuz/modules/amelia_review.yaml +112 -0
  934. package/core/.specialist/Ansuz/modules/ddx.yaml +47 -0
  935. package/core/.specialist/Ansuz/modules/design_checks.yaml +47 -0
  936. package/core/.specialist/Ansuz/modules/identity_verification.yaml +119 -0
  937. package/core/.specialist/Ansuz/modules/loop_guard.yaml +36 -0
  938. package/core/.specialist/Ansuz/modules/prevention.yaml +84 -0
  939. package/core/.specialist/Ansuz/modules/prophecy.yaml +95 -0
  940. package/core/.specialist/Ansuz/modules/pulse_empty.yaml +36 -0
  941. package/core/.specialist/Ansuz/modules/qa_intake.yaml +29 -0
  942. package/core/.specialist/Ansuz/modules/recall.yaml +45 -0
  943. package/core/.specialist/Ansuz/principles.yaml +31 -0
  944. package/core/.specialist/Ansuz/research/EMBER_architecture_comparison.md +142 -0
  945. package/core/.specialist/Ansuz/rule.yaml +97 -0
  946. package/core/.specialist/Ansuz/self_model_seed.backup.json +100 -0
  947. package/core/.specialist/Ansuz/self_model_seed.json +100 -0
  948. package/core/.specialist/Ansuz/self_model_seed.sha256 +1 -0
  949. package/core/.specialist/Ansuz/tools/ansuz-handoff-snapshot.js +626 -0
  950. package/core/.specialist/Ansuz/tools/ansuz-handoff.js +437 -0
  951. package/core/.specialist/Ansuz/tools/ansuz-sdk-runner.js +1254 -0
  952. package/core/.specialist/Ansuz/tools/ansuz-sdk-runner.test.js +137 -0
  953. package/core/.specialist/Ansuz/tools/ansuz-state.js +288 -0
  954. package/core/.specialist/Ansuz/tools/bootstrap-anchors.js +289 -0
  955. package/core/.specialist/Ansuz/tools/handoff-freshness-milestone.test.js +73 -0
  956. package/core/.specialist/Ansuz/tools/handoff-resolver.js +207 -0
  957. package/core/.specialist/Ansuz/tools/handoff-session-identity.test.js +333 -0
  958. package/core/.specialist/Ansuz/tools/handoff-snapshot-args.test.js +25 -0
  959. package/core/.specialist/Ansuz/tools/install-claude-hooks.js +354 -0
  960. package/core/.specialist/Ansuz/tools/install-claude-hooks.test.js +110 -0
  961. package/core/.specialist/Ansuz/tools/package.json +16 -0
  962. package/core/.specialist/Ansuz/tools/preservation-coordinator.js +504 -0
  963. package/core/.specialist/Ansuz/tools/verify-and-land.js +1012 -0
  964. package/core/.specialist/Ansuz/tools/verify-and-land.test.js +1099 -0
  965. package/core/.specialist/Ansuz/workflow.yaml +1273 -0
  966. package/core/.specialist/Forseti/capability.yaml +210 -0
  967. package/core/.specialist/Forseti/core.yaml +176 -0
  968. package/core/.specialist/Forseti/principles.yaml +88 -0
  969. package/core/.specialist/Forseti/rule.yaml +86 -0
  970. package/core/.specialist/Heimdall/SKILL.md +65 -0
  971. package/core/.specialist/Heimdall/capability.yaml +134 -0
  972. package/core/.specialist/Heimdall/core.yaml +275 -0
  973. package/core/.specialist/Heimdall/principles.yaml +66 -0
  974. package/core/.specialist/Heimdall/rule.yaml +68 -0
  975. package/core/.specialist/Huginn/capability.yaml +234 -0
  976. package/core/.specialist/Huginn/core.yaml +482 -0
  977. package/core/.specialist/Huginn/principles.yaml +57 -0
  978. package/core/.specialist/Huginn/rule.yaml +121 -0
  979. package/core/.specialist/REFLECTION_TO_CONTROL.md +347 -0
  980. package/core/.specialist/ansuz_session_handoff.json +96 -0
  981. package/core/.specialist/experiments/rg_benchmark.js +523 -0
  982. package/core/.specialist/experiments/rg_benchmark_results.json +27 -0
  983. package/core/.specialist/shared/cognitive-primer.md +15 -0
  984. package/core/.specialist/shared/guard_schema.json +290 -0
  985. package/core/.specialist/shared/principles.yaml +213 -0
  986. package/core/.specialist/tests/runtime-discovery/README.md +224 -0
  987. package/core/.specialist/tests/runtime-discovery/active-project-polling.test.js +495 -0
  988. package/core/.specialist/tests/runtime-discovery/port-binding.test.js +418 -0
  989. package/core/.specialist/tests/runtime-discovery/resolver-priority.test.js +693 -0
  990. package/core/.specialist/tests/runtime-discovery/resolver-skip-on-invalid.test.js +467 -0
  991. package/core/.specialist/tests/runtime-discovery/resolver-symmetry.test.js +679 -0
  992. package/core/.specialist/tests/runtime-discovery/tail-cli-project-path.test.js +231 -0
  993. package/core/.specialist/tools/MEMORY_RECALL_TRIGGERS.md +156 -0
  994. package/core/.specialist/tools/README.md +129 -0
  995. package/core/.specialist/tools/__tests__/freya-cli-contract.test.js +156 -0
  996. package/core/.specialist/tools/__tests__/task-1863-boot-lease-reuse.test.js +99 -0
  997. package/core/.specialist/tools/__tests__/task-1917-orphan-detection.test.js +175 -0
  998. package/core/.specialist/tools/__tests__/task-1977-banner-cap.test.js +129 -0
  999. package/core/.specialist/tools/__tests__/task-1983-lease-project-path.test.js +96 -0
  1000. package/core/.specialist/tools/__tests__/task-2218-boot-session-id.test.js +118 -0
  1001. package/core/.specialist/tools/__tests__/task-2222-session-identity-interleave.test.js +203 -0
  1002. package/core/.specialist/tools/__tests__/task-2246-reap-honesty.test.js +96 -0
  1003. package/core/.specialist/tools/__tests__/task-2254-handoff-archive-contract.test.js +60 -0
  1004. package/core/.specialist/tools/__tests__/task-2272-open-card-status-quote.test.js +26 -0
  1005. package/core/.specialist/tools/__tests__/task-2374-usage-counter.test.js +34 -0
  1006. package/core/.specialist/tools/ansuz-boot-fast.js +1120 -0
  1007. package/core/.specialist/tools/ansuz-boot-fast.test.js +705 -0
  1008. package/core/.specialist/tools/canary.js +501 -0
  1009. package/core/.specialist/tools/context-injection.js +395 -0
  1010. package/core/.specialist/tools/design-reasoning.js +493 -0
  1011. package/core/.specialist/tools/discovery-fixtures.js +308 -0
  1012. package/core/.specialist/tools/discovery-runner.js +460 -0
  1013. package/core/.specialist/tools/failure-detector.js +1132 -0
  1014. package/core/.specialist/tools/identity-scorer.js +714 -0
  1015. package/core/.specialist/tools/jev-optional-context.js +107 -0
  1016. package/core/.specialist/tools/jev-optional-context.test.js +152 -0
  1017. package/core/.specialist/tools/lesson-guard.js +1084 -0
  1018. package/core/.specialist/tools/lib/chart-path.js +159 -0
  1019. package/core/.specialist/tools/lib/chart-path.test.js +171 -0
  1020. package/core/.specialist/tools/lib/project-resolver.js +200 -0
  1021. package/core/.specialist/tools/lib/project-resolver.test.js +241 -0
  1022. package/core/.specialist/tools/memory-action-log.js +839 -0
  1023. package/core/.specialist/tools/phase-gate.js +3754 -0
  1024. package/core/.specialist/tools/phase-gate.test.js +85 -0
  1025. package/core/.specialist/tools/phase9-policy.test.js +109 -0
  1026. package/core/.specialist/tools/precompute-runner.js +444 -0
  1027. package/core/.specialist/tools/prompt-files.test.js +169 -0
  1028. package/core/.specialist/tools/replay-detectors.js +290 -0
  1029. package/core/.specialist/tools/rule-engine.js +621 -0
  1030. package/core/.specialist/tools/session-boot-ownership.test.js +117 -0
  1031. package/core/.specialist/tools/session-project-state.test.js +65 -0
  1032. package/core/.specialist/tools/session.js +1866 -0
  1033. package/core/.specialist/tools/stream-lease.js +263 -0
  1034. package/core/.specialist/tools/task-bridge-jev.test.js +170 -0
  1035. package/core/.specialist/tools/task-bridge.js +765 -0
  1036. package/core/.specialist/tools/verify-identity.js +453 -0
  1037. package/core/.specialist/tools/wish-mandate-delivery.test.js +76 -0
  1038. package/core/.system/README.md +555 -0
  1039. package/core/.system/agent-skills/README.md +724 -0
  1040. package/core/.system/archive/README.md +499 -0
  1041. package/core/.system/assessment/README.md +645 -0
  1042. package/core/.system/cli-tools/README.md +724 -0
  1043. package/core/.system/collaboration/KNOWLEDGE.md +65 -0
  1044. package/core/.system/collaboration/README.md +570 -0
  1045. package/core/.system/cortex/MODULES.md +1046 -0
  1046. package/core/.system/dashboard/FRONTEND.md +812 -0
  1047. package/core/.system/dashboard/README.md +737 -0
  1048. package/core/.system/external-skills/README.md +522 -0
  1049. package/core/.system/failure/README.md +723 -0
  1050. package/core/.system/formation/LEGACY_SKILLS.md +972 -0
  1051. package/core/.system/formation/POST_COMPLETE.md +600 -0
  1052. package/core/.system/formation/README.md +1092 -0
  1053. package/core/.system/formation/TOOLS_REFERENCE.md +1145 -0
  1054. package/core/.system/githooks/README.md +846 -0
  1055. package/core/.system/kenaz/README.md +787 -0
  1056. package/core/.system/memory/README.md +716 -0
  1057. package/core/.system/pipeline/README.md +712 -0
  1058. package/core/.system/rule/README.md +794 -0
  1059. package/core/.system/specialist/README.md +669 -0
  1060. package/core/.system/specialist/STRUCTURE.md +262 -0
  1061. package/core/.system/sunny/README.md +476 -0
  1062. package/core/.system/sunny/RULES.json +89 -0
  1063. package/core/.system/sunny/knowledge/INDEX.md +37 -0
  1064. package/core/.system/sunny/knowledge/agent-teams-api.md +0 -0
  1065. package/core/.system/sunny/knowledge/ansuz-specialist.md +500 -0
  1066. package/core/.system/sunny/knowledge/claude-cli-spawn.md +177 -0
  1067. package/core/.system/sunny/knowledge/collaboration-api.md +925 -0
  1068. package/core/.system/sunny/teammates/README.md +107 -0
  1069. package/core/.system/sunny/teammates/how_to_use.yaml +101 -0
  1070. package/core/.system/sunny/teammates/tools/headless/launcher.js +318 -0
  1071. package/core/.system/sunny/teammates/tools/powershell/launcher.js +241 -0
  1072. package/core/.system/sunny/teammates/tools/powershell/start.bat +50 -0
  1073. package/core/.system/sunny/teammates/tools/utils/env.js +96 -0
  1074. package/core/.system/sunny/teammates/tools/utils/format-output.js +329 -0
  1075. package/core/.system/sunny/tools.json +101 -0
  1076. package/core/.vendor/js-yaml.cjs +2795 -0
  1077. package/core/.vendor/require-yaml.cjs +8 -0
  1078. package/core/CLAUDE.md +172 -0
  1079. package/core/KENAZ_CORE_VERSION +1 -0
  1080. package/core/dev/ALAYA_FIELD_FEEDBACK_DESIGN.md +126 -0
  1081. package/core/dev/ANSUZ_SCAFFOLD_DIET_2026-09-20.md +231 -0
  1082. package/core/dev/ANSUZ_STARTUP_INJECTION_REVIEW.md +355 -0
  1083. package/core/dev/ANSUZ_WORKFLOW_MODERNIZATION.md +143 -0
  1084. package/core/dev/CORTEX_META_GRAPH_ASSESSMENT.md +99 -0
  1085. package/core/dev/FREYA_DOWNSTREAM_BUGS_2026-09-19.md +44 -0
  1086. package/core/dev/GLOBAL_MEMORY_IDENTITY_CONSOLIDATION.md +263 -0
  1087. package/core/dev/GUARD_EFFECTIVENESS_DESIGN.md +180 -0
  1088. package/core/dev/HEALTH_GATE_VARIANCE_ASSESSMENT.md +271 -0
  1089. package/core/dev/HOOK_DIET_2026-09-21.md +126 -0
  1090. package/core/dev/JEV_INTEGRATION_PLAN.md +189 -0
  1091. package/core/dev/KENAZ_AGENT_CONNECT_v1_SPEC.md +139 -0
  1092. package/core/dev/MOBILE_DESIGN_SPEC.md +569 -0
  1093. package/core/dev/MULTI_ANSUZ_SPEC.md +136 -0
  1094. package/core/dev/MUNINN_RETIREMENT.md +115 -0
  1095. package/core/dev/PHASE3_ATTRIBUTION_POPULATION_DIAGNOSIS.md +211 -0
  1096. package/core/dev/PHASE3_P3-2B_TASKLEVEL_PROBE.md +83 -0
  1097. package/core/dev/PHASE3_P3-2_POPULATION_DISJOINTNESS.md +83 -0
  1098. package/core/dev/PHASE3_P3-2_REMEASURE_REPORT.md +231 -0
  1099. package/core/dev/PREDICTION_GROUNDING_DESIGN.md +376 -0
  1100. package/core/dev/PRODUCT_SPEC.md +317 -0
  1101. package/core/dev/PRODUCT_SPEC_FOR_AI_tepmlate.md +716 -0
  1102. package/core/dev/PROJECT_REGISTRY_DUPLICATE_ASSESSMENT.md +86 -0
  1103. package/core/dev/STARTUP_TIMELINE_TASK_1995.md +181 -0
  1104. package/core/dev/SYNAPSE_WORKER_PER_PROJECT.md +881 -0
  1105. package/core/dev/TASK_1680_P3-3_DISPATCH_SPEC.md +96 -0
  1106. package/core/dev/TASK_1684_CALIBRATION_IMPACT_ANALYSIS.md +170 -0
  1107. package/core/dev/TASK_1684_FORK_A_GOODHART_DESIGN.md +171 -0
  1108. package/core/dev/TASK_1684_P3_2_REMEASURE_VALIDATION.md +262 -0
  1109. package/core/dev/TASK_1903_SIGNAL_AUC_MEASUREMENT.md +207 -0
  1110. package/core/dev/TASK_1904_BRANCH_INTEGRITY_AUDIT.md +146 -0
  1111. package/core/dev/ansuz-eval/README.md +38 -0
  1112. package/core/dev/ansuz-eval/build-fixtures.js +87 -0
  1113. package/core/dev/ansuz-eval/grade.js +96 -0
  1114. package/core/dev/ansuz-eval/grader.test.js +117 -0
  1115. package/core/dev/ansuz-eval/tasks.md +32 -0
  1116. package/core/dev/archive/ansuz/BOOT_FULL.md +141 -0
  1117. package/core/dev/archive/ansuz/agents/ansuz-boot.md +176 -0
  1118. package/core/dev/archive/ansuz/designs/alaya-passive-surfacing.md +84 -0
  1119. package/core/dev/archive/ansuz/designs/cc_memory_indexing.md +307 -0
  1120. package/core/dev/archive/ansuz/designs/check_guard.md +322 -0
  1121. package/core/dev/archive/ansuz/designs/consequence_loop.md +227 -0
  1122. package/core/dev/archive/ansuz/designs/mcp_kuzudb_lock_architecture.md +312 -0
  1123. package/core/dev/archive/ansuz/designs/phase0_git_enrichment.md +278 -0
  1124. package/core/dev/archive/ansuz/designs/refactor_mcp_tools_synapse.md +490 -0
  1125. package/core/dev/archive/ansuz/designs/semantic_markdown_extraction.md +167 -0
  1126. package/core/dev/archive/ansuz/designs/task_1372_prompt_injects_into.md +193 -0
  1127. package/core/dev/archive/ansuz/designs/thought_stack.md +286 -0
  1128. package/core/dev/archive/ansuz/investigations/reachability_unified_api_2026-04-11.md +330 -0
  1129. package/core/dev/archive/ansuz/investigations/synapse_orphans_indexing_bug_2026-04-11.md +352 -0
  1130. package/core/dev/archive/ansuz/investigations/synapse_orphans_reindex_verification_2026-04-11.md +48 -0
  1131. package/core/dev/archive/ansuz/investigations/synapse_orphans_verification_2026-04-11.md +170 -0
  1132. package/core/dev/archive/ansuz/legacy/kernel.yaml +399 -0
  1133. package/core/dev/archive/ansuz/legacy/phases/phase_0.yaml +418 -0
  1134. package/core/dev/archive/ansuz/legacy/phases/phase_1.yaml +376 -0
  1135. package/core/dev/archive/ansuz/legacy/phases/phase_10.yaml +35 -0
  1136. package/core/dev/archive/ansuz/legacy/phases/phase_11.yaml +582 -0
  1137. package/core/dev/archive/ansuz/legacy/phases/phase_2.yaml +94 -0
  1138. package/core/dev/archive/ansuz/legacy/phases/phase_3.yaml +274 -0
  1139. package/core/dev/archive/ansuz/legacy/phases/phase_4.yaml +67 -0
  1140. package/core/dev/archive/ansuz/legacy/phases/phase_5.yaml +32 -0
  1141. package/core/dev/archive/ansuz/legacy/phases/phase_6.yaml +91 -0
  1142. package/core/dev/archive/ansuz/legacy/phases/phase_7.yaml +58 -0
  1143. package/core/dev/archive/ansuz/legacy/phases/phase_8.yaml +146 -0
  1144. package/core/dev/archive/ansuz/legacy/phases/phase_9.yaml +424 -0
  1145. package/core/dev/archive/ansuz/specs/INDEX_bifrost_hook_parity.yaml +92 -0
  1146. package/core/dev/archive/ansuz/specs/active-inference-formation.yaml +453 -0
  1147. package/core/dev/archive/ansuz/specs/brief_TASK_1228_userpromptsubmit.yaml +191 -0
  1148. package/core/dev/archive/ansuz/specs/brief_TASK_1229_pretooluse_posttooluse.yaml +250 -0
  1149. package/core/dev/archive/ansuz/specs/brief_TASK_1230_sessionstart_stop.yaml +301 -0
  1150. package/core/dev/archive/ansuz/specs/brief_TASK_1231_verification.yaml +272 -0
  1151. package/core/dev/design/PHASE4_DESIGN.md +559 -0
  1152. package/core/dev/design/dashboard_docs_integration_PLAN.md +388 -0
  1153. package/core/dev/design/matrix_format_ABBREVIATIONS.md +655 -0
  1154. package/core/dev/design/matrix_format_DESIGN_SPEC.md +601 -0
  1155. package/core/dev/design/matrix_format_DISCUSSION_SUMMARY.md +484 -0
  1156. package/core/dev/design/matrix_format_EXAMPLE_memory.matrix +13 -0
  1157. package/core/dev/design/matrix_format_EXAMPLE_project_status.matrix +9 -0
  1158. package/core/dev/design/matrix_format_EXAMPLE_tasks.matrix +14 -0
  1159. package/core/dev/design/matrix_format_SYNTAX_BNF.md +754 -0
  1160. package/core/dev/design/matrix_format_TOKEN_COMPARISON.md +484 -0
  1161. package/core/dev/design/matrix_v2_COGNITIVE_DESIGN.md +503 -0
  1162. package/core/dev/design/matrix_v2_DISCUSSION_SUMMARY.md +414 -0
  1163. package/core/dev/design/matrix_v2_EXAMPLE.matrix +67 -0
  1164. package/core/dev/designs/EXPANDABLE_CARD_DESIGN_SPEC.md +509 -0
  1165. package/core/dev/jev-eval/ACTIVE_CORRECTION.md +52 -0
  1166. package/core/dev/jev-eval/ANNOTATION_GUIDE.md +68 -0
  1167. package/core/dev/jev-eval/BASELINE_COMPARISON.md +45 -0
  1168. package/core/dev/jev-eval/CONTEXT_REVIEW.md +31 -0
  1169. package/core/dev/jev-eval/EVALUATION_STATUS.md +39 -0
  1170. package/core/dev/jev-eval/HISTORICAL_CORPUS.md +33 -0
  1171. package/core/dev/jev-eval/PACKAGING_VERIFICATION.md +42 -0
  1172. package/core/dev/jev-eval/README.md +101 -0
  1173. package/core/dev/jev-eval/THALAMUS_RANKING.md +58 -0
  1174. package/core/dev/jev-eval/VALIDATION_PROGRESS.md +54 -0
  1175. package/core/dev/jev-eval/cli.mjs +50 -0
  1176. package/core/dev/jev-eval/context.mjs +183 -0
  1177. package/core/dev/jev-eval/corpus.mjs +186 -0
  1178. package/core/dev/jev-eval/fixtures/conversation-review.seed.jsonl +6 -0
  1179. package/core/dev/jev-eval/fixtures/synthetic.jsonl +11 -0
  1180. package/core/dev/jev-eval/metrics.mjs +67 -0
  1181. package/core/dev/jev-eval/muninn-baseline.mjs +119 -0
  1182. package/core/dev/jev-eval/providers.mjs +95 -0
  1183. package/core/dev/jev-eval/reports/annotation-pilot-2026-09-20.json +32 -0
  1184. package/core/dev/jev-eval/reports/context-review-2026-09-20.json +48 -0
  1185. package/core/dev/jev-eval/reports/conversation-review.pending.json +151 -0
  1186. package/core/dev/jev-eval/reports/history-corpus-2026-09-20.json +52 -0
  1187. package/core/dev/jev-eval/reports/length-probe-2026-09-20.json +133 -0
  1188. package/core/dev/jev-eval/reports/live-smoke-2026-09-20.json +616 -0
  1189. package/core/dev/jev-eval/reports/muninn-baseline-2026-09-20.json +52 -0
  1190. package/core/dev/jev-eval/reports/resilience-2026-09-20.json +520 -0
  1191. package/core/dev/jev-eval/reports/rules-baseline.json +197 -0
  1192. package/core/dev/jev-eval/reports/synthetic-review.pending.json +357 -0
  1193. package/core/dev/jev-eval/resilience.mjs +71 -0
  1194. package/core/dev/jev-eval/review.mjs +78 -0
  1195. package/core/dev/jev-eval/schema.mjs +87 -0
  1196. package/core/dev/jev-eval/test/context.test.mjs +95 -0
  1197. package/core/dev/jev-eval/test/corpus.test.mjs +102 -0
  1198. package/core/dev/jev-eval/test/eval.test.mjs +146 -0
  1199. package/core/dev/jev-eval/test/muninn-baseline.test.mjs +71 -0
  1200. package/core/dev/jev-eval/test/resilience.test.mjs +72 -0
  1201. package/core/dev/jev-eval/test/review.test.mjs +61 -0
  1202. package/core/dev/pipeline/LOCK_STATE.json +4 -0
  1203. package/core/dev/pipeline/OPTIMIZATION_PROPOSALS.json +32 -0
  1204. package/core/dev/pipeline/PHASE3_PLANNING_SUMMARY.md +338 -0
  1205. package/core/dev/pipeline/PIPELINE_CONFIG.json +46 -0
  1206. package/core/dev/pipeline/PROGRESS.md +113 -0
  1207. package/core/dev/pipeline/PROGRESS_template.md +860 -0
  1208. package/core/dev/pipeline/QA_REPORT_F008.md +431 -0
  1209. package/core/dev/pipeline/QA_REPORT_LOCAL_CLAUDE_DIAGNOSIS.md +583 -0
  1210. package/core/dev/pipeline/README.md +210 -0
  1211. package/core/dev/pipeline/SELF_ENHANCEMENT_STATUS.json.bak +47 -0
  1212. package/core/dev/pipeline/TASK_QUEUE.json +192 -0
  1213. package/core/dev/pipeline/WORKFLOW_GUIDE.md +824 -0
  1214. package/core/dev/pipeline/archived/TASK_015_tauri_init.yaml +53 -0
  1215. package/core/dev/pipeline/archived/TASK_016_tauri_commands.yaml +54 -0
  1216. package/core/dev/pipeline/archived/TASK_017_rust_pty.yaml +54 -0
  1217. package/core/dev/pipeline/archived/TASK_018_tauri_bundle.yaml +53 -0
  1218. package/core/dev/pipeline/archived/TASK_019_release_workflow.yaml +56 -0
  1219. package/core/dev/pipeline/archived/TASK_020_update_ui.yaml +54 -0
  1220. package/core/dev/pipeline/archived/TASK_021_update_notification_ui.yaml +55 -0
  1221. package/core/dev/pipeline/archived/TASK_022_remove_node_pty.yaml +65 -0
  1222. package/core/dev/pipeline/archived/TASK_023_api_routes_migration.yaml +86 -0
  1223. package/core/dev/pipeline/archived/TASK_024_feature_id_system.yaml +51 -0
  1224. package/core/dev/pipeline/archived/TASK_025_executable_acceptance.yaml +66 -0
  1225. package/core/dev/pipeline/archived/TASK_026_spec_versioning.yaml +56 -0
  1226. package/core/dev/pipeline/archived/TASK_027_drift_detection.yaml +60 -0
  1227. package/core/dev/pipeline/archived/TASK_028_tauri_pty_manager.yaml +60 -0
  1228. package/core/dev/pipeline/archived/TASK_029_tauri_pty_commands.yaml +62 -0
  1229. package/core/dev/pipeline/archived/TASK_030_frontend_session_adapter.yaml +54 -0
  1230. package/core/dev/pipeline/archived/TASK_031_terminal_tauri_events.yaml +56 -0
  1231. package/core/dev/pipeline/archived/TASK_041_scheduler_data_models.yaml +54 -0
  1232. package/core/dev/pipeline/archived/TASK_042_path_lock_manager.yaml +53 -0
  1233. package/core/dev/pipeline/archived/TASK_043_process_manager.yaml +57 -0
  1234. package/core/dev/pipeline/archived/TASK_044_git_integration.yaml +85 -0
  1235. package/core/dev/pipeline/archived/TASK_045_task_queue_manager.yaml +54 -0
  1236. package/core/dev/pipeline/archived/TASK_046_scheduler_dispatcher.yaml +60 -0
  1237. package/core/dev/pipeline/archived/TASK_047_tauri_scheduler_commands.yaml +55 -0
  1238. package/core/dev/pipeline/archived/TASK_048_realtime_status_push.yaml +92 -0
  1239. package/core/dev/pipeline/archived/TASK_049_frontend_scheduler_integration.yaml +58 -0
  1240. package/core/dev/pipeline/archived/TASK_050_error_recovery.yaml +56 -0
  1241. package/core/dev/pipeline/archived/TASK_051_optimization_proposals_backend.yaml +53 -0
  1242. package/core/dev/pipeline/archived/TASK_052_optimization_proposals_ui.yaml +58 -0
  1243. package/core/dev/pipeline/archived/TASK_053_optimization_proposals_diff_view.yaml +54 -0
  1244. package/core/dev/pipeline/archived/TASK_054_multi_project_scheduler_state.yaml +76 -0
  1245. package/core/dev/pipeline/archived/TASK_055_scheduler_api_project_scope.yaml +64 -0
  1246. package/core/dev/pipeline/archived/TASK_056_frontend_scheduler_project_scope.yaml +62 -0
  1247. package/core/dev/pipeline/archived/TASK_057_scheduler_module_structure.yaml +54 -0
  1248. package/core/dev/pipeline/archived/TASK_058_scheduler_models_extract.yaml +51 -0
  1249. package/core/dev/pipeline/archived/TASK_059_scheduler_core_extract.yaml +51 -0
  1250. package/core/dev/pipeline/archived/TASK_060_scheduler_commands_extract.yaml +51 -0
  1251. package/core/dev/pipeline/archived/TASK_061_scheduler_specialized_commands.yaml +53 -0
  1252. package/core/dev/pipeline/archived/TASK_062_process_manager_module_structure.yaml +56 -0
  1253. package/core/dev/pipeline/archived/TASK_063_process_manager_core_extract.yaml +56 -0
  1254. package/core/dev/pipeline/archived/TASK_064_recovery_module_structure.yaml +57 -0
  1255. package/core/dev/pipeline/archived/TASK_065_recovery_core_extract.yaml +56 -0
  1256. package/core/dev/pipeline/archived/TASK_066_self_enhancement_scheduler_models.yaml +60 -0
  1257. package/core/dev/pipeline/archived/TASK_067_agents_section_quick_actions.yaml +53 -0
  1258. package/core/dev/pipeline/archived/TASK_067_self_enhancement_scheduler_core.yaml +65 -0
  1259. package/core/dev/pipeline/archived/TASK_068_agent_workflow_rule_enhancement.yaml +46 -0
  1260. package/core/dev/pipeline/archived/TASK_068_self_enhancement_tauri_commands.yaml +61 -0
  1261. package/core/dev/pipeline/archived/TASK_069_agent_wizard_responsive.yaml +46 -0
  1262. package/core/dev/pipeline/archived/TASK_069_self_enhancement_ui.yaml +62 -0
  1263. package/core/dev/pipeline/archived/TASK_070_preview_panel_redesign.yaml +62 -0
  1264. package/core/dev/pipeline/archived/TASK_070_self_enhancement_integration.yaml +57 -0
  1265. package/core/dev/pipeline/archived/TASK_071_preview_panel_qa.yaml +98 -0
  1266. package/core/dev/pipeline/archived/TASK_071_single_agent_config.yaml +57 -0
  1267. package/core/dev/pipeline/archived/TASK_072_preview_modal_esc_fix.yaml +71 -0
  1268. package/core/dev/pipeline/archived/TASK_072_product_review_module.yaml +57 -0
  1269. package/core/dev/pipeline/archived/TASK_073_agents_page_component_refactor.yaml +68 -0
  1270. package/core/dev/pipeline/archived/TASK_073_rename_single_agent.yaml +64 -0
  1271. package/core/dev/pipeline/archived/TASK_074_preview_mode_ui_diagnosis.yaml +71 -0
  1272. package/core/dev/pipeline/archived/TASK_074_single_agent_ui_toggle.yaml +56 -0
  1273. package/core/dev/pipeline/archived/TASK_075_agents_page_component_refactor.yaml +69 -0
  1274. package/core/dev/pipeline/archived/TASK_075_single_agent_integration_test.yaml +75 -0
  1275. package/core/dev/pipeline/archived/TASK_076_preview_mode_ui_diagnosis.yaml +70 -0
  1276. package/core/dev/pipeline/archived/TASK_076_single_agent_continuous_mode.yaml +65 -0
  1277. package/core/dev/pipeline/archived/TASK_077_failure_directory_structure.yaml +51 -0
  1278. package/core/dev/pipeline/archived/TASK_077_single_agent_typescript_types.yaml +59 -0
  1279. package/core/dev/pipeline/archived/TASK_078_fail_001_agent_no_output.yaml +53 -0
  1280. package/core/dev/pipeline/archived/TASK_078_single_agent_ui_simplify.yaml +74 -0
  1281. package/core/dev/pipeline/archived/TASK_079_dashboard_rwd_responsive.yaml +63 -0
  1282. package/core/dev/pipeline/archived/TASK_079_fail_002_json_bom.yaml +56 -0
  1283. package/core/dev/pipeline/archived/TASK_080_fail_003_queue_pollution.yaml +56 -0
  1284. package/core/dev/pipeline/archived/TASK_080_http_server_module.yaml +55 -0
  1285. package/core/dev/pipeline/archived/TASK_081_failure_logging_tools.yaml +57 -0
  1286. package/core/dev/pipeline/archived/TASK_081_http_api_routes.yaml +62 -0
  1287. package/core/dev/pipeline/archived/TASK_082_frontend_api_adapter.yaml +51 -0
  1288. package/core/dev/pipeline/archived/TASK_082_integrate_failure_to_workflow.yaml +60 -0
  1289. package/core/dev/pipeline/archived/TASK_083_cleanup_nextjs_api.yaml +48 -0
  1290. package/core/dev/pipeline/archived/TASK_083_task_queue_cleanup.yaml +67 -0
  1291. package/core/dev/pipeline/archived/TASK_084_rust_dead_code_cleanup.yaml +66 -0
  1292. package/core/dev/pipeline/archived/TASK_084_scheduler_sync_logic_fix.yaml +68 -0
  1293. package/core/dev/pipeline/archived/TASK_085_http_api_web_mode_fixes.yaml +46 -0
  1294. package/core/dev/pipeline/archived/TASK_085_memory_consolidation_0204_0205.yaml +98 -0
  1295. package/core/dev/pipeline/archived/TASK_086_collapsible_preview_panel.yaml +161 -0
  1296. package/core/dev/pipeline/archived/TASK_086_web_mode_feature_parity.yaml +62 -0
  1297. package/core/dev/pipeline/archived/TASK_087_manual_memory_archival.yaml +163 -0
  1298. package/core/dev/pipeline/archived/TASK_087_mobile_http_control.yaml +68 -0
  1299. package/core/dev/pipeline/archived/TASK_088_fail_003_to_ppl_002_rule.yaml +63 -0
  1300. package/core/dev/pipeline/archived/TASK_088_mobile_http_qa.yaml +121 -0
  1301. package/core/dev/pipeline/archived/TASK_089_agent_collaboration_topic.yaml +60 -0
  1302. package/core/dev/pipeline/archived/TASK_089_web_mode_monitor_fix.yaml +58 -0
  1303. package/core/dev/pipeline/archived/TASK_090_cli_detection_fix.yaml +61 -0
  1304. package/core/dev/pipeline/archived/TASK_090_ui_ux_lessons_topic.yaml +63 -0
  1305. package/core/dev/pipeline/archived/TASK_091_expandable_card_design.yaml +56 -0
  1306. package/core/dev/pipeline/archived/TASK_091_move_agent_section_components.yaml +65 -0
  1307. package/core/dev/pipeline/archived/TASK_092_expandable_card_component.yaml +60 -0
  1308. package/core/dev/pipeline/archived/TASK_092_refactor_agent_create_wizard.yaml +84 -0
  1309. package/core/dev/pipeline/archived/TASK_093_taskcard_detail_integration.yaml +57 -0
  1310. package/core/dev/pipeline/archived/TASK_093_update_barrel_exports_test.yaml +84 -0
  1311. package/core/dev/pipeline/archived/TASK_094_ai_agent_generation_enhancement.yaml +115 -0
  1312. package/core/dev/pipeline/archived/TASK_094_proposalcard_detail_integration.yaml +55 -0
  1313. package/core/dev/pipeline/archived/TASK_095_preview_fixes.yaml +129 -0
  1314. package/core/dev/pipeline/archived/TASK_095_single_agent_task_selector.yaml +60 -0
  1315. package/core/dev/pipeline/archived/TASK_096_agents_page_ux_improvements.yaml +163 -0
  1316. package/core/dev/pipeline/archived/TASK_096_single_agent_status_sync.yaml +60 -0
  1317. package/core/dev/pipeline/archived/TASK_097_local_claude_error_logging.yaml +59 -0
  1318. package/core/dev/pipeline/archived/TASK_097_single_agent_monitor_events.yaml +59 -0
  1319. package/core/dev/pipeline/archived/TASK_098_product_manager_team_phase2.yaml +60 -0
  1320. package/core/dev/pipeline/archived/TASK_098_single_agent_refactor_test.yaml +58 -0
  1321. package/core/dev/pipeline/archived/TASK_099_backend_team_creation.yaml +258 -0
  1322. package/core/dev/pipeline/archived/TASK_100_frontend_team_creation.yaml +61 -0
  1323. package/core/dev/pipeline/archived/TASK_101_orchestrator_system.yaml +403 -0
  1324. package/core/dev/pipeline/archived/TASK_102_designer_sre_teams.yaml +90 -0
  1325. package/core/dev/pipeline/archived/TASK_103_integration_testing.yaml +86 -0
  1326. package/core/dev/pipeline/archived/TASK_128_integration_testing.yaml +83 -0
  1327. package/core/dev/pipeline/archived/TASK_134_cortex_v2_phase3_file_watcher.yaml +65 -0
  1328. package/core/dev/pipeline/archived/TASK_134_team_http_api.yaml +96 -0
  1329. package/core/dev/pipeline/archived/TASK_135_cortex_v2_phase3_git_monitor.yaml +63 -0
  1330. package/core/dev/pipeline/archived/TASK_136_cortex_v2_phase3_change_analyzer.yaml +69 -0
  1331. package/core/dev/pipeline/archived/TASK_137_cortex_v2_phase3_cache_invalidator.yaml +67 -0
  1332. package/core/dev/pipeline/archived/TASK_137_team_orchestrator_integration.yaml +93 -0
  1333. package/core/dev/pipeline/archived/TASK_138_cortex_v2_phase3_distributed_cache.yaml +68 -0
  1334. package/core/dev/pipeline/archived/TASK_138_matrix_folder_structure.yaml +61 -0
  1335. package/core/dev/pipeline/archived/TASK_139_cortex_v2_phase3_cache_prewarming.yaml +65 -0
  1336. package/core/dev/pipeline/archived/TASK_146_unified_documentation.yaml +141 -0
  1337. package/core/dev/pipeline/archived/TASK_147_pipeline_execution_rules.yaml +76 -0
  1338. package/core/dev/pipeline/archived/TASK_148_update_claude_md.yaml +77 -0
  1339. package/core/dev/pipeline/archived/TASK_149_fix_nextjs_mdx_serialization.yaml +63 -0
  1340. package/core/dev/pipeline/archived/TASK_149_update_team_docs.yaml +77 -0
  1341. package/core/dev/pipeline/archived/TASK_150_pipeline_workflow_guide.yaml +82 -0
  1342. package/core/dev/pipeline/archived/TASK_164_fix_smart_context_switch.yaml +49 -0
  1343. package/core/dev/pipeline/archived/TASK_165_ctags_symbol_index.yaml +53 -0
  1344. package/core/dev/pipeline/archived/TASK_166_symbol_search_mcp_tool.yaml +48 -0
  1345. package/core/dev/pipeline/archived/TASK_167_llm_module_summary.yaml +55 -0
  1346. package/core/dev/pipeline/archived/TASK_168_map_reduce_context.yaml +51 -0
  1347. package/core/dev/pipeline/archived/TASK_169_v2_integration_testing.yaml +52 -0
  1348. package/core/dev/pipeline/backups/archive_2026-02-04T22-07-22/TASK_QUEUE_backup.json +95 -0
  1349. package/core/dev/pipeline/docs/multi-agent-coordination.md +446 -0
  1350. package/core/dev/pipeline/docs/overview.md +406 -0
  1351. package/core/dev/pipeline/docs/task-management.md +412 -0
  1352. package/core/dev/pipeline/docs/workflows.md +32 -0
  1353. package/core/dev/pipeline/orchestrator/schemas/task_queue_schema.json +58 -0
  1354. package/core/dev/pipeline/orchestrator/schemas/task_schema.json +139 -0
  1355. package/core/dev/pipeline/plans/PLAN_task_cli_refactor.md +281 -0
  1356. package/core/dev/pipeline/tasks/.gitkeep +1 -0
  1357. package/core/dev/pipeline/test_results/TASK_TEST_PARALLEL_002_result.txt +27 -0
  1358. package/core/dev/plans/CLI_FIRST_INSTALL_FLOW.md +128 -0
  1359. package/core/dev/plans/FORMATION_RETIREMENT_PLAN.md +313 -0
  1360. package/core/dev/plans/KUZU_REPLACEMENT_PLAN.md +126 -0
  1361. package/core/dev/schemas/PRODUCT_SPEC.example.yaml +382 -0
  1362. package/core/dev/schemas/PRODUCT_SPEC.schema.json +800 -0
  1363. package/core/dev/schemas/README.md +517 -0
  1364. package/core/dev/schemas/TASK.schema.json +226 -0
  1365. package/core/dev/schemas/dataflows_ground_truth.yaml +173 -0
  1366. package/core/dev/schemas/dataflows_spec.yaml +160 -0
  1367. package/core/dev/schemas/extends_ground_truth.yaml +66 -0
  1368. package/core/dev/schemas/extends_spec.yaml +121 -0
  1369. package/core/dev/schemas/implements_ground_truth.yaml +77 -0
  1370. package/core/dev/schemas/implements_spec.yaml +140 -0
  1371. package/core/dev/scripts/CRASH_DIAGNOSIS.md +47 -0
  1372. package/core/dev/scripts/README.md +142 -0
  1373. package/core/dev/scripts/RUN_ONCE.bat +40 -0
  1374. package/core/dev/scripts/START_DEV_AGENT.bat +63 -0
  1375. package/core/dev/scripts/START_MULTI_AGENT.bat +80 -0
  1376. package/core/dev/scripts/check-alaya-report-isolation.js +255 -0
  1377. package/core/dev/scripts/check-file-size.js +268 -0
  1378. package/core/dev/scripts/ci-feedback.js +251 -0
  1379. package/core/dev/scripts/clean-verify-targets.js +132 -0
  1380. package/core/dev/scripts/cleanup-queue.js +184 -0
  1381. package/core/dev/scripts/cleanup_queue.js +86 -0
  1382. package/core/dev/scripts/dev_agent_scheduler.ps1 +536 -0
  1383. package/core/dev/scripts/dispatch-stats.js +384 -0
  1384. package/core/dev/scripts/dispatch-stats.test.js +162 -0
  1385. package/core/dev/scripts/gc-agent-worktrees.js +461 -0
  1386. package/core/dev/scripts/gc-agent-worktrees.test.js +48 -0
  1387. package/core/dev/scripts/hooks/README.md +148 -0
  1388. package/core/dev/scripts/init_git.ps1 +396 -0
  1389. package/core/dev/scripts/init_git.sh +337 -0
  1390. package/core/dev/scripts/init_project.ps1 +851 -0
  1391. package/core/dev/scripts/init_project.sh +477 -0
  1392. package/core/dev/scripts/js-yaml-resolution.test.js +48 -0
  1393. package/core/dev/scripts/kenaz-session.js +354 -0
  1394. package/core/dev/scripts/kenaz-session.test.js +234 -0
  1395. package/core/dev/scripts/legacy/README.md +39 -0
  1396. package/core/dev/scripts/legacy/dev_agent_scheduler.ps1.bak +536 -0
  1397. package/core/dev/scripts/legacy/multi_agent_scheduler.ps1.bak +1978 -0
  1398. package/core/dev/scripts/matrix/CLI_README.md +214 -0
  1399. package/core/dev/scripts/matrix/README.md +310 -0
  1400. package/core/dev/scripts/matrix/package-lock.json +4266 -0
  1401. package/core/dev/scripts/matrix/package.json +55 -0
  1402. package/core/dev/scripts/matrix/src/abbreviations.ts +295 -0
  1403. package/core/dev/scripts/matrix/src/cli/commands/convert.ts +211 -0
  1404. package/core/dev/scripts/matrix/src/cli/commands/create.ts +95 -0
  1405. package/core/dev/scripts/matrix/src/cli/commands/delete.ts +102 -0
  1406. package/core/dev/scripts/matrix/src/cli/commands/list-tags.ts.wip +140 -0
  1407. package/core/dev/scripts/matrix/src/cli/commands/manage-tags.ts.wip +173 -0
  1408. package/core/dev/scripts/matrix/src/cli/commands/query.ts +261 -0
  1409. package/core/dev/scripts/matrix/src/cli/commands/read.ts +77 -0
  1410. package/core/dev/scripts/matrix/src/cli/commands/stats.ts.wip +168 -0
  1411. package/core/dev/scripts/matrix/src/cli/commands/tokens.ts.wip +126 -0
  1412. package/core/dev/scripts/matrix/src/cli/commands/update.ts +147 -0
  1413. package/core/dev/scripts/matrix/src/cli/commands/validate.ts +275 -0
  1414. package/core/dev/scripts/matrix/src/cli/index.ts +350 -0
  1415. package/core/dev/scripts/matrix/src/cli/utils/file-handler.ts +72 -0
  1416. package/core/dev/scripts/matrix/src/cli/utils/logger.ts +65 -0
  1417. package/core/dev/scripts/matrix/src/index.ts +62 -0
  1418. package/core/dev/scripts/matrix/src/indexer/tag-indexer.ts +165 -0
  1419. package/core/dev/scripts/matrix/src/parser.ts +281 -0
  1420. package/core/dev/scripts/matrix/src/serializer.ts +151 -0
  1421. package/core/dev/scripts/matrix/src/validator.ts +301 -0
  1422. package/core/dev/scripts/matrix/tests/abbreviations.test.ts +122 -0
  1423. package/core/dev/scripts/matrix/tests/cli.test.ts +177 -0
  1424. package/core/dev/scripts/matrix/tests/convert.test.ts +143 -0
  1425. package/core/dev/scripts/matrix/tests/parser.test.ts +203 -0
  1426. package/core/dev/scripts/matrix/tests/query.test.ts +85 -0
  1427. package/core/dev/scripts/matrix/tests/serializer.test.ts +197 -0
  1428. package/core/dev/scripts/matrix/tests/validate.test.ts +141 -0
  1429. package/core/dev/scripts/matrix/tests/validator.test.ts +167 -0
  1430. package/core/dev/scripts/matrix/tsconfig.json +20 -0
  1431. package/core/dev/scripts/matrix/types/index.d.ts +111 -0
  1432. package/core/dev/scripts/matrix/types/index.d.ts.map +1 -0
  1433. package/core/dev/scripts/matrix/types/index.js +8 -0
  1434. package/core/dev/scripts/matrix/types/index.js.map +1 -0
  1435. package/core/dev/scripts/matrix/types/index.ts +124 -0
  1436. package/core/dev/scripts/memory-guard-eval.js +330 -0
  1437. package/core/dev/scripts/memory-usage-report.js +152 -0
  1438. package/core/dev/scripts/migrate-task-dependencies.js +198 -0
  1439. package/core/dev/scripts/multi_agent_scheduler.ps1 +2021 -0
  1440. package/core/dev/scripts/multi_agent_scheduler.sh +1344 -0
  1441. package/core/dev/scripts/probe/ansuz-scaffold-ablation.js +579 -0
  1442. package/core/dev/scripts/probe/ansuz-scaffold-ablation.test.js +244 -0
  1443. package/core/dev/scripts/probe/hippocampus-concurrency.js +247 -0
  1444. package/core/dev/scripts/probe/hook-latency-probe.js +315 -0
  1445. package/core/dev/scripts/probe/hook-latency-probe.test.js +105 -0
  1446. package/core/dev/scripts/probe/prediction-signal-auc.js +483 -0
  1447. package/core/dev/scripts/probe/prediction-signal-auc.test.js +200 -0
  1448. package/core/dev/scripts/reset_tasks.js +99 -0
  1449. package/core/dev/scripts/run-rust-tests.js +207 -0
  1450. package/core/dev/scripts/run-rust-tests.test.js +154 -0
  1451. package/core/dev/scripts/run_once.sh +47 -0
  1452. package/core/dev/scripts/rust-verify-worktree.js +591 -0
  1453. package/core/dev/scripts/rust-verify-worktree.test.js +574 -0
  1454. package/core/dev/scripts/seh_probe.rs +26 -0
  1455. package/core/dev/scripts/setup_mcp.ps1 +192 -0
  1456. package/core/dev/scripts/setup_mcp.sh +159 -0
  1457. package/core/dev/scripts/setup_rag.ps1 +304 -0
  1458. package/core/dev/scripts/setup_rag.sh +230 -0
  1459. package/core/dev/scripts/start_dev_agent.sh +137 -0
  1460. package/core/dev/scripts/start_multi_agent.sh +41 -0
  1461. package/core/dev/scripts/sync_task_queue.ps1 +505 -0
  1462. package/core/dev/scripts/sync_task_queue.sh +392 -0
  1463. package/core/dev/scripts/task1961/RUNBOOK.md +300 -0
  1464. package/core/dev/scripts/task1961/fixtures/never-listens.server.js +54 -0
  1465. package/core/dev/scripts/task1961/fixtures/slow-serve.server.js +134 -0
  1466. package/core/dev/scripts/task1961/run-fixture.js +659 -0
  1467. package/core/dev/scripts/task1961/selftest.js +247 -0
  1468. package/core/dev/scripts/test-pty-ws-tunnel.js +229 -0
  1469. package/core/dev/scripts/validate_pipeline.js +197 -0
  1470. package/core/dev/scripts/verify-isbar-capture.js +100 -0
  1471. package/core/dev/scripts/verify-target-dir.js +69 -0
  1472. package/core/dev/scripts/verify-task-1839.js +141 -0
  1473. package/core/dev/specs/agent-connect/PROTOCOL.md +177 -0
  1474. package/core/dev/specs/agent-connect/SDK_GUIDE.md +915 -0
  1475. package/core/dev/specs/agent-connect/examples/minimal-site/README.md +137 -0
  1476. package/core/dev/specs/agent-connect/examples/minimal-site/package.json +12 -0
  1477. package/core/dev/specs/agent-connect/examples/minimal-site/public/index.html +116 -0
  1478. package/core/dev/specs/agent-connect/examples/minimal-site/public/install-redirect.js +73 -0
  1479. package/core/dev/specs/agent-connect/examples/minimal-site/server.js +516 -0
  1480. package/core/dev/specs/agent-connect/examples/minimal-site/test/smoke.test.mjs +263 -0
  1481. package/core/dev/specs/agent-connect/history/DEFECT_REPORT_kenaz-agent-hub_2026-09-09_v0.4-empty-prompt-no-first-turn.md +77 -0
  1482. package/core/dev/specs/agent-connect/history/DEFECT_REPORT_kenaz-agent-hub_2026-09-09_v0.4-prompt-mojibake.md +90 -0
  1483. package/core/dev/specs/agent-connect/history/FEATURE_REQUEST_kenaz-agent-hub_2026-09-07.md +61 -0
  1484. package/core/dev/specs/agent-connect/history/FEATURE_REQUEST_kenaz-agent-hub_2026-09-08_relay-v1-conformance.md +76 -0
  1485. package/core/dev/specs/agent-connect/history/FEATURE_REQUEST_kenaz-agent-hub_2026-09-09_v0.4-session-channel.md +87 -0
  1486. package/core/dev/specs/agent-connect/history/FLOWPIX_REPLY_agent-hub_2026-09-08_relay-v1-answers.md +68 -0
  1487. package/core/dev/specs/agent-connect/history/FLOWPIX_bridge_CONTRACT.md +642 -0
  1488. package/core/dev/specs/agent-connect/history/FLOWPIX_spikes_relay_spike_relay.mjs +244 -0
  1489. package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-07.md +77 -0
  1490. package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-08_direction-change-v0.3.md +44 -0
  1491. package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-08_relay-v1-answers-ack.md +37 -0
  1492. package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-08_relay-v1-conformance.md +56 -0
  1493. package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-09_annotations-install-coldstart.md +44 -0
  1494. package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-09_empty-prompt-first-turn.md +56 -0
  1495. package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-09_prompt-mojibake-fixed.md +48 -0
  1496. package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-09_session-channel.md +57 -0
  1497. package/core/dev/specs/agent-connect/history/PROTOCOL_v0.3_snapshot.md +379 -0
  1498. package/core/dev/specs/agent-connect/history/README.md +47 -0
  1499. package/core/dev/specs/peer/CODEX_INTERACTIVE_PUSH.md +65 -0
  1500. package/core/dev/specs/peer/CODEX_PEER_PULL_SPIKE.md +54 -0
  1501. package/core/dev/specs/peer/MODS_SPIKE.md +133 -0
  1502. package/core/dev/specs/peer/PER_PROJECT_ADDRESSING.md +143 -0
  1503. package/core/dev/specs/peer/SWARM_PROTOCOLS.md +256 -0
  1504. package/core/dev/specs/peer/codex-hook-shim-peer.test.js +101 -0
  1505. package/core/dev/specs/peer/codex-push-launcher.test.js +142 -0
  1506. package/core/dev/specs/peer/setup-codex-hooks.test.js +22 -0
  1507. package/core/dev/specs/peer-ansuz/DELIVERY_SPIKE.md +397 -0
  1508. package/core/dev/specs/peer-ansuz/DESIGN.md +109 -0
  1509. package/core/dev/specs/peer-ansuz/spike/claude_poke.js +129 -0
  1510. package/core/dev/specs/peer-ansuz/spike/claude_session_start_hook.js +37 -0
  1511. package/core/dev/specs/peer-ansuz/spike/claude_settings_hook.json +14 -0
  1512. package/core/dev/specs/peer-ansuz/spike/codex_appserver_client.js +105 -0
  1513. package/core/dev/specs/peer-ansuz/spike/codex_appserver_query.js +29 -0
  1514. package/core/dev/specs/peer-ansuz/spike/extract_timeline.js +26 -0
  1515. package/core/dev/specs/synapse/SYMBOL_IDENTITY.md +305 -0
  1516. package/core/dev/spikes/A4-cypher-varlen.md +176 -0
  1517. package/core/dev/spikes/bloat-rounds.sh +25 -0
  1518. package/core/dev/spikes/mods/clean-claude.js +9 -0
  1519. package/core/dev/spikes/mods/drive-probe.js +29 -0
  1520. package/core/dev/spikes/mods/e2e-peer.js +71 -0
  1521. package/core/dev/spikes/mods/evidence/e2e-peer-control.json +17 -0
  1522. package/core/dev/spikes/mods/evidence/e2e-peer-mod.json +17 -0
  1523. package/core/dev/spikes/mods/evidence/probe-006a6e65-d807-4bc1-b648-fd7d1edfe0b4.jsonl +4 -0
  1524. package/core/dev/spikes/mods/evidence/probe-cebdf1f7-f9c4-47a8-83cd-7c0786177404.jsonl +12 -0
  1525. package/core/dev/spikes/mods/evidence/probe-eb21147d-10ce-4c32-93ed-37ca37d88d5a.jsonl +11 -0
  1526. package/core/dev/spikes/mods/evidence/stream-cebdf1f7.jsonl +18 -0
  1527. package/core/dev/spikes/mods/kenaz-mod-probe/.claude-plugin/plugin.json +1 -0
  1528. package/core/dev/spikes/mods/kenaz-mod-probe/hooks/hooks.json +1 -0
  1529. package/core/dev/spikes/mods/kenaz-mod-probe/hooks/register.ts +65 -0
  1530. package/core/dev/spikes/mods/kenaz-mod-probe/tsconfig.json +3 -0
  1531. package/core/k-cli/README.md +423 -0
  1532. package/core/k-cli/package.json +21 -0
  1533. package/core/k-cli/templates/k-cli.md +91 -0
  1534. package/core/k-cli/test/TEST_SPEC.md +134 -0
  1535. package/core/k-cli/test/run.sh +469 -0
  1536. package/core/plugins/kenaz/.claude-plugin/plugin.json +1 -0
  1537. package/core/plugins/kenaz/.mcp.json +5 -0
  1538. package/core/plugins/kenaz/INVENTORY.md +48 -0
  1539. package/core/plugins/kenaz/README.md +55 -0
  1540. package/core/plugins/kenaz/commands/Amelia.md +5 -0
  1541. package/core/plugins/kenaz/commands/Ansuz.md +38 -0
  1542. package/core/plugins/kenaz/commands/architect.md +24 -0
  1543. package/core/plugins/kenaz/commands/incident.md +15 -0
  1544. package/core/plugins/kenaz/commands/kenaz.md +12 -0
  1545. package/core/plugins/kenaz/commands/review.md +14 -0
  1546. package/core/plugins/kenaz/commands/security.md +15 -0
  1547. package/core/plugins/kenaz/commands/spec.md +22 -0
  1548. package/core/plugins/kenaz/commands/strategy.md +141 -0
  1549. package/core/plugins/kenaz/commands//347/224/242/345/223/201.md +15 -0
  1550. package/core/plugins/kenaz/commands//350/250/255/350/250/210.md +14 -0
  1551. package/core/plugins/kenaz/commands//350/251/225/344/274/260.md +16 -0
  1552. package/core/plugins/kenaz/guidance.md +5 -0
  1553. package/core/plugins/kenaz/hooks/core-resolve.js +230 -0
  1554. package/core/plugins/kenaz/hooks/hooks.json +31 -0
  1555. package/core/plugins/kenaz/hooks/kenaz-hook.js +112 -0
  1556. package/core/plugins/kenaz/hooks/mode.js +39 -0
  1557. package/core/plugins/kenaz/scripts/kenaz-mode.js +46 -0
  1558. package/core/plugins/kenaz/scripts/kenaz.test.js +123 -0
  1559. package/core/plugins/kenaz/scripts/sync.js +45 -0
  1560. package/core/plugins/kenaz/scripts/ygg.js +157 -0
  1561. package/core/plugins/kenaz/skills/adapt/SKILL.md +199 -0
  1562. package/core/plugins/kenaz/skills/animate/SKILL.md +190 -0
  1563. package/core/plugins/kenaz/skills/architect_agent/SKILL.md +408 -0
  1564. package/core/plugins/kenaz/skills/assessment_agent/SKILL.md +289 -0
  1565. package/core/plugins/kenaz/skills/audit/SKILL.md +129 -0
  1566. package/core/plugins/kenaz/skills/backend_agent/SKILL.md +407 -0
  1567. package/core/plugins/kenaz/skills/backend_engineer/SKILL.md +788 -0
  1568. package/core/plugins/kenaz/skills/bolder/SKILL.md +132 -0
  1569. package/core/plugins/kenaz/skills/clarify/SKILL.md +180 -0
  1570. package/core/plugins/kenaz/skills/code_reviewer/SKILL.md +305 -0
  1571. package/core/plugins/kenaz/skills/code_reviewer/patterns.yaml +85 -0
  1572. package/core/plugins/kenaz/skills/colorize/SKILL.md +158 -0
  1573. package/core/plugins/kenaz/skills/critique/SKILL.md +118 -0
  1574. package/core/plugins/kenaz/skills/delight/SKILL.md +317 -0
  1575. package/core/plugins/kenaz/skills/designer/SKILL.md +845 -0
  1576. package/core/plugins/kenaz/skills/dev_agent/SKILL.md +503 -0
  1577. package/core/plugins/kenaz/skills/developer/SKILL.md +792 -0
  1578. package/core/plugins/kenaz/skills/distill/SKILL.md +137 -0
  1579. package/core/plugins/kenaz/skills/extract/SKILL.md +95 -0
  1580. package/core/plugins/kenaz/skills/feature_agent/SKILL.md +303 -0
  1581. package/core/plugins/kenaz/skills/frontend-design/SKILL.md +127 -0
  1582. package/core/plugins/kenaz/skills/frontend-design/reference/color-and-contrast.md +132 -0
  1583. package/core/plugins/kenaz/skills/frontend-design/reference/interaction-design.md +123 -0
  1584. package/core/plugins/kenaz/skills/frontend-design/reference/motion-design.md +99 -0
  1585. package/core/plugins/kenaz/skills/frontend-design/reference/responsive-design.md +114 -0
  1586. package/core/plugins/kenaz/skills/frontend-design/reference/spatial-design.md +100 -0
  1587. package/core/plugins/kenaz/skills/frontend-design/reference/typography.md +131 -0
  1588. package/core/plugins/kenaz/skills/frontend-design/reference/ux-writing.md +107 -0
  1589. package/core/plugins/kenaz/skills/frontend_agent/SKILL.md +327 -0
  1590. package/core/plugins/kenaz/skills/harden/SKILL.md +358 -0
  1591. package/core/plugins/kenaz/skills/incident_response/SKILL.md +315 -0
  1592. package/core/plugins/kenaz/skills/normalize/SKILL.md +67 -0
  1593. package/core/plugins/kenaz/skills/onboard/SKILL.md +243 -0
  1594. package/core/plugins/kenaz/skills/optimize/SKILL.md +269 -0
  1595. package/core/plugins/kenaz/skills/polish/SKILL.md +202 -0
  1596. package/core/plugins/kenaz/skills/product_manager/SKILL.md +1091 -0
  1597. package/core/plugins/kenaz/skills/qa_engineer/SKILL.md +1269 -0
  1598. package/core/plugins/kenaz/skills/quieter/SKILL.md +118 -0
  1599. package/core/plugins/kenaz/skills/security_agent/SKILL.md +312 -0
  1600. package/core/plugins/kenaz/skills/spec_optimizer/SKILL.md +299 -0
  1601. package/core/plugins/kenaz/skills/sre_agent/SKILL.md +1347 -0
  1602. package/core/plugins/kenaz/skills/ui-ux-pro-max/SKILL.md +377 -0
  1603. package/core/plugins/kenaz/skills/ui-ux-pro-max/data/charts.csv +26 -0
  1604. package/core/plugins/kenaz/skills/ui-ux-pro-max/data/colors.csv +97 -0
  1605. package/core/plugins/kenaz/skills/ui-ux-pro-max/data/icons.csv +101 -0
  1606. package/core/plugins/kenaz/skills/ui-ux-pro-max/data/landing.csv +31 -0
  1607. package/core/plugins/kenaz/skills/ui-ux-pro-max/data/products.csv +97 -0
  1608. package/core/plugins/kenaz/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
  1609. package/core/plugins/kenaz/skills/ui-ux-pro-max/data/stacks/astro.csv +54 -0
  1610. package/core/plugins/kenaz/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  1611. package/core/plugins/kenaz/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  1612. package/core/plugins/kenaz/skills/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
  1613. package/core/plugins/kenaz/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  1614. package/core/plugins/kenaz/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  1615. package/core/plugins/kenaz/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  1616. package/core/plugins/kenaz/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  1617. package/core/plugins/kenaz/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
  1618. package/core/plugins/kenaz/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  1619. package/core/plugins/kenaz/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  1620. package/core/plugins/kenaz/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  1621. package/core/plugins/kenaz/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  1622. package/core/plugins/kenaz/skills/ui-ux-pro-max/data/styles.csv +68 -0
  1623. package/core/plugins/kenaz/skills/ui-ux-pro-max/data/typography.csv +58 -0
  1624. package/core/plugins/kenaz/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
  1625. package/core/plugins/kenaz/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  1626. package/core/plugins/kenaz/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
  1627. package/core/plugins/kenaz/skills/ui-ux-pro-max/scripts/core.py +253 -0
  1628. package/core/plugins/kenaz/skills/ui-ux-pro-max/scripts/design_system.py +1067 -0
  1629. package/core/plugins/kenaz/skills/ui-ux-pro-max/scripts/search.py +106 -0
  1630. package/core/plugins/kenaz-peer/.claude-plugin/plugin.json +1 -0
  1631. package/core/plugins/kenaz-peer/hooks/hooks.json +1 -0
  1632. package/core/plugins/kenaz-peer/hooks/register.test.ts +62 -0
  1633. package/core/plugins/kenaz-peer/hooks/register.ts +146 -0
  1634. package/core/plugins/kenaz-peer/tsconfig.json +3 -0
  1635. package/lib/cli.js +251 -0
  1636. package/lib/cli.test.js +59 -0
  1637. package/lib/dashboard.js +80 -0
  1638. package/lib/dashboard.test.js +59 -0
  1639. package/package.json +28 -4
  1640. package/vendor/install-kenaz-cli.js +268 -0
  1641. package/README.md +0 -3
@@ -0,0 +1,1931 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Formation Dispatch — CLI 入口
4
+ *
5
+ * 根據陣型調度 subagent 執行任務。
6
+ * 實際邏輯分散在各模組:loader, prompt, runner, logger, utils。
7
+ *
8
+ * Usage:
9
+ * node .formation/tools/dispatch.js --skill=do --task=TASK_172
10
+ * node .formation/tools/dispatch.js --formation=solo --skill=strategy --task=TASK_172
11
+ * node .formation/tools/dispatch.js --formation=squad --skill=blitz --task=TASK_173
12
+ * node .formation/tools/dispatch.js --formation=legion --skill=forge --task=TASK_174 --dry-run
13
+ */
14
+
15
+ const path = require('path');
16
+ const fs = require('fs');
17
+ const { execSync } = require('child_process');
18
+ const { loadSkill, loadTask } = require('./loader');
19
+ const {
20
+ buildPrompt, SUBAGENT_PREFIX, SUBAGENT_PREFIX_DIRECT, buildSubagentWorktreePrefix,
21
+ promptProfile, extractRigor, extractComplexity, splitPromptSections,
22
+ applyRustCheckToPrefix,
23
+ } = require('./prompt');
24
+ const { runSingle, runParallel } = require('./runner');
25
+ const {
26
+ generateSessionId, ensureGitReady, ROOT, loadDashboardModels,
27
+ resolveWorktreeDecision, dispatchLockPath, tryAcquireDispatchLock, dispatchLockStaleness,
28
+ createWorktree, ensureWorktreeDirIgnored, COLLABORATION_API,
29
+ getVerifyOfflineCommand,
30
+ } = require('./utils');
31
+ const { refreshCache, hasRemoteConflict, hasRemoteFileConflict, isCacheStale } = require('./remote-conflict');
32
+
33
+ // TASK_1815: the Agent tool's `model` parameter accepts ONLY these Claude
34
+ // family names — no versions, no [1m] speed modifiers, no full model ids.
35
+ // Measured 2026-07-26 by a direct Agent tool probe from the main thread:
36
+ // model="claude-fable-5" and model="gpt-5-codex" both raise the SAME
37
+ // InputValidationError listing exactly this enum. This is a harness-side
38
+ // constraint that may drift with Claude Code versions — keep the four values
39
+ // in THIS single constant; if subagent dispatch starts failing with
40
+ // InputValidationError on the model field, re-probe the Agent tool and update
41
+ // here (nowhere else).
42
+ // (Declared before the CLI entry point below — module-scope code calls
43
+ // getSubagentDispatchParams during evaluation, so a later `const` would be in
44
+ // its temporal dead zone at call time.)
45
+ const AGENT_TOOL_MODEL_ENUM = ['sonnet', 'opus', 'haiku', 'fable'];
46
+
47
+ /**
48
+ * TASK_1815: translate a dashboard-models.json dispatchModel string into the
49
+ * Agent tool model enum. Dashboard model ids carry versions and speed
50
+ * modifiers (claude-opus-5[1m], claude-sonnet-4-6, ...) that the Agent tool
51
+ * cannot express — the enum has FAMILY names only. So this translation is
52
+ * structurally LOSSY: claude-opus-5[1m] and claude-opus-4-8[1m] both become
53
+ * 'opus'. Callers must surface that loss, never treat it as equivalence.
54
+ * NOTE: dashboard/src/lib/models.ts `family` ('claude'|'bifrost') is the
55
+ * ADAPTER family and is unrelated to this Claude sub-family mapping.
56
+ * @param {string} rawModel - dashboard model id, possibly with [1m]-style suffix
57
+ * @returns {{ model: string|null, lossless: boolean }} model=null → unmappable
58
+ */
59
+ function translateModelForAgentTool(rawModel) {
60
+ // Strip Formation-internal speed modifier suffixes like [1m]
61
+ const stripped = String(rawModel || '').replace(/\[.*?\]/g, '').trim();
62
+ if (AGENT_TOOL_MODEL_ENUM.includes(stripped)) {
63
+ // Already a bare family name — lossless only if there was no suffix to strip.
64
+ return { model: stripped, lossless: stripped === String(rawModel).trim() };
65
+ }
66
+ // claude-<family>[-version...] → <family>. Covers every NATIVE id in
67
+ // dashboard/src/lib/models.ts (claude-fable-5-1[1m], claude-opus-5-5[1m],
68
+ // claude-fable-5[1m], claude-opus-4-8[1m], claude-sonnet-5,
69
+ // claude-sonnet-4-6) plus future versions of the same families. 'haiku' has
70
+ // no dashboard source entry today but maps fine if one appears.
71
+ const m = stripped.match(/^claude-(opus|sonnet|haiku|fable)(?:-|$)/);
72
+ if (m) return { model: m[1], lossless: false };
73
+ return { model: null, lossless: false };
74
+ }
75
+
76
+ // TASK_1998 R3 (spec correction, user decision 2026-09-22 — supersedes an
77
+ // earlier low→haiku/high→opus hard-coded policy that was implemented and then
78
+ // reverted before merge): the model ALWAYS follows the Dashboard setting.
79
+ // For every rigor the model is dashboard-models.json's `dispatchModel`,
80
+ // exactly as before R3 — UNLESS that same file also carries an explicit
81
+ // `dispatchModelByRigor: {low?, medium?, high?}` object (populated from the
82
+ // Dashboard's own settings UI, not hand-edited), in which case the entry for
83
+ // the card's rigor wins for that rigor only (missing keys fall back to
84
+ // dispatchModel). `--dispatch-model` CLI keeps precedence over both. Every
85
+ // source runs through the SAME translateModelForAgentTool below, and
86
+ // TASK_1815's rule applies uniformly: an id that cannot be mapped to the
87
+ // Agent tool enum exits 1 loudly — never a silent substitute.
88
+ /**
89
+ * @param {object} p
90
+ * @param {string|null} p.rigor - card rigor ('low'|'medium'|'high'|null).
91
+ * null/unrecognized normalizes to 'medium' — mirrors promptProfile()'s
92
+ * treatment of missing/unrecognized rigor as the diet(medium) default.
93
+ * @param {object|null} p.models - parsed dashboard-models.json (routing.models)
94
+ * @param {string|null} p.cliDispatchModel - --dispatch-model CLI value, if any
95
+ * @returns {{ rawModel: string, source: 'cli'|'dashboard-by-rigor'|'dashboard', label: string, rigorKey: 'low'|'medium'|'high' }}
96
+ */
97
+ function resolveDispatchModelForRigor({ rigor, models, cliDispatchModel }) {
98
+ const rigorKey = (rigor === 'low' || rigor === 'high') ? rigor : 'medium';
99
+ // 1. CLI flag wins over everything.
100
+ if (cliDispatchModel) {
101
+ return { rawModel: cliDispatchModel, source: 'cli', label: '--dispatch-model', rigorKey };
102
+ }
103
+ // 2. dashboard-models.json dispatchModelByRigor — only when the Dashboard
104
+ // has set an entry for THIS rigor; unset keys fall through to dispatchModel.
105
+ const byRigor = (models && typeof models.dispatchModelByRigor === 'object' && models.dispatchModelByRigor) || null;
106
+ const overrideRaw = byRigor && typeof byRigor[rigorKey] === 'string' ? byRigor[rigorKey].trim() : '';
107
+ if (overrideRaw) {
108
+ return { rawModel: overrideRaw, source: 'dashboard-by-rigor', label: `dashboard-models.json dispatchModelByRigor.${rigorKey}`, rigorKey };
109
+ }
110
+ // 3. Default for every rigor: the dashboard dispatchModel, unchanged fallback
111
+ // ('claude-sonnet-4-6', mirrors DEFAULT_DISPATCH_MODEL in dashboard/src/lib/models.ts).
112
+ const rawModel = (models && typeof models.dispatchModel === 'string' && models.dispatchModel) || 'claude-sonnet-4-6';
113
+ return { rawModel, source: 'dashboard', label: 'dashboard-models.json dispatchModel', rigorKey };
114
+ }
115
+
116
+ // ─────────────────────────────────────────
117
+ // -----------------------------------------
118
+ // M1 (TASK_1758): Dispatch-time scope gate + resource lease
119
+ // Spec: dev/MULTI_ANSUZ_SPEC.md §2.3 + §2.5
120
+ // -----------------------------------------
121
+
122
+ function normalizeScopePath(p_) {
123
+ if (!p_) return '';
124
+ let s = String(p_).split(String.fromCharCode(92)).join("/").trim();
125
+ if (process.platform === 'win32') s = s.toLowerCase();
126
+ return s;
127
+ }
128
+
129
+ function pathsCollide(a, b) {
130
+ const na = normalizeScopePath(a);
131
+ const nb = normalizeScopePath(b);
132
+ if (!na || !nb) return false;
133
+ if (na === nb) return true;
134
+ const naSlash = na.endsWith('/') ? na : na + '/';
135
+ const nbSlash = nb.endsWith('/') ? nb : nb + '/';
136
+ if (nb.startsWith(naSlash)) return true;
137
+ if (na.startsWith(nbSlash)) return true;
138
+ return false;
139
+ }
140
+
141
+ function _dispPidAlive(pid) {
142
+ if (!pid || pid <= 0) return false;
143
+ try { process.kill(pid, 0); return true; }
144
+ catch (e) { if (e.code === 'EPERM') return true; return false; }
145
+ }
146
+
147
+ // TASK_2263: identity + provenance. source 'hmap' = resolved via this process's own
148
+ // CLAUDE_CODE_SESSION_ID (provable); 'current_stream' = the singleton file that may
149
+ // name ANOTHER live session (unprovable, best-effort label only).
150
+ function _getOwnSessionId(projectRoot) { return _resolveOwnSession(projectRoot).id; }
151
+
152
+ // TASK_2265: id usable as "self" for filtering OTHER sessions' leases/claims and as an
153
+ // authoritative owner in written records. Only hmap-proven identity qualifies; the
154
+ // current_stream singleton may name a foreign live session, so it yields null (callers
155
+ // fail closed: nothing is treated as self, writers fall back to the 'unknown' sentinel).
156
+ function _getProvenSessionId(projectRoot) {
157
+ var o = _resolveOwnSession(projectRoot);
158
+ return o.source === 'hmap' ? o.id : null;
159
+ }
160
+
161
+ function _resolveOwnSession(projectRoot) {
162
+ // TASK_1764 AMEND: use CLAUDE_CODE_SESSION_ID (= conversation UUID, stable across compact/resume).
163
+ // CLAUDE_SESSION_ID does not exist; CLAUDE_CODE_SESSION_ID is the correct env variable.
164
+ // hmap key is now convId (transcript_path basename = conversation id), consistent with hooks.
165
+ try {
166
+ var sessId = process.env.CLAUDE_CODE_SESSION_ID;
167
+ if (sessId) {
168
+ var hmapF = require('path').join(projectRoot, '.kenaz', 'specialist', 'sessions', 'hmap_' + sessId + '.json');
169
+ try {
170
+ var hmap = JSON.parse(require('fs').readFileSync(hmapF, 'utf8'));
171
+ if (hmap && hmap.boot_sid) return { id: hmap.boot_sid, source: 'hmap' };
172
+ } catch (_e2) {}
173
+ }
174
+ // Fallback: current_stream.json (solo session, headless, or hmap not yet written)
175
+ var sf = require('path').join(projectRoot, '.kenaz', 'specialist', 'current_stream.json');
176
+ var parsed = JSON.parse(require('fs').readFileSync(sf, 'utf8'));
177
+ var fid = (parsed && parsed.session_id) || null;
178
+ return { id: fid, source: fid ? 'current_stream' : null };
179
+ } catch (_e) { return { id: null, source: null }; }
180
+ }
181
+
182
+ // TASK_1863: own conversation id — the STABLE self-identity anchor (TASK_1764;
183
+ // ash rune_cfc898ca: session ids rotate/alias, conversation id does not).
184
+ // Env CLAUDE_CODE_SESSION_ID (= transcript basename, stable across compact/resume)
185
+ // only (TASK_2281: the current_stream.json conversation_id is NOT trusted — singleton).
186
+ function _getOwnConversationId(projectRoot) {
187
+ try {
188
+ var envId = process.env.CLAUDE_CODE_SESSION_ID;
189
+ // TASK_2281: no current_stream fallback — the singleton may name another live
190
+ // conversation; unproven identity fails closed (null = no marker is "ours").
191
+ return envId || null;
192
+ } catch (_e) { return null; }
193
+ }
194
+
195
+ // TASK_1787/2281: is this claim marker ours? Anchor: owner_conversation_id; fallback
196
+ // owner_session when the marker has no conv id; never owner_pid. (headless auto-claim guard)
197
+ function _isOwnClaimMarker(marker, projectRoot) {
198
+ // TASK_2281: proven identity only (env conv id / hmap). The current_stream.json singleton
199
+ // may name another live session -> unproven -> never "ours" (fail closed).
200
+ if (!marker) return false;
201
+ if (marker.owner_conversation_id) {
202
+ var conv = _getOwnConversationId(projectRoot);
203
+ return !!conv && marker.owner_conversation_id === conv;
204
+ }
205
+ var sid = _getProvenSessionId(projectRoot);
206
+ return !!sid && !!marker.owner_session && marker.owner_session === sid;
207
+ }
208
+
209
+ // TASK_1863: late-failure claim rollback — the same guarantee TASK_1833 gave
210
+ // resource leases. dispatch.js does not WRITE claim markers (task-api does, on
211
+ // the chain's pre-claim / move→active), but a dispatch that fails AFTER the
212
+ // scope gate must not leave that marker behind: the leaked marker blocks the
213
+ // same conversation's retry when its owner_session is a live alias (measured
214
+ // 2026-08-13: claim_TASK_1861 owned by ghost stream-D blocked the retry with
215
+ // '<same-task>' until hand-deleted), and blocks every other session for the
216
+ // full 8h liveness window if this session dies. Adoption is strictly
217
+ // self-scoped: only a marker provably owned by this session OR this
218
+ // conversation is ever released. Foreign markers are never touched — orphan
219
+ // arbitration stays in task-api (never auto-steal, rune_0378754d).
220
+ function adoptSelfClaimMarker(taskId, projectRoot, ownSessionId) {
221
+ const adoption = { markerPath: null, adopted: false };
222
+ if (!taskId || !/^TASK_/.test(taskId)) return adoption;
223
+ adoption.markerPath = require('path').join(projectRoot, '.kenaz', 'locks', 'claim_' + taskId + '.json');
224
+ let mk = null;
225
+ try { mk = JSON.parse(require('fs').readFileSync(adoption.markerPath, 'utf8')); } catch (_e) { return adoption; }
226
+ if (!mk) return adoption;
227
+ const ownConvId = _getOwnConversationId(projectRoot);
228
+ adoption.adopted =
229
+ (!!ownSessionId && mk.owner_session === ownSessionId) ||
230
+ (!!ownConvId && mk.owner_conversation_id === ownConvId);
231
+ return adoption;
232
+ }
233
+
234
+ function releaseAdoptedClaimMarker(adoption) {
235
+ if (!adoption || !adoption.adopted || !adoption.markerPath) return;
236
+ try { require('fs').unlinkSync(adoption.markerPath); } catch (_e) { /* already gone */ }
237
+ }
238
+
239
+ /**
240
+ * TASK_1859: explicit release for the serial dispatch lock (utils.dispatchLockPath).
241
+ * The previous release contract was "delete the lock file" — structurally
242
+ * unexecutable in orchestrator environments that deny Bash(rm *) (deny wins
243
+ * over every allow), leaving 60min staleness as the only exit. This gives the
244
+ * lock a first-class release interface: `--release-lock` on this CLI.
245
+ *
246
+ * Ownership rule (never silent): a release without --force requires PROVABLE
247
+ * same-session ownership — both the holder's sessionId and our own resolved
248
+ * session must exist, neither may be the 'unknown' sentinel (locks are written
249
+ * with sessionId `_getOwnSessionId(ROOT) || 'unknown'`), and they must match.
250
+ * Any unprovable case (holder corrupt, holder sessionId missing/'unknown',
251
+ * own session unresolvable) REFUSES and requires --force — an 'unknown' holder
252
+ * is exactly the case where we cannot know whose live agent we would unlock.
253
+ *
254
+ * Deliberately NOT pid-based: pid:null is the designed holder shape (the
255
+ * dispatch CLI exits right after emitting params — its pid proves nothing
256
+ * about the agent's liveness). Staleness info comes from the single authority
257
+ * utils.dispatchLockStaleness and is surfaced for the operator, but this
258
+ * function never auto-releases on staleness — the next tryAcquireDispatchLock
259
+ * already breaks stale locks; release stays an explicit human/orchestrator act.
260
+ *
261
+ * @param {object} [opts]
262
+ * @param {string|null} [opts.projectPath] - target project (lock key), null = core
263
+ * @param {boolean} [opts.force] - allow releasing a lock we cannot prove we own
264
+ * @param {string|null} [opts.ownSessionId] - test injection point ONLY; when the
265
+ * key is absent the real _getOwnSessionId(ROOT) is used (same source as the
266
+ * lock writer). Explicit null models "own session resolution failed".
267
+ * @returns {{ released: boolean, existed: boolean, lockFile: string,
268
+ * holder: object|null, staleness: object|null, ownSessionId: string|null,
269
+ * reason: string }}
270
+ */
271
+ function releaseDispatchLock(opts = {}) {
272
+ const { projectPath = null, force = false } = opts;
273
+ const lockFile = dispatchLockPath(projectPath);
274
+ // TASK_2263: an identity from the singleton current_stream.json fallback can name
275
+ // another live session, so it is not ownership proof (injected ids count as proven).
276
+ const _own = ('ownSessionId' in opts) ? { id: opts.ownSessionId, source: 'injected' } : _resolveOwnSession(ROOT);
277
+ const ownSessionId = _own.id;
278
+ let raw = null;
279
+ try { raw = fs.readFileSync(lockFile, 'utf8'); }
280
+ catch (e) {
281
+ if (e.code === 'ENOENT') {
282
+ return { released: false, existed: false, lockFile, holder: null, staleness: null, ownSessionId, reason: 'not-held' };
283
+ }
284
+ return { released: false, existed: true, lockFile, holder: null, staleness: null, ownSessionId, reason: 'read-error: ' + e.message };
285
+ }
286
+ let holder = null;
287
+ try { holder = JSON.parse(raw); } catch { /* corrupt — unprovable ownership below */ }
288
+ const staleness = dispatchLockStaleness(holder);
289
+ const holderSession = holder && typeof holder.sessionId === 'string' && holder.sessionId.trim() ? holder.sessionId.trim() : null;
290
+ // Defined-behavior ladder for unprovable ownership (acceptance: never silent):
291
+ let refusal = null;
292
+ if (!holder) refusal = 'holder-unreadable';
293
+ else if (!holderSession || holderSession === 'unknown') refusal = 'holder-session-unknown';
294
+ else if (!ownSessionId) refusal = 'own-session-unresolved';
295
+ else if (holderSession !== ownSessionId) refusal = 'session-mismatch';
296
+ else if (_own.source === 'current_stream') refusal = 'own-session-unproven';
297
+ if (refusal && !force) {
298
+ return { released: false, existed: true, lockFile, holder, staleness, ownSessionId, reason: refusal };
299
+ }
300
+ try { fs.unlinkSync(lockFile); }
301
+ catch (e) {
302
+ if (e.code === 'ENOENT') {
303
+ // Racing releaser/breaker got there first — the desired end state holds.
304
+ return { released: false, existed: false, lockFile, holder, staleness, ownSessionId, reason: 'not-held' };
305
+ }
306
+ return { released: false, existed: true, lockFile, holder, staleness, ownSessionId, reason: 'unlink-failed: ' + e.message };
307
+ }
308
+ return { released: true, existed: true, lockFile, holder, staleness, ownSessionId, reason: refusal ? 'forced (' + refusal + ')' : 'own-session' };
309
+ }
310
+
311
+ function checkDispatchScopeGate(targetScopePaths, projectRoot, currentSessionId, force, targetTaskId) {
312
+ targetScopePaths = targetScopePaths || [];
313
+ // TASK_1767: empty scope_paths must not bypass the TASK_1764 same-task-id guard --
314
+ // early-return only when there is neither scope to compare nor a target task id.
315
+ if (targetScopePaths.length === 0 && !targetTaskId) return { blocked: false, collisions: [] };
316
+ let readAllLeases, isPidAlive, isSessionLive;
317
+ try {
318
+ const sl = require(require('path').join(projectRoot, '.specialist', 'tools', 'stream-lease.js'));
319
+ readAllLeases = sl.readAllLeases;
320
+ isPidAlive = sl.isPidAlive;
321
+ isSessionLive = sl.isSessionLive;
322
+ } catch (_e) { return { blocked: false, collisions: [] }; }
323
+ const locksDir = require('path').join(projectRoot, '.kenaz', 'locks');
324
+ const fsL = require('fs');
325
+ const pathMod = require('path');
326
+ const _ownConvForLease = process.env.CLAUDE_CODE_SESSION_ID || null;
327
+ const leases = readAllLeases().filter(function(l) {
328
+ // M1.5 (TASK_1761): use isSessionLive (pid-alive OR heartbeat-fresh) not just isPidAlive
329
+ // TASK_2265: own conversation's lease is self even when session identity is unproven
330
+ // (currentSessionId null); a foreign conversation's lease never is.
331
+ if (_ownConvForLease && l.conversation_id === _ownConvForLease) return false;
332
+ return l.session_id !== currentSessionId && (isSessionLive ? isSessionLive(l) : isPidAlive(l.pid));
333
+ });
334
+ if (leases.length === 0) return { blocked: false, collisions: [] };
335
+ // TASK_1863: self-recognition anchor for claim markers. A marker whose
336
+ // owner_conversation_id matches OUR conversation is a self-claim recorded
337
+ // under a session ALIAS (e.g. a boot ghost lease clobbered current_stream.json
338
+ // before task-api attributed the claim) — never a foreign stream. Skipping it
339
+ // lets a retry proceed after a mid-dispatch failure leaked our own claim.
340
+ // Foreign claims (different conversation, or no conversation id) still block.
341
+ const ownConvId = _getOwnConversationId(projectRoot);
342
+ const collisions = [];
343
+ for (const lease of leases) {
344
+ const claimedTaskIds = [];
345
+ try {
346
+ for (const lf of fsL.readdirSync(locksDir)) {
347
+ if (!lf.startsWith('claim_TASK_') || !lf.endsWith('.json')) continue;
348
+ try {
349
+ const mk = JSON.parse(fsL.readFileSync(pathMod.join(locksDir, lf), 'utf8'));
350
+ if (ownConvId && mk.owner_conversation_id === ownConvId) continue; // TASK_1863: self-claim via alias
351
+ // M1.5 (TASK_1761): liveness via owner SESSION lease, not just owner_pid
352
+ if (mk.owner_session === lease.session_id) {
353
+ const mkLive = isSessionLive ? isSessionLive(lease) : _dispPidAlive(mk.owner_pid);
354
+ if (mkLive) claimedTaskIds.push(lf.slice(6, -5));
355
+ }
356
+ } catch (_e2) {}
357
+ }
358
+ } catch (_e3) {}
359
+ // TASK_1764: same-task-id guard -- if another live stream already claimed this task, block.
360
+ if (targetTaskId && claimedTaskIds.indexOf(targetTaskId) !== -1) {
361
+ collisions.push({ stream_label: lease.label || lease.session_id, task_id: targetTaskId, paths: ['<same-task>'], sameTaskId: true });
362
+ }
363
+ for (const cid of claimedTaskIds) {
364
+ const claimedSP = [];
365
+ try {
366
+ const activeDir = pathMod.join(projectRoot, '.kenaz', 'tasks', 'active');
367
+ for (const e of fsL.readdirSync(activeDir)) {
368
+ if (e.startsWith(cid + '_') || e.startsWith(cid + '.')) {
369
+ const raw = fsL.readFileSync(pathMod.join(activeDir, e), 'utf8');
370
+ const spIdx = raw.indexOf('scope_paths:');
371
+ if (spIdx !== -1) {
372
+ const itemLines = raw.slice(spIdx + 12).split(String.fromCharCode(10));
373
+ for (const il of itemLines) {
374
+ const trimmed = il.trim();
375
+ if (!trimmed.startsWith('-')) break;
376
+ const val = trimmed.slice(1).trim().replace(/^['"]|['"]$/g, '');
377
+ if (val) claimedSP.push(val);
378
+ }
379
+ }
380
+ break;
381
+ }
382
+ }
383
+ } catch (_e4) {}
384
+ const cp = targetScopePaths.filter(function(tp) {
385
+ return claimedSP.some(function(csp) { return pathsCollide(tp, csp); });
386
+ });
387
+ if (cp.length > 0) {
388
+ collisions.push({ stream_label: lease.label || lease.session_id, task_id: cid, paths: cp });
389
+ }
390
+ }
391
+ }
392
+ return { blocked: collisions.length > 0 && !force, collisions: collisions };
393
+ }
394
+
395
+ function acquireResourceLocks(resources, projectRoot, sessionId, taskId) {
396
+ if (!resources || resources.length === 0) return { acquired: [], failed: [] };
397
+ const locksDir = require('path').join(projectRoot, '.kenaz', 'locks');
398
+ const fsL = require('fs');
399
+ const pathMod = require('path');
400
+ try { fsL.mkdirSync(locksDir, { recursive: true }); } catch (_e) {}
401
+ const acquired = [];
402
+ const failed = [];
403
+ for (const name of resources) {
404
+ const lp = pathMod.join(locksDir, 'resource_' + name + '.lock');
405
+ const content = JSON.stringify({
406
+ owner_session: sessionId || 'unknown',
407
+ owner_pid: process.pid,
408
+ task_id: taskId || null,
409
+ acquired_at: new Date().toISOString()
410
+ }, null, 2);
411
+ try { fsL.writeFileSync(lp, content, { flag: 'wx', encoding: 'utf8' }); acquired.push(name); }
412
+ catch (err) {
413
+ if (err.code !== 'EEXIST') throw err;
414
+ let holder = null;
415
+ try { holder = JSON.parse(fsL.readFileSync(lp, 'utf8')); } catch (_e2) {}
416
+ if (holder && _dispPidAlive(holder.owner_pid)) {
417
+ failed.push({ name: name, holder: holder });
418
+ } else {
419
+ process.stderr.write('WARNING: resource ' + name + ' ORPHAN lock (pid=' +
420
+ (holder && holder.owner_pid) + ' dead). Release: node .specialist/tools/stream-lease.js resource-release --name=' + name + String.fromCharCode(10));
421
+ failed.push({ name: name, holder: holder, orphan: true });
422
+ }
423
+ }
424
+ }
425
+ return { acquired: acquired, failed: failed };
426
+ }
427
+
428
+ function releaseResourceLocks(resources, projectRoot) {
429
+ if (!resources || resources.length === 0) return;
430
+ const locksDir = require('path').join(projectRoot, '.kenaz', 'locks');
431
+ for (const name of resources) {
432
+ try { require('fs').unlinkSync(require('path').join(locksDir, 'resource_' + name + '.lock')); } catch (_e) {}
433
+ }
434
+ }
435
+ // TASK_1710: path comparison helper — normalises separators and drive-letter case on Windows
436
+ // so that forward-slash paths (C:/...) match backslash paths (C:...) and mixed-case drives.
437
+ // Uses path.resolve (canonicalises separators) + toLowerCase on win32 + path.relative === ''
438
+ // to confirm identity (also handles trailing-slash edge cases).
439
+ function samePath(a, b) {
440
+ if (!a || !b) return false;
441
+ let ra = path.resolve(a);
442
+ let rb = path.resolve(b);
443
+ if (process.platform === 'win32') {
444
+ ra = ra.toLowerCase();
445
+ rb = rb.toLowerCase();
446
+ }
447
+ return path.relative(ra, rb) === '';
448
+ }
449
+
450
+ // ─────────────────────────────────────────
451
+ // Yggdrasil 廣播(lazy load, fire-and-forget)
452
+ // ─────────────────────────────────────────
453
+
454
+ let _supabaseClient = null;
455
+ let _taskSync = null;
456
+ let _commitSync = null;
457
+ function getSupabaseClient(projectPath) {
458
+ if (_supabaseClient === undefined) return null;
459
+ if (!_supabaseClient) try { _supabaseClient = require('./supabase-client'); } catch { _supabaseClient = undefined; return null; }
460
+ return _supabaseClient.getClient(projectPath);
461
+ }
462
+ function getTaskSync() {
463
+ if (_taskSync === undefined) return null;
464
+ if (!_taskSync) try { _taskSync = require('./task-sync'); } catch { _taskSync = undefined; return null; }
465
+ return _taskSync;
466
+ }
467
+ function getCommitSync() {
468
+ if (_commitSync === undefined) return null;
469
+ if (!_commitSync) try { _commitSync = require('./commit-sync'); } catch { _commitSync = undefined; return null; }
470
+ return _commitSync;
471
+ }
472
+
473
+ /**
474
+ * 同步 commit 到 kenaz_commits。
475
+ * 回傳 Promise(await 時確保完成,或 fire-and-forget)。
476
+ */
477
+ function syncCommit(taskId, projectPath) {
478
+ try {
479
+ const cs = getCommitSync();
480
+ if (!cs) return Promise.resolve();
481
+ return cs.syncLatestCommit({ taskId, projectPath }).catch(() => {});
482
+ } catch { return Promise.resolve(); }
483
+ }
484
+
485
+ /**
486
+ * 廣播 kenaz_status。
487
+ * 回傳 Promise — caller 可 await 確保完成(cleanup 場景),
488
+ * 或 fire-and-forget(上線廣播場景)。
489
+ */
490
+ function broadcastStatus(projectPath, updates) {
491
+ try {
492
+ const sb = getSupabaseClient(projectPath);
493
+ if (!sb) return Promise.resolve();
494
+ const { client, config } = sb;
495
+ const ts = getTaskSync();
496
+ const project = ts?.resolveProjectName?.(projectPath || ROOT) || path.basename(ROOT);
497
+ return client.from('kenaz_status').upsert({
498
+ node_name: config.node_name,
499
+ project,
500
+ ...updates,
501
+ }, { onConflict: 'node_name,project' }).then(() => {}).catch(() => {});
502
+ } catch { return Promise.resolve(); }
503
+ }
504
+
505
+ // ─────────────────────────────────────────
506
+ // Active dispatch registry(Dashboard Agent Monitor 用)
507
+ // ─────────────────────────────────────────
508
+
509
+ const ACTIVE_DISPATCH_FILE = path.join(ROOT, '.formation', '.active-dispatches.json');
510
+
511
+ /**
512
+ * TASK_1833: THE single isolation-routing decision for a dispatch. Consumed by
513
+ * the real sub-agent path — do not copy the check:
514
+ * - getSubagentDispatchParams (real sub-agent routing — ENFORCED)
515
+ * History: the cross-project check has been duplicated/decorative twice before
516
+ * (TASK_1672 omitted isolation on the real path; the old selectDispatchPath
517
+ * cross_project_cwd guard never influenced routing). Third recurrence of
518
+ * copy-the-check documented in rune_9fe1bdb57d834750ac443b1d7f09e965 /
519
+ * rune_eb53038640e246dea32764f89b18bfa1's point (5) — call this, never copy it.
520
+ * Modes:
521
+ * agent_tool_worktree — same-project: Agent tool isolation:'worktree'
522
+ * (harness-managed worktree in the conversation repo).
523
+ * target_repo_worktree — cross-project + useWorktree: dispatcher pre-creates
524
+ * a worktree INSIDE the target repo (the Agent tool's
525
+ * own worktree derives from the conversation cwd repo
526
+ * and cannot isolate another repo — TASK_1672/1593).
527
+ * serial_lock — cross-project + !useWorktree (single-editor-bound
528
+ * projects like Unity): shared working tree, WRITES
529
+ * SERIALIZED via the per-project dispatch lock.
530
+ * direct_no_git — cross-project target WITHOUT a .git dir: the entire
531
+ * hazard class this decision guards (index.lock
532
+ * contention, commits silently vanishing, worktrees)
533
+ * is git-level and cannot occur — keep the plain
534
+ * direct-write behavior (no worktree, no lock).
535
+ * TASK_2176: also surfaces `verifyOffline` (the project's .kenaz/project.yaml
536
+ * `verify_offline: <command>` key, or null) regardless of isolation mode —
537
+ * same-project dispatches can declare it too, not only cross-project ones.
538
+ * The isolation decision itself (worktree vs serial_lock) is UNCHANGED by
539
+ * this key; verifyOffline only rides along so the caller can (a) hand the
540
+ * worktree agent a non-authoritative self-check instruction and (b) know,
541
+ * at landing time, that the authoritative run must happen serialized on the
542
+ * main tree (see verify-and-land.js stepVerifyOffline — a SEPARATE lock from
543
+ * the serial_lock dispatch lock above, scoped to just the verify command).
544
+ * @param {object} opts
545
+ * @param {string|null} opts.projectPath
546
+ * @param {boolean|null} [opts.useWorktreeOverride] - dispatch-time toggle (CLI --use-worktree)
547
+ * @returns {{ isCrossProject: boolean, mode: string, useWorktree: boolean, source: string, verifyOffline: string|null }}
548
+ */
549
+ function resolveDispatchIsolation({ projectPath = null, useWorktreeOverride = null } = {}) {
550
+ // TASK_1710 semantics: samePath, not raw string compare (separator/case).
551
+ const isCrossProject = !!(projectPath && !samePath(projectPath, ROOT));
552
+ const verifyOffline = getVerifyOfflineCommand(projectPath);
553
+ if (!isCrossProject) {
554
+ return { isCrossProject, mode: 'agent_tool_worktree', useWorktree: true, source: 'same-project', verifyOffline };
555
+ }
556
+ if (!fs.existsSync(path.join(projectPath, '.git'))) {
557
+ return { isCrossProject, mode: 'direct_no_git', useWorktree: false, source: 'no-git-target', verifyOffline };
558
+ }
559
+ const d = resolveWorktreeDecision(projectPath, useWorktreeOverride);
560
+ return {
561
+ isCrossProject,
562
+ mode: d.useWorktree ? 'target_repo_worktree' : 'serial_lock',
563
+ useWorktree: d.useWorktree,
564
+ source: d.source,
565
+ verifyOffline,
566
+ };
567
+ }
568
+
569
+ function readActiveDispatches() {
570
+ try {
571
+ if (fs.existsSync(ACTIVE_DISPATCH_FILE)) {
572
+ return JSON.parse(fs.readFileSync(ACTIVE_DISPATCH_FILE, 'utf-8'));
573
+ }
574
+ } catch { /* corrupted file */ }
575
+ return [];
576
+ }
577
+
578
+ function writeActiveDispatches(list) {
579
+ try {
580
+ fs.writeFileSync(ACTIVE_DISPATCH_FILE, JSON.stringify(list, null, 2));
581
+ } catch { /* ignore */ }
582
+ }
583
+
584
+ function registerDispatch({ sessionId, logPath, taskId, formation, projectPath: pp }) {
585
+ const list = readActiveDispatches();
586
+ const nextEntry = {
587
+ sessionId,
588
+ logPath,
589
+ taskId,
590
+ formation,
591
+ startedAt: new Date().toISOString(),
592
+ projectPath: pp || null,
593
+ };
594
+ const existingIndex = list.findIndex(d => d.sessionId === sessionId);
595
+ if (existingIndex >= 0) {
596
+ const mergedEntry = {
597
+ ...list[existingIndex],
598
+ startedAt: list[existingIndex].startedAt || nextEntry.startedAt,
599
+ };
600
+ for (const [key, value] of Object.entries(nextEntry)) {
601
+ if (key === 'startedAt') continue;
602
+ if (value !== null && value !== undefined) {
603
+ mergedEntry[key] = value;
604
+ }
605
+ }
606
+ list[existingIndex] = mergedEntry;
607
+ } else {
608
+ list.push(nextEntry);
609
+ }
610
+ writeActiveDispatches(list);
611
+ }
612
+
613
+ function unregisterDispatch(sessionId) {
614
+ const list = readActiveDispatches().filter(d => d.sessionId !== sessionId);
615
+ if (list.length === 0) {
616
+ try { fs.unlinkSync(ACTIVE_DISPATCH_FILE); } catch { /* ignore */ }
617
+ } else {
618
+ writeActiveDispatches(list);
619
+ }
620
+ }
621
+
622
+ // ─────────────────────────────────────────
623
+ // Cortex Context 注入(dispatch 前自動注入相關檔案摘要)
624
+ // ─────────────────────────────────────────
625
+
626
+ /**
627
+ * 從 scope_paths 提取相關檔案的簡要 context。
628
+ * Cortex 不可用時的 graceful fallback — 直接讀取檔案頭。
629
+ *
630
+ * 行為契約(TASK_1822 確認,回應外部 bug 回報的求證):
631
+ * - 目錄條目:**完全不展開**,直接跳過(不 inline 其下任何檔案)。
632
+ * scope_paths 全是目錄時,prompt 只會出現路徑清單、不會有本區段內容。
633
+ * - 檔案條目:inline 前 30 行,且整個 preview 另受位元組上限
634
+ * (CORTEX_PREVIEW_MAX_BYTES)保護 — 30 是「行數」上限不是「位元組」
635
+ * 上限,單行極長的檔案(.min.js、無換行大檔)曾借道灌入數百 KB;
636
+ * 超過位元組上限會截斷並明確標註。
637
+ * - 二進位檔(開頭 sniff 區含 NUL 位元組):跳過內容但保留區段標題
638
+ * 註明已跳過 — 靜默跳過會讓使用者誤以為內容已被看過。
639
+ * 偵測方式選 NUL-byte sniff 而非副檔名白名單:零依賴、不需維護
640
+ * 清單,且對無副檔名/罕見副檔名的二進位一樣有效(YAGNI)。
641
+ *
642
+ * @param {string[]} scopePaths - 任務的 scope_paths
643
+ * @param {string|null} projectPath - 子專案路徑
644
+ * @returns {string} 注入到 prompt 的 context 文字,空字串表示無可用 context
645
+ */
646
+ const CORTEX_PREVIEW_MAX_LINES = 30;
647
+ // thrift: 8KB 對 30 行綽綽有餘(平均 273 bytes/行);若未來要 inline 更多行再調
648
+ const CORTEX_PREVIEW_MAX_BYTES = 8 * 1024;
649
+ const CORTEX_BINARY_SNIFF_BYTES = 8 * 1024;
650
+
651
+ /**
652
+ * 讀取檔案開頭 sniff 區,含 NUL 位元組即視為二進位。
653
+ * PNG/JPEG/EXE 等格式的頭部幾乎必含 0x00;UTF-8 文字合法內容不含 NUL。
654
+ */
655
+ function isBinaryFile(fullPath) {
656
+ const fd = fs.openSync(fullPath, 'r');
657
+ try {
658
+ const buf = Buffer.alloc(CORTEX_BINARY_SNIFF_BYTES);
659
+ const bytesRead = fs.readSync(fd, buf, 0, buf.length, 0);
660
+ return buf.subarray(0, bytesRead).includes(0);
661
+ } finally {
662
+ fs.closeSync(fd);
663
+ }
664
+ }
665
+
666
+ function buildCortexContext(scopePaths, projectPath) {
667
+ if (!scopePaths || scopePaths.length === 0) return '';
668
+
669
+ const projectRoot = projectPath || ROOT;
670
+ const sections = [];
671
+
672
+ for (const sp of scopePaths) {
673
+ const fullPath = path.resolve(projectRoot, sp);
674
+ if (!fs.existsSync(fullPath)) continue;
675
+
676
+ try {
677
+ const stat = fs.statSync(fullPath);
678
+ if (stat.isDirectory()) continue;
679
+
680
+ if (isBinaryFile(fullPath)) {
681
+ // 註明已跳過而非靜默略過 — 讓 agent 知道這個 scope 檔案沒被預覽
682
+ sections.push(`### ${sp} (binary file, ${stat.size} bytes — content preview skipped)`);
683
+ continue;
684
+ }
685
+
686
+ // 只讀前 CORTEX_PREVIEW_MAX_BYTES(+1) 位元組(經 fd),不整檔載入記憶體
687
+ let head;
688
+ {
689
+ const fd = fs.openSync(fullPath, 'r');
690
+ try {
691
+ const buf = Buffer.alloc(CORTEX_PREVIEW_MAX_BYTES + 1);
692
+ head = buf.subarray(0, fs.readSync(fd, buf, 0, buf.length, 0));
693
+ } finally {
694
+ fs.closeSync(fd);
695
+ }
696
+ }
697
+ const partial = head.length > CORTEX_PREVIEW_MAX_BYTES; // 檔案超過上限,總行數未知
698
+ const content = head.toString('utf-8');
699
+ const lines = content.split('\n');
700
+ if (partial && lines.length > 1) lines.pop(); // 丟掉被截斷的最後一行
701
+ let preview = lines.slice(0, CORTEX_PREVIEW_MAX_LINES).join('\n');
702
+ const totalLines = lines.length;
703
+
704
+ // 位元組上限:防單行極長檔案(.min.js、無換行大檔)繞過行數上限
705
+ let byteTruncated = false;
706
+ if (Buffer.byteLength(preview, 'utf-8') > CORTEX_PREVIEW_MAX_BYTES) {
707
+ preview = Buffer.from(preview, 'utf-8')
708
+ .subarray(0, CORTEX_PREVIEW_MAX_BYTES)
709
+ .toString('utf-8')
710
+ .replace(/�+$/, ''); // 去掉截斷產生的不完整 multibyte 殘片
711
+ byteTruncated = true;
712
+ }
713
+
714
+ const marker = (byteTruncated || (partial && totalLines <= CORTEX_PREVIEW_MAX_LINES))
715
+ ? `\n... (truncated at ${CORTEX_PREVIEW_MAX_BYTES} bytes)`
716
+ : (totalLines > CORTEX_PREVIEW_MAX_LINES ? '\n... (truncated)' : '');
717
+
718
+ // partial 時只讀了開頭,行數僅為下限,故標 N+
719
+ sections.push(
720
+ `### ${sp} (${totalLines}${partial ? '+' : ''} lines)\n` +
721
+ '```\n' + preview + marker + '\n```'
722
+ );
723
+ } catch (err) {
724
+ // 註明已跳過而非靜默略過(與二進位分支一致)
725
+ sections.push(`### ${sp} (unreadable - preview skipped: ${(err && err.code) || 'error'})`);
726
+ }
727
+ }
728
+
729
+ if (sections.length === 0) return '';
730
+
731
+ return (
732
+ '\n## Cortex Context (Related Files Preview)\n' +
733
+ 'The following files are in your scope. Review them before making changes.\n\n' +
734
+ sections.join('\n\n')
735
+ );
736
+ }
737
+
738
+ // ─────────────────────────────────────────
739
+ // TASK_1998 R1: dispatch-prompt telemetry
740
+ // ─────────────────────────────────────────
741
+
742
+ /**
743
+ * Append one structured JSONL line to .kenaz/specialist/dispatch_prompt_stats.jsonl —
744
+ * one per sub-agent dispatch (getSubagentDispatchParams). Mirrors
745
+ * post-complete.js's appendPhase9OutcomeLog: same project-pinning
746
+ * (projectPath || ROOT), same best-effort append, never throws.
747
+ *
748
+ * Format: { ts, task_id, rigor, complexity, formation, prompt_bytes, sections: [{title, bytes}], model, model_source }
749
+ * dev/scripts/dispatch-stats.js reads this to print p50/p90 prompt_bytes per (rigor, complexity).
750
+ * model_source (TASK_1998 R3): 'dashboard'|'dashboard-by-rigor'|'cli' — which
751
+ * layer of resolveDispatchModelForRigor() picked `model`. Optional (older
752
+ * callers, and the non-subagent path, omit it — reader must tolerate absence).
753
+ * complexity (TASK_1998 two-axis policy): the normalized 'simple'|'medium'|'complex'
754
+ * CONTEXT-volume key (extractComplexity() default). Optional for older readers.
755
+ */
756
+ function appendDispatchPromptStats({ taskId, rigor, complexity, formation, promptText, model, modelSource, projectPath }) {
757
+ const root = projectPath || ROOT;
758
+ const dir = path.join(root, '.kenaz', 'specialist');
759
+ try {
760
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
761
+ const line = JSON.stringify({
762
+ ts: new Date().toISOString(),
763
+ task_id: taskId || null,
764
+ rigor: rigor || 'medium',
765
+ complexity: complexity || 'medium',
766
+ formation,
767
+ prompt_bytes: Buffer.byteLength(promptText || '', 'utf-8'),
768
+ sections: splitPromptSections(promptText || ''),
769
+ model,
770
+ model_source: modelSource || null,
771
+ });
772
+ fs.appendFileSync(path.join(dir, 'dispatch_prompt_stats.jsonl'), line + '\n', 'utf8');
773
+ } catch { /* best-effort — telemetry must never block dispatch */ }
774
+ }
775
+
776
+ // ─────────────────────────────────────────
777
+ // 依賴預檢
778
+ // ─────────────────────────────────────────
779
+
780
+ /**
781
+ * 檢查任務的依賴是否都已完成。
782
+ * 掃描 done/ + archived/ + completed/。
783
+ *
784
+ * @param {string} taskData - JSON or YAML 任務文本
785
+ * @param {string|null} projectPath - 子專案路徑(null = core)
786
+ * @returns {{ blocked: boolean, unmet: string[] }}
787
+ */
788
+ function checkDependencies(taskData, projectPath) {
789
+ let deps = [];
790
+ try {
791
+ const parsed = JSON.parse(taskData);
792
+ deps = parsed.dependencies || [];
793
+ } catch {
794
+ // Try YAML key extraction as fallback
795
+ const match = taskData.match(/^dependencies:\s*\n((?:\s+-\s+\S+\n?)+)/m);
796
+ if (match) {
797
+ deps = match[1].split('\n')
798
+ .map(l => l.trim().replace(/^-\s*/, ''))
799
+ .filter(Boolean);
800
+ }
801
+ }
802
+
803
+ if (deps.length === 0) return { blocked: false, unmet: [] };
804
+
805
+ // Collect completed task IDs from all relevant directories
806
+ const completedIds = new Set();
807
+ const blockedIds = new Set();
808
+ const scanDir = (dir, bucket) => {
809
+ if (!dir || !fs.existsSync(dir)) return;
810
+ try {
811
+ for (const f of fs.readdirSync(dir)) {
812
+ if (f.startsWith('TASK_')) {
813
+ const base = f.replace(/\.yaml$/, '');
814
+ bucket.add(base.split('_').slice(0, 2).join('_'));
815
+ }
816
+ }
817
+ } catch { /* ignore */ }
818
+ };
819
+
820
+ const projectRoot = projectPath || ROOT;
821
+
822
+ // New system: scan BOTH .kenaz/tasks/ and .collaboration/tasks/
823
+ // (Core project may have both directories)
824
+ const kenazTasks = path.join(projectRoot, '.kenaz', 'tasks');
825
+ const collabTasks = path.join(projectRoot, '.collaboration', 'tasks');
826
+
827
+ for (const base of [kenazTasks, collabTasks]) {
828
+ scanDir(path.join(base, 'done'), completedIds);
829
+ scanDir(path.join(base, 'archived'), completedIds);
830
+ scanDir(path.join(base, 'blocked'), blockedIds);
831
+ }
832
+
833
+ // Legacy system: completed/
834
+ scanDir(path.join(projectRoot, 'dev', 'pipeline', 'completed'), completedIds);
835
+
836
+ const blockedDeps = deps.filter(dep => blockedIds.has(dep));
837
+ const unmet = deps.filter(dep => !completedIds.has(dep));
838
+ return { blocked: unmet.length > 0, unmet, blockedDeps };
839
+ }
840
+
841
+ // ─────────────────────────────────────────
842
+ // 調度主函數
843
+ // ─────────────────────────────────────────
844
+
845
+ async function dispatch(options) {
846
+ const {
847
+ formation = 'unit',
848
+ skill = 'do',
849
+ task,
850
+ output = null,
851
+ dryRun = false,
852
+ projectPath = null
853
+ } = options;
854
+
855
+ const sessionId = generateSessionId();
856
+
857
+ // 1. 載入技能定義
858
+ const skillDef = loadSkill(formation, skill);
859
+
860
+ // 2. 載入任務(如果是 TASK_ID,支援 projectPath)
861
+ const loadOpts = projectPath ? { projectPath } : undefined;
862
+ const taskData = task && task.startsWith('TASK_') ? loadTask(task, loadOpts) : null;
863
+ const taskInput = task || '';
864
+
865
+ // 2.5 依賴預檢:確認所有依賴都已完成
866
+ if (taskData) {
867
+ const depCheck = checkDependencies(taskData, projectPath);
868
+ if (depCheck.blocked) {
869
+ console.error(`❌ Dispatch blocked: ${taskInput} has unmet dependencies`);
870
+ for (const dep of depCheck.unmet) {
871
+ if (depCheck.blockedDeps && depCheck.blockedDeps.includes(dep)) {
872
+ console.error(` ??${dep} ??blocked`);
873
+ continue;
874
+ }
875
+ console.error(` ⛔ ${dep} — not in done/completed`);
876
+ }
877
+ console.error(` → Complete the dependencies first, or use --force to override`);
878
+ if (!options.force) {
879
+ process.exitCode = 1;
880
+ return null;
881
+ }
882
+ console.warn(` ⚠️ --force: dispatching despite unmet dependencies`);
883
+ }
884
+ }
885
+
886
+ // 3. 組裝 prompt(注入 projectPath context + Yggdrasil network context)
887
+ const promptOptions = {};
888
+ if (projectPath) {
889
+ promptOptions.projectPath = projectPath;
890
+ }
891
+ if (taskInput && taskInput.startsWith('TASK_')) {
892
+ promptOptions.taskId = taskInput;
893
+ }
894
+
895
+ // Yggdrasil: 查詢遠端節點狀態,注入 prompt 讓 Agent 知道其他人在做什麼
896
+ const taskScopePaths = (() => {
897
+ try {
898
+ if (!taskData) return [];
899
+ const parsed = JSON.parse(taskData);
900
+ return parsed.scope_paths || [];
901
+ } catch { return []; }
902
+ })();
903
+ try {
904
+ const ts = getTaskSync();
905
+ if (ts) {
906
+ const [onlineNodes, remoteTasks] = await Promise.all([
907
+ ts.getOnlineNodes(projectPath).catch(() => []),
908
+ ts.getRemoteActiveTasks(projectPath).catch(() => []),
909
+ ]);
910
+ if (onlineNodes.length > 0 || remoteTasks.length > 0) {
911
+ const sb = getSupabaseClient(projectPath);
912
+ promptOptions.yggdrasilContext = {
913
+ onlineNodes,
914
+ remoteTasks,
915
+ myNodeName: sb?.config?.node_name || 'unknown',
916
+ myScopePaths: taskScopePaths,
917
+ };
918
+ }
919
+ }
920
+ } catch { /* Yggdrasil context is best-effort */ }
921
+
922
+ let prompt = buildPrompt(skillDef, taskInput, taskData, promptOptions);
923
+
924
+ // 3.5 Cortex Context 注入:將 scope_paths 相關檔案摘要注入 prompt
925
+ // TASK_1998: "Related Files Preview" is CONTEXT volume, driven by
926
+ // complexity — simple/medium drop it entirely (it was 3.9 KB of mostly
927
+ // low-relevance file-head previews on the measured TASK_1992 prompt),
928
+ // complex keeps it.
929
+ const _dietProfile = promptProfile({ rigor: extractRigor(taskData), complexity: extractComplexity(taskData) });
930
+ if (typeof prompt === 'string' && taskScopePaths.length > 0 && !_dietProfile.skipRelatedFilesPreview) {
931
+ const cortexCtx = buildCortexContext(taskScopePaths, projectPath);
932
+ if (cortexCtx) {
933
+ prompt = prompt + '\n' + cortexCtx;
934
+ }
935
+ }
936
+
937
+ console.log(`⚔️ Formation Dispatch`);
938
+ console.log(` Formation: ${formation}`);
939
+ console.log(` Skill: ${skill}`);
940
+ console.log(` Task: ${taskInput.slice(0, 60)}${taskInput.length > 60 ? '...' : ''}`);
941
+ console.log(` Session: ${sessionId}`);
942
+ if (projectPath) console.log(` Project: ${projectPath}`);
943
+
944
+ // 4. 確保子專案 git 已就緒(TASK_2274: dry-run 不得 git init — 只回報)
945
+ if (dryRun) {
946
+ if (projectPath && !fs.existsSync(path.join(projectPath, '.git'))) console.log(' [dry-run] would git init: ' + projectPath);
947
+ } else {
948
+ ensureGitReady(projectPath);
949
+ }
950
+
951
+ // 4.5 遠端衝突預檢(警告但不阻擋)
952
+ const scopePaths = taskData?.scope_paths || [];
953
+ if (scopePaths.length > 0) {
954
+ try {
955
+ if (isCacheStale()) {
956
+ await refreshCache(projectPath);
957
+ }
958
+ const taskConflict = hasRemoteConflict(scopePaths);
959
+ if (taskConflict.conflict) {
960
+ console.log(`\n ⚠️ Remote conflict: ${taskConflict.conflictNode} is working on ${taskConflict.conflictTask}`);
961
+ }
962
+ const fileConflict = hasRemoteFileConflict(scopePaths);
963
+ if (fileConflict.conflict) {
964
+ console.log(` ⚠️ Remote file conflict: ${fileConflict.conflictNode} is touching ${fileConflict.conflictFile}`);
965
+ }
966
+ } catch {
967
+ // 衝突檢查失敗不阻擋 dispatch
968
+ }
969
+ }
970
+
971
+
972
+ // M1 (TASK_1758): Dispatch-time scope gate + resource lease
973
+ {
974
+ const _sgRoot = projectPath || ROOT;
975
+ const _sgSession = _getProvenSessionId(_sgRoot); // TASK_2265: proven identity only
976
+ const _sgPaths = (() => { try { return taskData ? JSON.parse(taskData).scope_paths || [] : []; } catch { return []; } })();
977
+ const _sgResult = checkDispatchScopeGate(_sgPaths, _sgRoot, _sgSession, !!options.force, taskInput);
978
+ if (_sgResult.collisions.length > 0) {
979
+ for (const col of _sgResult.collisions) {
980
+ const pl = col.paths.slice(0,3).join(', ') + (col.paths.length > 3 ? ' +' + (col.paths.length-3) + ' more' : '');
981
+ if (_sgResult.blocked) {
982
+ console.error(' Scope conflict with stream ' + col.stream_label + ' (task ' + col.task_id + '): ' + pl);
983
+ } else {
984
+ console.warn(' WARNING scope conflict with stream ' + col.stream_label + ' (task ' + col.task_id + '): ' + pl);
985
+ }
986
+ }
987
+ if (_sgResult.blocked) {
988
+ console.error('Dispatch blocked: scope overlap with live stream(s). Use --force to override.');
989
+ process.exitCode = 1;
990
+ return null;
991
+ }
992
+ }
993
+ // TASK_1863: adopt our own claim marker (written by the chain's pre-claim /
994
+ // move→active) so a post-gate rejection below releases it — TASK_1833
995
+ // late-failure semantics extended from resource leases to the claim marker.
996
+ const _sgResources = (() => { try { return taskData ? JSON.parse(taskData).resources || [] : []; } catch { return []; } })();
997
+ // TASK_2274: dry-run takes no claim adoption / resource locks (mirrors the subagent path)
998
+ const _sgClaim = dryRun ? null : adoptSelfClaimMarker(taskInput, _sgRoot, _sgSession);
999
+ if (_sgResources.length > 0 && dryRun) {
1000
+ console.log(' [dry-run] resource locks NOT acquired: ' + _sgResources.join(', '));
1001
+ } else if (_sgResources.length > 0) {
1002
+ const _sgLock = acquireResourceLocks(_sgResources, _sgRoot, _sgSession, taskInput);
1003
+ if (_sgLock.failed.length > 0) {
1004
+ for (const fail of _sgLock.failed) {
1005
+ const hi = fail.holder ? ' (session=' + fail.holder.owner_session + ', task=' + fail.holder.task_id + ')' : '';
1006
+ console.error((fail.orphan ? 'WARNING' : 'ERROR') + ': resource ' + fail.name + (fail.orphan ? ' ORPHAN lock' : ' busy') + hi);
1007
+ }
1008
+ releaseResourceLocks(_sgLock.acquired, _sgRoot);
1009
+ if (!options.force) { releaseAdoptedClaimMarker(_sgClaim); console.error('Dispatch blocked: resource lock conflict. Use --force to override.'); process.exitCode = 1; return null; }
1010
+ console.warn('WARNING: proceeding despite resource lock conflicts (--force).');
1011
+ } else if (_sgLock.acquired.length > 0) {
1012
+ console.log(' Resource locks acquired: ' + _sgLock.acquired.join(', '));
1013
+ console.log(' (Release after merge: node .specialist/tools/stream-lease.js resource-release --name=<resource>)');
1014
+ }
1015
+ }
1016
+ }
1017
+
1018
+ // 5. Dry run
1019
+ if (dryRun) {
1020
+ return handleDryRun(formation, prompt);
1021
+ }
1022
+
1023
+ // 5.5 Yggdrasil: 廣播上線狀態
1024
+ // Note: cleanup 由 child.on('close') 處理(await 確保完成)
1025
+ // process.on('exit') 不支援 async,不適合做 Supabase cleanup
1026
+ if (formation !== 'legion') {
1027
+ broadcastStatus(projectPath, {
1028
+ is_online: true,
1029
+ current_task: taskInput || null,
1030
+ touching_files: scopePaths || [],
1031
+ });
1032
+
1033
+ // Yggdrasil: 同步任務狀態為 active
1034
+ if (taskInput.startsWith('TASK_')) {
1035
+ const ts = getTaskSync();
1036
+ if (ts) {
1037
+ const sb = getSupabaseClient(projectPath);
1038
+ const myNode = sb?.config?.node_name || null;
1039
+ ts.syncTaskStatus({
1040
+ taskId: taskInput,
1041
+ status: 'active',
1042
+ claimedBy: myNode,
1043
+ scopePaths: taskScopePaths,
1044
+ projectPath,
1045
+ }).catch(() => {});
1046
+ }
1047
+ }
1048
+
1049
+ // Signal handlers: 盡力 cleanup(best-effort,process 會等 promise)
1050
+ const handleSignal = (code) => {
1051
+ broadcastStatus(projectPath, { current_task: null, touching_files: [] })
1052
+ .finally(() => process.exit(code));
1053
+ };
1054
+ process.on('SIGINT', () => handleSignal(130));
1055
+ process.on('SIGTERM', () => handleSignal(143));
1056
+ }
1057
+
1058
+ // 6. 根據陣型執行(傳入 projectPath + sessionId for registry)
1059
+ return execute(formation, { prompt, skill, sessionId, output, projectPath, taskId: taskInput });
1060
+ }
1061
+
1062
+ // ─────────────────────────────────────────
1063
+ // Dry Run
1064
+ // ─────────────────────────────────────────
1065
+
1066
+ function handleDryRun(formation, prompt) {
1067
+ if (formation === 'squad' && Array.isArray(prompt)) {
1068
+ console.log(`\n--- SQUAD PROMPTS (${prompt.length} members) ---\n`);
1069
+ for (const m of prompt) {
1070
+ console.log(`=== Member: ${m.memberId} (skill: ${m.skill}) ===`);
1071
+ console.log(m.prompt);
1072
+ console.log('');
1073
+ }
1074
+ console.log(`--- END ---`);
1075
+ } else if (formation === 'legion' && prompt.members) {
1076
+ console.log(`\n--- LEGION CONFIG ---`);
1077
+ console.log(`Team: ${prompt.teamName}`);
1078
+ console.log(`Description: ${prompt.teamDesc}`);
1079
+ console.log(`Members: ${prompt.members.length}`);
1080
+ console.log(`\n--- LEAD PROMPT ---\n`);
1081
+ console.log(prompt.lead.prompt);
1082
+ console.log(`\n--- MEMBER PROMPTS ---\n`);
1083
+ for (const m of prompt.members) {
1084
+ console.log(`=== ${m.name} (${m.agentType}) ===`);
1085
+ console.log(m.prompt);
1086
+ console.log('');
1087
+ }
1088
+ console.log(`--- END ---`);
1089
+ } else {
1090
+ console.log(`\n--- PROMPT ---\n`);
1091
+ console.log(prompt);
1092
+ console.log(`\n--- END ---`);
1093
+ }
1094
+ }
1095
+
1096
+ // ─────────────────────────────────────────
1097
+ // 執行分發
1098
+ // ─────────────────────────────────────────
1099
+
1100
+ function execute(formation, opts) {
1101
+ const { prompt, skill, sessionId, output, projectPath, taskId } = opts;
1102
+
1103
+ switch (formation) {
1104
+ case 'unit':
1105
+ case 'solo': {
1106
+ const child = runSingle({
1107
+ prompt,
1108
+ formation,
1109
+ skill,
1110
+ sessionId,
1111
+ outputPath: output,
1112
+ projectPath
1113
+ });
1114
+
1115
+ // 註冊 dispatch(Dashboard Agent Monitor 用)
1116
+ registerDispatch({ sessionId, logPath: child._formation?.logPath, taskId, formation, projectPath });
1117
+
1118
+ // Cleanup guard: 確保只執行一次,防止 close + formation:done 重複觸發
1119
+ let cleanedUp = false;
1120
+ const cleanup = (code) => {
1121
+ if (cleanedUp) return;
1122
+ cleanedUp = true;
1123
+ unregisterDispatch(sessionId);
1124
+ // Keep event loop alive with a timer so Supabase HTTP requests can complete
1125
+ // before Node.js exits (child close leaves no other handles active)
1126
+ const keepAlive = setTimeout(() => {}, 10000);
1127
+
1128
+ // Yggdrasil: 同步任務最終狀態到 kenaz_tasks
1129
+ const syncFinalStatus = (() => {
1130
+ if (!taskId || !taskId.startsWith('TASK_')) return Promise.resolve();
1131
+ try {
1132
+ const ts = getTaskSync();
1133
+ if (!ts) return Promise.resolve();
1134
+ return ts.syncTaskStatus({
1135
+ taskId,
1136
+ status: code === 0 ? 'done' : 'failed',
1137
+ projectPath,
1138
+ }).catch(() => {});
1139
+ } catch { return Promise.resolve(); }
1140
+ })();
1141
+
1142
+ Promise.allSettled([
1143
+ broadcastStatus(projectPath, { current_task: null, touching_files: [] }),
1144
+ code === 0 ? syncCommit(taskId, projectPath) : Promise.resolve(),
1145
+ syncFinalStatus,
1146
+ ]).then(() => {
1147
+ clearTimeout(keepAlive);
1148
+ });
1149
+ };
1150
+
1151
+ child.on('close', cleanup);
1152
+ // Fallback: formation:done fires when result is received, even if process lingers
1153
+ child.on('formation:done', cleanup);
1154
+
1155
+ return child;
1156
+ }
1157
+
1158
+ case 'squad': {
1159
+ if (!Array.isArray(prompt)) {
1160
+ throw new Error('Squad prompt builder should return an array of member prompts');
1161
+ }
1162
+
1163
+ // Squad: 註冊整個 session
1164
+ registerDispatch({ sessionId, logPath: null, taskId, formation: 'squad', projectPath });
1165
+
1166
+ const result = runParallel({
1167
+ members: prompt,
1168
+ formation,
1169
+ sessionId,
1170
+ projectPath
1171
+ });
1172
+
1173
+ // runParallel returns a promise; await cleanup 確保完成
1174
+ if (result && typeof result.then === 'function') {
1175
+ const cleanup = (results) => {
1176
+ unregisterDispatch(sessionId);
1177
+
1178
+ // Yggdrasil: 同步任務最終狀態(squad 以全員成功為準)
1179
+ const syncFinalStatus = (() => {
1180
+ if (!taskId || !taskId.startsWith('TASK_')) return Promise.resolve();
1181
+ try {
1182
+ const ts = getTaskSync();
1183
+ if (!ts) return Promise.resolve();
1184
+ const allSuccess = Array.isArray(results) && results.every(r => r.exitCode === 0);
1185
+ return ts.syncTaskStatus({
1186
+ taskId,
1187
+ status: allSuccess ? 'done' : 'failed',
1188
+ projectPath,
1189
+ }).catch(() => {});
1190
+ } catch { return Promise.resolve(); }
1191
+ })();
1192
+
1193
+ return Promise.allSettled([
1194
+ broadcastStatus(projectPath, { current_task: null, touching_files: [] }),
1195
+ syncFinalStatus,
1196
+ ]);
1197
+ };
1198
+ result.then(cleanup, () => cleanup(null));
1199
+ }
1200
+
1201
+ return result;
1202
+ }
1203
+
1204
+ case 'legion':
1205
+ // Legion 不 spawn 進程,輸出 TeamCreate 配置供 Formation Lead 使用
1206
+ console.log(`\n⚔️ Legion: TeamCreate configuration generated`);
1207
+ console.log(` Team: ${prompt.teamName}`);
1208
+ console.log(` Members: ${prompt.members.length}`);
1209
+ console.log(`\n Legion 不直接啟動進程。`);
1210
+ console.log(` 請使用 TeamCreate API 搭配以上配置啟動團隊。`);
1211
+ console.log(` 或使用 --dry-run 查看完整 prompt。`);
1212
+ return prompt;
1213
+
1214
+ default:
1215
+ throw new Error(`Unknown formation: ${formation}`);
1216
+ }
1217
+ }
1218
+
1219
+ // ─────────────────────────────────────────
1220
+ // CLI
1221
+ // ─────────────────────────────────────────
1222
+
1223
+ if (require.main === module) {
1224
+ const args = process.argv.slice(2);
1225
+
1226
+ if (args.includes('--help') || args.includes('-h')) {
1227
+ console.log(`
1228
+ ⚔️ Formation Dispatch
1229
+
1230
+ Usage:
1231
+ node .formation/tools/dispatch.js --skill=<name> --task=<TASK_ID|description>
1232
+
1233
+ Options:
1234
+ --formation <name> Formation type: unit (default), solo, squad, legion
1235
+ --skill <name> Skill to use (YAML filename without extension)
1236
+ --task <value> Task ID (TASK_XXX) or free-text description
1237
+ --concurrency <n> Parallel execution slots (default 3, max 5, legacy only)
1238
+ --output <path> Custom log output path
1239
+ --dry-run Only print the prompt, don't launch
1240
+ --prompt-only Print raw prompt text to stdout (machine-readable, no headers)
1241
+ --dispatch-mode <mode> Output mode: formation (default), subagent (JSON params for Agent tool)
1242
+ --dispatch-model <id> TASK_1998 R3: subagent-path model override (wins over
1243
+ dashboard-models.json dispatchModelByRigor and the
1244
+ default — the dashboard dispatchModel, used for
1245
+ every rigor unless dispatchModelByRigor sets that
1246
+ rigor's entry). Only used with --dispatch-mode=subagent.
1247
+ --use-worktree <bool> TASK_1833: dispatch-time worktree toggle (true|false).
1248
+ Overrides env FORMATION_USE_WORKTREE and the target
1249
+ project's .kenaz/project.yaml use_worktree. For
1250
+ cross-project subagent dispatch: true → pre-created
1251
+ worktree inside the target repo; false → shared tree
1252
+ with serialized writes (dispatch lock). Single-editor
1253
+ projects (Unity) should pass false.
1254
+ --release-lock TASK_1859: release the serial dispatch lock for
1255
+ --project-path (omit for the core lock). Prints the
1256
+ holder's taskId/sessionId/startedAt, then releases.
1257
+ Default releases only a lock held by THIS session;
1258
+ cross-session / unknown-holder release needs --force.
1259
+ Idempotent: exit 0 with a harmless message when no
1260
+ lock is held. Fallback remains deleting the lock file.
1261
+ --force Dispatch even if dependencies are not met
1262
+ (with --release-lock: release a lock this session
1263
+ cannot prove it owns)
1264
+
1265
+ Formation-Skill Quick Reference:
1266
+ unit: do, think, plan
1267
+ solo: strategy, diagnosis
1268
+ squad: blitz, sweep
1269
+ legion: forge, hive
1270
+
1271
+ Sub-agent dispatch (Ansuz billing-aware path):
1272
+ node .formation/tools/dispatch.js --skill=do --task=TASK_172 --dispatch-mode=subagent
1273
+ → prints JSON: { promptText, taskId, agentParams: { model, isolation, description } }
1274
+ Ansuz passes promptText to Agent tool with agentParams for worktree-isolated execution.
1275
+
1276
+ Headless Mode (recommended for long tasks):
1277
+ node .formation/tools/headless.js --formation=legion --skill=forge --task=TASK_174
1278
+
1279
+ Examples:
1280
+ node .formation/tools/dispatch.js --skill=do --task=TASK_172
1281
+ node .formation/tools/dispatch.js --formation=solo --skill=strategy --task="評估新功能"
1282
+ node .formation/tools/dispatch.js --formation=squad --skill=blitz --task=TASK_173
1283
+ node .formation/tools/dispatch.js --formation=legion --skill=forge --task=TASK_174 --dry-run
1284
+ `);
1285
+ process.exit(0);
1286
+ }
1287
+
1288
+ const getArg = (flag) => {
1289
+ for (let i = 0; i < args.length; i++) {
1290
+ if (args[i].startsWith(`${flag}=`)) {
1291
+ return args[i].split('=').slice(1).join('=');
1292
+ }
1293
+ if (args[i] === flag && args[i + 1]) {
1294
+ return args[i + 1];
1295
+ }
1296
+ }
1297
+ return null;
1298
+ };
1299
+
1300
+ const formation = getArg('--formation') || 'unit';
1301
+ const skill = getArg('--skill');
1302
+ const task = getArg('--task');
1303
+ const output = getArg('--output');
1304
+ const projectPath = getArg('--project-path');
1305
+ const dryRun = args.includes('--dry-run');
1306
+ const promptOnly = args.includes('--prompt-only');
1307
+ const dispatchModeCli = getArg('--dispatch-mode');
1308
+ // TASK_1998 R3: subagent-path model override — wins over dashboard
1309
+ // dispatchModelByRigor and the dashboard dispatchModel default. Accepts
1310
+ // either a bare Agent tool family (sonnet|opus|haiku|fable) or a full
1311
+ // dashboard-style id (translated the same way as every other source).
1312
+ const dispatchModelCli = getArg('--dispatch-model');
1313
+ const force = args.includes('--force');
1314
+ // TASK_2315: harness selector; auto-detect Codex from its session env (same signal as the boot fix).
1315
+ const harnessCli = getArg('--harness') || ((process.env.CODEX_SESSION_ID || process.env.CODEX_THREAD_ID) ? 'codex' : 'claude');
1316
+
1317
+ // TASK_1833: dispatch-time worktree toggle. Parsed strictly — a typo must not
1318
+ // silently fall through to the project default. Also exported to
1319
+ // FORMATION_USE_WORKTREE so any in-process readWorktreeConfig consumer
1320
+ // (formation path included) sees the same decision.
1321
+ const useWorktreeRaw = getArg('--use-worktree');
1322
+ let useWorktreeCli = null;
1323
+ if (useWorktreeRaw != null) {
1324
+ const v = String(useWorktreeRaw).trim().toLowerCase();
1325
+ if (v === 'true' || v === '1') useWorktreeCli = true;
1326
+ else if (v === 'false' || v === '0') useWorktreeCli = false;
1327
+ else {
1328
+ console.error(`❌ --use-worktree expects true|false (got '${useWorktreeRaw}')`);
1329
+ process.exit(1);
1330
+ }
1331
+ process.env.FORMATION_USE_WORKTREE = String(useWorktreeCli);
1332
+ }
1333
+
1334
+ // TASK_1859: standalone lock-release subcommand — needs neither --skill nor
1335
+ // --task. Exists because "delete the lock file" (the previous release
1336
+ // contract) is unexecutable where Bash(rm *) is denied.
1337
+ if (args.includes('--release-lock')) {
1338
+ const res = releaseDispatchLock({ projectPath, force });
1339
+ const h = res.holder || {};
1340
+ const holderLine = res.existed
1341
+ ? ` Holder: task=${h.taskId || '?'}, session=${h.sessionId || '?'}, startedAt=${h.startedAt || '?'}` +
1342
+ (res.staleness ? ` (age=${Number.isFinite(res.staleness.ageMs) ? Math.round(res.staleness.ageMs / 60000) + 'min' : '?'}, stale=${res.staleness.stale})` : '')
1343
+ : null;
1344
+ if (!res.existed) {
1345
+ console.log(`✅ No dispatch lock held (${res.lockFile}) — nothing to release.`);
1346
+ process.exit(0);
1347
+ }
1348
+ if (res.released) {
1349
+ console.log(holderLine);
1350
+ console.log(`✅ Dispatch lock released (${res.reason}): ${res.lockFile}`);
1351
+ process.exit(0);
1352
+ }
1353
+ console.log(holderLine);
1354
+ console.error(`❌ Dispatch lock NOT released (${res.reason}): ${res.lockFile}`);
1355
+ if (res.reason === 'session-mismatch' || res.reason === 'holder-session-unknown' ||
1356
+ res.reason === 'own-session-unresolved' || res.reason === 'own-session-unproven' ||
1357
+ res.reason === 'holder-unreadable') {
1358
+ console.error(' This session cannot prove it owns the lock. Verify the previous agent is done, then re-run with --force. (Stale locks auto-break on the next dispatch after 60min.)');
1359
+ }
1360
+ process.exit(1);
1361
+ }
1362
+
1363
+ if (!skill) {
1364
+ console.error('❌ --skill is required');
1365
+ process.exit(1);
1366
+ }
1367
+
1368
+ if (!task) {
1369
+ console.error('❌ --task is required (TASK_ID or description)');
1370
+ process.exit(1);
1371
+ }
1372
+
1373
+ // Sub-agent mode: output JSON params for Agent tool consumption
1374
+ if (dispatchModeCli === 'subagent') {
1375
+ getSubagentDispatchParams({ formation, skill, task, projectPath, force, useWorktree: useWorktreeCli, dispatchModelOverride: dispatchModelCli, dryRun, harness: harnessCli }).then(result => {
1376
+ if (!result) { process.exitCode = 1; return; }
1377
+ process.stdout.write(JSON.stringify(result, null, 2) + '\n');
1378
+ });
1379
+ return;
1380
+ }
1381
+
1382
+ // Prompt-only mode: output raw prompt to stdout (machine-readable, no decorations)
1383
+ if (promptOnly) {
1384
+ const skillDef = loadSkill(formation, skill);
1385
+ const loadOpts = projectPath ? { projectPath } : undefined;
1386
+ const taskData = task && task.startsWith('TASK_') ? loadTask(task, loadOpts) : null;
1387
+ const promptOptions = {};
1388
+ if (projectPath) promptOptions.projectPath = projectPath;
1389
+ if (task && task.startsWith('TASK_')) promptOptions.taskId = task;
1390
+ const rawPrompt = buildPrompt(skillDef, task, taskData, promptOptions);
1391
+ const text = typeof rawPrompt === 'string' ? rawPrompt : JSON.stringify(rawPrompt);
1392
+ process.stdout.write(text + '\n');
1393
+ return;
1394
+ }
1395
+
1396
+ dispatch({ formation, skill, task, output, dryRun, projectPath, force });
1397
+ }
1398
+
1399
+ // ─────────────────────────────────────────
1400
+ // Sub-agent dispatch path
1401
+ // ─────────────────────────────────────────
1402
+
1403
+ /**
1404
+ * TASK_1813: read dispatch routing (dispatchFamily/dispatchAdapter) plus the raw
1405
+ * dashboard-models.json object, mirroring kenaz.rs load_dispatch_routing /
1406
+ * load_dashboard_model semantics:
1407
+ * - Candidate order: project first, then core (ROOT). Same order as the Rust
1408
+ * side's dashboard_models_candidates — both paths must read the SAME file or
1409
+ * they can reach different routing conclusions for one dispatch.
1410
+ * - ALL fields come from the FIRST parseable candidate file, so family and
1411
+ * adapter can never be mixed across two different dashboard-models.json files.
1412
+ * - Empty/whitespace strings coalesce to null (mirrors Rust `.filter(|s| !s.is_empty())`).
1413
+ * @param {string|null} projectPath
1414
+ * @returns {{ models: object|null, family: string|null, adapter: string|null }}
1415
+ */
1416
+ function loadDispatchRouting(projectPath) {
1417
+ const parsed = loadDashboardModels(projectPath); // first parseable candidate wins (TASK_2249)
1418
+ if (!parsed) return { models: null, family: null, adapter: null };
1419
+ const get = (field) => {
1420
+ const v = parsed[field];
1421
+ if (typeof v !== 'string') return null;
1422
+ const trimmed = v.trim();
1423
+ return trimmed || null;
1424
+ };
1425
+ return { models: parsed, family: get('dispatchFamily'), adapter: get('dispatchAdapter') };
1426
+ }
1427
+
1428
+ /**
1429
+ * Build the sub-agent dispatch payload without spawning a process.
1430
+ * Ansuz calls this to get the prompt + Agent tool parameters, then passes them
1431
+ * to the Agent tool (isolation='worktree') directly. (Originally motivated by
1432
+ * the June 15 claude -p credit pool, since rescinded; it remains the default
1433
+ * because results return in-session without log polling.)
1434
+ *
1435
+ * Routing: use for rigor:low/medium tasks estimated <30min.
1436
+ * Formation dispatch (claude -p) remains the default for rigor:high / multi-hour tasks.
1437
+ *
1438
+ * @param {object} options
1439
+ * @param {string} [options.formation='unit']
1440
+ * @param {string} [options.skill='do']
1441
+ * @param {string} options.task - Task ID (TASK_XXX) or description
1442
+ * @param {string|null} [options.projectPath]
1443
+ * @param {boolean} [options.force] - Skip dependency check
1444
+ * @param {boolean|null} [options.useWorktree] - TASK_1833 dispatch-time worktree toggle
1445
+ * (true/false overrides env/project.yaml; null = no override). Only affects
1446
+ * cross-project dispatch — same-project always uses Agent tool isolation:'worktree'.
1447
+ * @param {string|null} [options.dispatchModelOverride] - TASK_1998 R3: --dispatch-model
1448
+ * CLI value, if any. Wins over dashboard-models.json dispatchModelByRigor and
1449
+ * the dashboard dispatchModel default.
1450
+ * @returns {Promise<{ promptText: string, taskId: string, formation: string, skill: string, dispatchMode: string, effectiveMode: 'subagent', modelTranslation: { requested: string, agentToolModel: string, granularityLoss: boolean }, isolation: object, agentParams: object, rigor: 'low'|'medium'|'high', modelSource: 'dashboard'|'dashboard-by-rigor'|'cli' }|null>}
1451
+ * dispatchMode = TASK_1813 config echo (dashboard-models.json request);
1452
+ * effectiveMode = the path actually taken (always 'subagent' here — TASK_1859).
1453
+ */
1454
+ async function getSubagentDispatchParams(options) {
1455
+ const {
1456
+ formation = 'unit', skill = 'do', task, projectPath = null, force = false, useWorktree = null,
1457
+ dispatchModelOverride = null, // TASK_1998 R3: --dispatch-model CLI flag, wins over dashboard dispatchModelByRigor/dispatchModel
1458
+ // --dry-run: build and print the payload with NO side effects — no resource
1459
+ // leases, no worktree, no serial lock, no prompt telemetry. Gates still run
1460
+ // so a dry run reports the same rejections a real dispatch would.
1461
+ dryRun = false,
1462
+ // TASK_2315: 'claude' (Agent tool) | 'codex' (Codex-native spawn_agent). Selects the payload shape.
1463
+ harness = 'claude',
1464
+ } = options;
1465
+ if (harness !== 'claude' && harness !== 'codex') {
1466
+ console.error(`❌ --harness expects claude|codex (got '${harness}')`);
1467
+ return null;
1468
+ }
1469
+ const isCodex = harness === 'codex';
1470
+
1471
+ // 1. Load skill + task
1472
+ const skillDef = loadSkill(formation, skill);
1473
+ const loadOpts = projectPath ? { projectPath } : undefined;
1474
+ const taskData = task && task.startsWith('TASK_') ? loadTask(task, loadOpts) : null;
1475
+ const taskInput = task || '';
1476
+ // TASK_1998 R3: extracted here (not at step 4, where it used to live) so the
1477
+ // model-resolution step (2c) below can read it before choosing a model.
1478
+ const rigor = extractRigor(taskData);
1479
+ // TASK_1998 two-axis policy: complexity drives CONTEXT volume (Cross-Project
1480
+ // Context caps, Related Files Preview, Known Failures, Project Memory).
1481
+ // Always normalized (extractComplexity defaults to 'medium').
1482
+ const complexity = extractComplexity(taskData);
1483
+
1484
+ // 2. Dependency check (same guard as Formation dispatch)
1485
+ if (taskData) {
1486
+ const depCheck = checkDependencies(taskData, projectPath);
1487
+ if (depCheck.blocked && !force) {
1488
+ console.error(`❌ Sub-agent dispatch blocked: ${taskInput} has unmet dependencies`);
1489
+ for (const dep of depCheck.unmet) {
1490
+ console.error(` ⛔ ${dep} — not in done/completed`);
1491
+ }
1492
+ return null;
1493
+ }
1494
+ }
1495
+
1496
+ // 2b. (TASK_1813) Dispatch routing guard — mirrors kenaz.rs tool_dispatch
1497
+ // (lines 624-654, TASK_1776) on the sub-agent path. The Agent tool's model
1498
+ // parameter only accepts Claude models, so a non-claude dispatchFamily has NO
1499
+ // viable execution here and MUST fail loudly (sigil_2a3f3b75 invariant:
1500
+ // "a non-claude model id MUST resolve to an adapter or fail loudly — never
1501
+ // silent Claude CLI fallback"). Runs BEFORE the scope gate / resource locks /
1502
+ // prompt build so a rejected dispatch never acquires locks it won't use.
1503
+ const routing = loadDispatchRouting(projectPath);
1504
+ const models = routing.models;
1505
+ // 2026-10-10: the harness decides the family. A Codex session can only spawn Codex
1506
+ // sub-agents (model inherited), so dashboard-models.json dispatchFamily (a Dashboard
1507
+ // preference for the retired Formation spawns) no longer blocks --harness=codex.
1508
+ if (isCodex && routing.family !== 'bifrost') {
1509
+ process.stderr.write(`[dispatch] --harness=codex: dispatchFamily '${routing.family || 'unset'}' ignored, Codex sub-agent inherits the session model
1510
+ `);
1511
+ }
1512
+ if (routing.family === 'bifrost' && !isCodex) {
1513
+ if (!routing.adapter) {
1514
+ console.error('❌ dashboard-models.json sets dispatchFamily=bifrost but dispatchAdapter is missing/empty — refusing to silently dispatch with the native Claude CLI. Fix the model selection (Quick Actions → Default Models) or dashboard-models.json, then use Formation dispatch (kenaz_dispatch).');
1515
+ } else {
1516
+ console.error(`❌ dashboard-models.json sets dispatchFamily=bifrost (dispatchAdapter '${routing.adapter}') — sub-agent dispatch cannot run non-Claude models (the Agent tool only accepts Claude models); refusing to silently dispatch with the native Claude CLI. Use Formation dispatch (kenaz_dispatch) instead — it routes through the Bifrost adapter.`);
1517
+ }
1518
+ return null;
1519
+ }
1520
+ if (!isCodex && routing.family && routing.family !== 'claude') {
1521
+ console.error(`❌ dashboard-models.json sets unsupported dispatchFamily '${routing.family}' (expected 'claude' or 'bifrost') — refusing to silently dispatch with the native Claude CLI. Fix the model selection (Quick Actions → Default Models) or use Formation dispatch (kenaz_dispatch).`);
1522
+ return null;
1523
+ }
1524
+
1525
+ // 2c. (TASK_1815 + TASK_1998 R3) Resolve which raw model id to use — CLI
1526
+ // --dispatch-model > dashboard-models.json dispatchModelByRigor[rigor] >
1527
+ // dashboard-models.json dispatchModel (today's behaviour, used for every
1528
+ // rigor unless dispatchModelByRigor overrides it) — THEN translate it to the
1529
+ // Agent tool's family enum. The raw id (e.g. 'claude-fable-5[1m]') is rejected by the
1530
+ // Agent tool for ANY source (measured 2026-07-26: same InputValidationError
1531
+ // as 'gpt-5-codex'); only the family names in AGENT_TOOL_MODEL_ENUM pass
1532
+ // validation. Fail loudly on unmappable ids from ANY source (TASK_1815:
1533
+ // never silently substitute), and surface the version-granularity loss to
1534
+ // the caller. Runs BEFORE the scope gate / resource leases (same reason as
1535
+ // 2b: a rejected dispatch must never acquire locks it won't use).
1536
+ const resolution = resolveDispatchModelForRigor({ rigor, models, cliDispatchModel: dispatchModelOverride });
1537
+ const rawModel = resolution.rawModel;
1538
+ // TASK_2315: Codex inherits the session model — nothing to translate or pass.
1539
+ const translated = isCodex ? { model: null, lossless: true } : translateModelForAgentTool(rawModel);
1540
+ if (!isCodex && !translated.model) {
1541
+ console.error(`❌ ${resolution.label} '${rawModel}' cannot be mapped to an Agent tool model family (${AGENT_TOOL_MODEL_ENUM.join('|')}) — refusing to silently guess a substitute model. Fix the model selection (Quick Actions → Default Models) or use Formation dispatch (kenaz_dispatch), which accepts full model ids via --dispatch-model.`);
1542
+ return null;
1543
+ }
1544
+ const dispatchModel = translated.model;
1545
+ const modelTranslation = isCodex
1546
+ ? { requested: rawModel, inherited: true }
1547
+ : { requested: rawModel, agentToolModel: dispatchModel, granularityLoss: !translated.lossless };
1548
+ if (!translated.lossless) {
1549
+ process.stderr.write(`[dispatch] model '${rawModel}' → Agent tool family '${dispatchModel}' — the Agent tool only expresses family names (${AGENT_TOOL_MODEL_ENUM.join('|')}); version/speed selections (e.g. 5 vs 4.x, [1m]) are NOT expressible on the subagent path. If the exact version matters, use Formation dispatch (kenaz_dispatch), which passes full model ids.\n`);
1550
+ }
1551
+ // TASK_1998 R3 (+ two-axis policy): the resolved choice, always printed
1552
+ // (unlike the granularity block above, which only fires on lossy translation).
1553
+ process.stderr.write(`[dispatch] rigor=${resolution.rigorKey} complexity=${complexity} model=${rawModel} → ${isCodex ? 'inherited by Codex session' : "family '" + dispatchModel + "'"} (source: ${resolution.source})\n`);
1554
+
1555
+ // TASK_2362: subagent is the only route. dispatchMode is a legacy config echo:
1556
+ // missing -> 'subagent'; 'subagent'|'auto' accepted; 'formation' (retired) or
1557
+ // any other value warns LOUDLY and uses 'subagent'.
1558
+ const rawDispatchMode = typeof models?.dispatchMode === 'string' ? models.dispatchMode.trim() : '';
1559
+ let dispatchMode = 'subagent';
1560
+ if (rawDispatchMode) {
1561
+ if (rawDispatchMode === 'subagent' || rawDispatchMode === 'auto') {
1562
+ dispatchMode = rawDispatchMode;
1563
+ } else {
1564
+ console.error(`⚠️ dashboard-models.json dispatchMode '${rawDispatchMode}' is invalid or retired (expected subagent|auto) — using 'subagent'`);
1565
+ }
1566
+ }
1567
+
1568
+ // M1 (TASK_1758): scope gate + resource lease (same as formation dispatch path)
1569
+ // TASK_1833: acquired resources tracked OUTSIDE the block so the isolation
1570
+ // step below can release them on late rejection (never leak leases).
1571
+ // TASK_1863: the self-owned claim marker gets the SAME late-rejection release
1572
+ // guarantee — tracked alongside the resources, released at every post-gate
1573
+ // failure exit (leaked markers blocked same-task retries for the 8h window).
1574
+ let _saAcquiredResources = [];
1575
+ let _saClaim = null;
1576
+ const _saRoot = projectPath || ROOT;
1577
+ {
1578
+ const _saSession = _getProvenSessionId(_saRoot); // TASK_2265: proven identity only
1579
+ const _saPaths = (() => { try { return taskData ? JSON.parse(taskData).scope_paths || [] : []; } catch { return []; } })();
1580
+ const _saResult = checkDispatchScopeGate(_saPaths, _saRoot, _saSession, !!force, taskInput);
1581
+ if (_saResult.collisions.length > 0) {
1582
+ for (const col of _saResult.collisions) {
1583
+ const pl = col.paths.slice(0,3).join(', ') + (col.paths.length > 3 ? ' +' + (col.paths.length-3) + ' more' : '');
1584
+ if (_saResult.blocked) { console.error('Sub-agent dispatch blocked: scope conflict with stream ' + col.stream_label + ' (task ' + col.task_id + '): ' + pl); }
1585
+ else { console.warn('WARNING scope conflict (--force): stream ' + col.stream_label + ' (task ' + col.task_id + '): ' + pl); }
1586
+ }
1587
+ if (_saResult.blocked) { return null; }
1588
+ }
1589
+ _saClaim = adoptSelfClaimMarker(taskInput, _saRoot, _saSession);
1590
+ const _saResources = (() => { try { return taskData ? JSON.parse(taskData).resources || [] : []; } catch { return []; } })();
1591
+ if (_saResources.length > 0 && dryRun) {
1592
+ console.error(' [dry-run] resource locks NOT acquired: ' + _saResources.join(', '));
1593
+ } else if (_saResources.length > 0) {
1594
+ const _saLock = acquireResourceLocks(_saResources, _saRoot, _saSession, taskInput);
1595
+ if (_saLock.failed.length > 0) {
1596
+ for (const fail of _saLock.failed) {
1597
+ const hi = fail.holder ? ' (session=' + fail.holder.owner_session + ', task=' + fail.holder.task_id + ')' : '';
1598
+ console.error((fail.orphan ? 'WARNING' : 'ERROR') + ': resource ' + fail.name + (fail.orphan ? ' ORPHAN' : ' busy') + hi);
1599
+ }
1600
+ releaseResourceLocks(_saLock.acquired, _saRoot);
1601
+ if (!force) { releaseAdoptedClaimMarker(_saClaim); return null; }
1602
+ console.warn('WARNING: proceeding despite resource lock conflicts (--force).');
1603
+ } else if (_saLock.acquired.length > 0) {
1604
+ console.error(' Resource locks acquired: ' + _saLock.acquired.join(', '));
1605
+ }
1606
+ _saAcquiredResources = _saLock.acquired;
1607
+ }
1608
+ }
1609
+
1610
+ // TASK_1833: cross-project dispatch now goes through the SAME isolation
1611
+ // decision as every other path (resolveDispatchIsolation — see its doc for
1612
+ // the mode taxonomy and the TASK_1672/1593 reason the Agent tool's own
1613
+ // isolation param cannot cover another repo). Before this, cross-project
1614
+ // sub-agent dispatch unconditionally got NEITHER isolation NOR
1615
+ // serialization, and the shared-tree `|| true` commit swallowed the
1616
+ // resulting index.lock data loss (measured 2026-07-31).
1617
+ // TASK_1824 ordering still holds: computed BEFORE buildPrompt so prompt
1618
+ // assembly (appendWorkflow staging gate, TASK_1819) knows the isolation mode.
1619
+ const iso = resolveDispatchIsolation({ projectPath, useWorktreeOverride: useWorktree });
1620
+ // TASK_2315: Codex has no harness-managed worktree isolation — always pre-create
1621
+ // one (same-project included) and hand its path to the agent as cwd.
1622
+ const wtRepo2315 = projectPath || ROOT;
1623
+ if (isCodex && iso.mode === 'agent_tool_worktree') { iso.mode = 'target_repo_worktree'; iso.source = 'codex-harness'; }
1624
+ const isCrossProject = iso.isCrossProject || (isCodex && iso.mode === 'target_repo_worktree');
1625
+ let crossWorktree = null; // { worktreePath, branchName } when mode=target_repo_worktree
1626
+ let serialLock = null; // { lockFile } when mode=serial_lock
1627
+ let worktreeFallbackReason = null; // TASK_2067: non-null only on a genuine target_repo_worktree creation failure that degraded to serial_lock -- rides in the isolation payload, not just stderr
1628
+
1629
+ // TASK_2297: free-space gate before any worktree is created. Reclaims finished-card
1630
+ // worktrees ONLY under pressure (merged+clean+no junctions+idle); refuses otherwise.
1631
+ if (iso.useWorktree && !dryRun) {
1632
+ const wtRepo = projectPath || ROOT;
1633
+ const space = require('./worktree-reclaim').ensureWorktreeSpace(wtRepo, path.join(wtRepo, '.formation', 'worktrees'));
1634
+ if (!space.ok) throw new Error(space.message);
1635
+ }
1636
+
1637
+ if (iso.mode === 'target_repo_worktree' && dryRun) {
1638
+ const idBase = taskInput.startsWith('TASK_') ? taskInput.toLowerCase() : 'adhoc';
1639
+ crossWorktree = { worktreePath: path.join(wtRepo2315, '.formation', 'worktrees', `task_${idBase}`) + ' (dry-run: not created)', branchName: `task/${idBase}` };
1640
+ } else if (iso.mode === 'target_repo_worktree') {
1641
+ try {
1642
+ crossWorktree = setupSubagentCrossProjectWorktree(wtRepo2315, taskInput);
1643
+ // stderr, not stdout — subagent mode's stdout is machine-readable JSON
1644
+ process.stderr.write(` 🌿 Cross-project worktree (in target repo): ${crossWorktree.worktreePath}${crossWorktree.reusedBranch ? ' (reused existing branch)' : ''}\n`);
1645
+ } catch (e) {
1646
+ // Safe degradation: NEVER fall back to unserialized shared-tree writes —
1647
+ // that is exactly the defect this path exists to prevent. Serialize instead.
1648
+ // TASK_2067: this must now be a GENUINE creation failure (e.g. branch
1649
+ // checked out in another worktree already) -- the "branch exists but
1650
+ // its worktree doesn't" case is handled inside createWorktree itself
1651
+ // and no longer throws here. Surface the reason in the payload too,
1652
+ // not only stderr, so a consumer of the JSON payload can see WHY it
1653
+ // degraded instead of assuming this is the normal/expected path.
1654
+ console.error(`⚠️ Cross-project worktree creation failed (${e.message}) — falling back to SERIALIZED shared-tree dispatch`);
1655
+ worktreeFallbackReason = e.message;
1656
+ iso.mode = 'serial_lock';
1657
+ iso.useWorktree = false;
1658
+ }
1659
+ }
1660
+
1661
+ if (iso.mode === 'serial_lock' && dryRun) {
1662
+ console.error(' [dry-run] shared-tree dispatch lock NOT acquired: ' + dispatchLockPath(projectPath));
1663
+ } else if (iso.mode === 'serial_lock') {
1664
+ const lockFile = dispatchLockPath(projectPath);
1665
+ // pid:null on purpose — this CLI exits right after emitting params, so its
1666
+ // own pid says nothing about the agent's liveness. pid-less locks are
1667
+ // broken only by staleness (60min) or explicit release (delete the file
1668
+ // after merge — the lock file path is surfaced in the returned payload).
1669
+ const acq = tryAcquireDispatchLock(lockFile, {
1670
+ sessionId: _getProvenSessionId(ROOT) || 'unknown', // TASK_2265: unproven fallback never written as owner
1671
+ taskId: taskInput || null,
1672
+ pid: null,
1673
+ holder: 'subagent-shared-tree',
1674
+ });
1675
+ if (!acq.acquired) {
1676
+ const h = acq.holder || {};
1677
+ console.error(`❌ Sub-agent dispatch blocked: shared-tree dispatch lock for this project is held (task=${h.taskId || '?'}, session=${h.sessionId || '?'}, since=${h.startedAt || '?'}). Cross-project dispatch WITHOUT worktree isolation is serialized — multiple agents committing into one shared working tree destroy each other's work (index.lock). Wait for the current dispatch to finish (lock auto-breaks 60min after acquisition), or release it after verifying the previous agent is done: node .formation/tools/dispatch.js --release-lock${projectPath ? ` --project-path "${projectPath}"` : ''} (add --force if held by another session). Fallback: delete ${lockFile}`);
1678
+ releaseResourceLocks(_saAcquiredResources, _saRoot);
1679
+ releaseAdoptedClaimMarker(_saClaim); // TASK_1863: late rejection must not leak the claim
1680
+ return null;
1681
+ }
1682
+ if (acq.broke) console.warn(` ⚠️ Broke ${acq.brokeReason} dispatch lock from ${acq.broke.taskId || acq.broke.sessionId || '<corrupt>'}`);
1683
+ serialLock = { lockFile };
1684
+ }
1685
+
1686
+ // 3. Build prompt (same buildPrompt() as Formation dispatch — same prompt quality)
1687
+ const promptOptions = { isSubagent: true, isCrossProject };
1688
+ if (crossWorktree) promptOptions.isWorktree = true; // isolated staging (TASK_1819 gate)
1689
+ if (projectPath) promptOptions.projectPath = projectPath;
1690
+ if (taskInput && taskInput.startsWith('TASK_')) promptOptions.taskId = taskInput;
1691
+
1692
+ const rawPrompt = buildPrompt(skillDef, taskInput, taskData, promptOptions);
1693
+
1694
+ // 4. Cortex context (same as Formation dispatch)
1695
+ const taskScopePaths = (() => {
1696
+ try {
1697
+ if (!taskData) return [];
1698
+ const parsed = JSON.parse(taskData);
1699
+ return parsed.scope_paths || [];
1700
+ } catch { return []; }
1701
+ })();
1702
+
1703
+ let promptText = typeof rawPrompt === 'string' ? rawPrompt : '';
1704
+ // TASK_1998: complexity (not rigor) gates the Related Files Preview section
1705
+ // (same two-axis gate as the Formation-dispatch path above). `rigor` and
1706
+ // `complexity` were both extracted in step 1 (rigor needed earlier, for
1707
+ // model resolution).
1708
+ const dietProfile = promptProfile({ rigor, complexity });
1709
+ if (taskScopePaths.length > 0 && !dietProfile.skipRelatedFilesPreview) {
1710
+ const cortexCtx = buildCortexContext(taskScopePaths, projectPath);
1711
+ if (cortexCtx) promptText = promptText + '\n' + cortexCtx;
1712
+ }
1713
+
1714
+ // TASK_2176: project declares verify_offline (single heavyweight tool —
1715
+ // Unity/Unreal/mobile — the worktree agent cannot run authoritatively).
1716
+ // Surface it as a non-authoritative self-check only; the authoritative,
1717
+ // serialized run happens on the main tree at landing (verify-and-land.js
1718
+ // stepVerifyOffline), never inside this worktree.
1719
+ if (iso.verifyOffline) {
1720
+ promptText += `\n\n## Offline self-check (non-authoritative)\nThis project's .kenaz/project.yaml declares \`verify_offline: ${iso.verifyOffline}\`. Run it yourself before committing as a self-check and note the pass/fail in your final summary. It does NOT replace the authoritative verification — that runs serialized on the main tree at landing.\n`;
1721
+ }
1722
+
1723
+ // 5. Swap HEADLESS_PREFIX → sub-agent transport preamble (mode-specific)
1724
+ // TASK_1833: prefix follows the isolation mode —
1725
+ // agent_tool_worktree → SUBAGENT_PREFIX (harness worktree, pwd-derived)
1726
+ // target_repo_worktree → buildSubagentWorktreePrefix (pre-created worktree
1727
+ // inside the target repo; agent cd's there)
1728
+ // serial_lock → SUBAGENT_PREFIX_DIRECT (shared tree, explicit-paths
1729
+ // staging, writes serialized by the dispatch lock)
1730
+ let subagentPrefix = SUBAGENT_PREFIX;
1731
+ if (isCrossProject) {
1732
+ subagentPrefix = crossWorktree
1733
+ ? buildSubagentWorktreePrefix(crossWorktree.worktreePath, crossWorktree.branchName, wtRepo2315)
1734
+ : SUBAGENT_PREFIX_DIRECT;
1735
+ process.stderr.write('[dispatch] cross-project detected (' + ROOT + ' vs ' + projectPath + ') — isolation mode: ' + iso.mode + '\n');
1736
+ }
1737
+ // TASK_2082 defect fix: when promptText's body carries the "## Rust check"
1738
+ // section (appendWorkflow -> appendRustCheckReminder), hard rule 4's
1739
+ // "Rust 交 Ansuz" wording inside the chosen prefix is contradictory — a
1740
+ // later "this overrides rule 4" note in the body was observed NOT
1741
+ // winning against the earlier hard rule. Rewrite the prefix itself at
1742
+ // this composition point instead; a body without the section marker
1743
+ // leaves the prefix byte-identical.
1744
+ subagentPrefix = applyRustCheckToPrefix(subagentPrefix, promptText);
1745
+ promptText = subagentPrefix + promptText;
1746
+
1747
+ // 6. Model (translated to the Agent tool enum, step 2c) + dispatchMode
1748
+ // (step 2b routing guard) were resolved above.
1749
+
1750
+ // TASK_1593: the Agent tool derives its worktree directory and branch from the
1751
+ // CONVERSATION id alone, so concurrent sub-agents of one session would collide on a
1752
+ // single worktree. That is HARNESS behaviour, upstream of us.
1753
+ //
1754
+ // TASK_1833 correction (2026-07-31): in THIS repo they no longer collide, and the
1755
+ // previous text here — "two parallel dispatches from the same Ansuz session share one
1756
+ // worktree directory" — is now FALSE. Registering .claude/hooks/worktree-create.js as
1757
+ // a WorktreeCreate hook makes the harness delegate creation entirely to that hook,
1758
+ // which DISCARDS the proposed path and synthesizes wt-<sid8>-<pid> (makeWtName), then
1759
+ // uniquifies the directory and the branch independently. Each hook invocation is its
1760
+ // own `node -e` process so the pid differs per sub-agent; the uniquify loops are what
1761
+ // actually guarantee correctness, since Windows recycles pids aggressively. Measured:
1762
+ // one session produced wt-8c83ecc1-12492 and wt-8c83ecc1-12624 for two concurrent
1763
+ // dispatches, and ten distinct wt-e989b14a-* trees exist from one earlier session.
1764
+ //
1765
+ // So parallel sub-agent dispatch from one Ansuz session IS safe here. Do not cite this
1766
+ // block as a reason to serialize — the stale version of this comment cost a round of
1767
+ // throughput on 2026-07-31 by talking a reader out of parallelizing. The historical
1768
+ // incident (TASK_1610/1611) was NOT collision-by-sharing: an older worktree-create.js
1769
+ // ran `worktree remove --force` for "idempotency" and destroyed a live sibling's
1770
+ // worktree mid-task. That path is gone (TASK_1639); the hook now never claims an
1771
+ // existing path.
1772
+ //
1773
+ // Still true: the description field does not affect the worktree name, and per-TASK
1774
+ // naming (task_<taskid>) requires the formation path via
1775
+ // formations.setupUnitWorktree({ taskId }).
1776
+ const agentParams = isCodex ? undefined : {
1777
+ // Include taskInput so the Agent tool description is unique per task (helps tracing)
1778
+ description: `[${taskInput}] Kenaz subagent (${skill})`,
1779
+ model: dispatchModel,
1780
+ // TASK_1672: omit Agent-tool isolation for cross-project dispatch — its worktree
1781
+ // would be rooted in the core/non-git cwd, not the sub-project repo. TASK_1833:
1782
+ // cross-project isolation is instead provided by the pre-created target-repo
1783
+ // worktree (target_repo_worktree) or by dispatch-lock serialization (serial_lock).
1784
+ ...(isCrossProject ? {} : { isolation: 'worktree' }),
1785
+ // run_in_background: false → Ansuz awaits result directly (no log polling)
1786
+ };
1787
+
1788
+ // TASK_1833: isolation metadata rides NEXT TO agentParams (same reason as
1789
+ // modelTranslation — the Agent tool schema rejects unknown fields). Ansuz
1790
+ // needs it to: merge the target-repo worktree branch after the agent returns,
1791
+ // and to release the serial dispatch lock after merge.
1792
+ const isolation = {
1793
+ mode: iso.mode,
1794
+ source: iso.source,
1795
+ worktreePath: crossWorktree ? crossWorktree.worktreePath : null,
1796
+ branchName: crossWorktree ? crossWorktree.branchName : null,
1797
+ // TASK_2067: true when an existing task/<id> branch (worktree missing,
1798
+ // e.g. a cancelled task resumed) was reused rather than created fresh.
1799
+ reusedBranch: crossWorktree ? !!crossWorktree.reusedBranch : false,
1800
+ // TASK_2067: non-null only when target_repo_worktree creation genuinely
1801
+ // failed and dispatch degraded to serial_lock -- never set for the
1802
+ // reused-branch case above, which is not a degradation.
1803
+ worktreeFallbackReason,
1804
+ serialLock: serialLock
1805
+ ? {
1806
+ lockFile: serialLock.lockFile,
1807
+ // TASK_1859: release contract is now the CLI (executable where
1808
+ // Bash(rm *) is denied); deleting the file stays as the fallback.
1809
+ releaseCommand: `node .formation/tools/dispatch.js --release-lock${projectPath ? ` --project-path "${projectPath}"` : ''}`,
1810
+ note: 'Release after the agent finishes and its work is merged: run releaseCommand (same session; add --force cross-session). Fallback: delete lockFile. Auto-breaks 60min after acquisition.',
1811
+ }
1812
+ : null,
1813
+ // TASK_2176: project's .kenaz/project.yaml verify_offline command, or
1814
+ // null (today's behaviour) when absent. The worktree agent already got
1815
+ // it as a non-authoritative self-check instruction above; this lets the
1816
+ // caller (Ansuz) pass it to verify-and-land.js at landing, where it runs
1817
+ // as the authoritative, serialized gate on the main tree.
1818
+ verifyOffline: iso.verifyOffline || null,
1819
+ };
1820
+
1821
+ // TASK_1815: modelTranslation rides NEXT TO agentParams (not inside it) so
1822
+ // the Agent tool payload stays pure while the caller (Ansuz) still SEES the
1823
+ // requested-vs-emitted model and the granularity loss. Do not fold it into
1824
+ // agentParams — the Agent tool schema would reject unknown fields.
1825
+ // TASK_1859: dispatchMode is the TASK_1813 CONFIG ECHO (what
1826
+ // dashboard-models.json requested: formation|subagent|auto) — do NOT change
1827
+ // its semantics, subagent-bifrost-guard.test.js pins them. effectiveMode is
1828
+ // the path this dispatch ACTUALLY took; this function IS the subagent path,
1829
+ // so consumers reading the payload of a --dispatch-mode=subagent run can see
1830
+ // 'subagent' even when the config echo says 'formation'.
1831
+
1832
+ // TASK_1998 R1a: telemetry — one JSONL line per sub-agent dispatch.
1833
+ // R3: modelSource rides along so dispatch-stats.js can break down turns/sec
1834
+ // by dashboard vs dashboard-by-rigor vs cli without re-deriving it.
1835
+ // Two-axis policy: complexity rides along too, so dispatch-stats.js can
1836
+ // group by (rigor, complexity) instead of rigor alone.
1837
+ if (!dryRun) appendDispatchPromptStats({ taskId: taskInput, rigor: resolution.rigorKey, complexity, formation, promptText, model: dispatchModel, modelSource: resolution.source, projectPath });
1838
+
1839
+ // TASK_2032: mirror headless.js's formation-path auto-activation (~L272-290)
1840
+ // on the subagent path — every gate/guard above has passed and this function
1841
+ // is about to return a real payload, so move the card backlog -> active NOW.
1842
+ // Root cause this fixes: the formation path activates the card before the
1843
+ // agent runs, but this function never did, so a --dispatch-mode=subagent
1844
+ // card sat in backlog/ the whole time the subagent worked — and afterwards
1845
+ // `task-api move <id> done` was rejected ("backlog -> done not allowed"),
1846
+ // forcing a backlog->active->done two-step every time.
1847
+ // Unlike headless.js, this does NOT git-commit the status change: the
1848
+ // subagent never reads the task dir (buildPrompt already inlined taskData
1849
+ // above) and post-complete's merge runs in the main tree, so there is no
1850
+ // worktree-forks-from-stale-HEAD problem to solve here.
1851
+ // Skipped for dryRun (same "no side effects" contract as the resource
1852
+ // leases / worktree / serial lock / telemetry above) and for non-TASK_
1853
+ // (ad-hoc) inputs, which have no card to move.
1854
+ // Non-fatal by design: already-active, an invalid transition, or task-api
1855
+ // being unavailable must never fail a dispatch that has otherwise succeeded
1856
+ // — log one stderr line and continue.
1857
+ if (!dryRun && taskInput && /^TASK_\d+$/i.test(taskInput)) {
1858
+ try {
1859
+ const projectArg = _saRoot !== ROOT ? ` --project-path "${_saRoot}"` : '';
1860
+ execSync(
1861
+ `node "${COLLABORATION_API}"${projectArg} move ${taskInput} active`,
1862
+ { encoding: 'utf8', cwd: _saRoot, timeout: 10000, windowsHide: true, stdio: ['pipe', 'pipe', 'pipe'] }
1863
+ );
1864
+ process.stderr.write(`[dispatch] Auto-activated: ${taskInput} → active/\n`);
1865
+ } catch (e) {
1866
+ // Non-fatal: task may already be active, completed, or in an incompatible state.
1867
+ const msg = (e.stderr || e.message || '').toString().split('\n')[0];
1868
+ process.stderr.write(`[dispatch] Auto-activate skipped: ${msg}\n`);
1869
+ }
1870
+ }
1871
+
1872
+ // TASK_1998 R3: rigor + modelSource ride NEXT TO agentParams (same reason as
1873
+ // modelTranslation/isolation — the Agent tool schema rejects unknown fields
1874
+ // on agentParams itself). rigor is the NORMALIZED key (null/unrecognized →
1875
+ // 'medium') that actually drove model resolution, not the raw card field.
1876
+ // complexity is likewise the normalized CONTEXT-volume key.
1877
+ return {
1878
+ promptText, taskId: taskInput, formation, skill, dispatchMode, effectiveMode: 'subagent',
1879
+ ...(isCodex ? { harness: 'codex', cwd: crossWorktree ? crossWorktree.worktreePath : null, worktreePath: crossWorktree ? crossWorktree.worktreePath : null } : {}),
1880
+ modelTranslation, isolation, ...(agentParams ? { agentParams } : {}), rigor: resolution.rigorKey, complexity, modelSource: resolution.source,
1881
+ ...(dryRun ? { dryRun: true } : {}),
1882
+ };
1883
+ }
1884
+
1885
+ /**
1886
+ * TASK_1833: pre-create an isolated worktree INSIDE the target sub-project repo
1887
+ * for a cross-project sub-agent dispatch. Naming matches the Formation path
1888
+ * (formations.setupUnitWorktree: .formation/worktrees/task_<id>, branch
1889
+ * task/<id>) so post-complete's worktree merge machinery finds it unchanged.
1890
+ * Reuses utils.createWorktree — index.lock wait, retry/backoff, stale-branch
1891
+ * and partial-dir cleanup all included. Throws on final failure (caller falls
1892
+ * back to serialized shared-tree mode — never to unserialized writes).
1893
+ * thrift: no MAX_PARALLEL semaphore / dirty-snapshot here (those live in the
1894
+ * long-lived Formation process; this CLI exits immediately). Sub-agent
1895
+ * cross-project dispatch is Ansuz-driven and low-fanout today — add the
1896
+ * semaphore if parallel cross-project sub-agent dispatch becomes routine.
1897
+ * @param {string} projectPath - target repo root
1898
+ * @param {string} taskInput - TASK_XXX id or free-text description
1899
+ * @returns {{ worktreePath: string, branchName: string }}
1900
+ */
1901
+ function setupSubagentCrossProjectWorktree(projectPath, taskInput) {
1902
+ const idBase = (taskInput && taskInput.startsWith('TASK_'))
1903
+ ? taskInput.toLowerCase()
1904
+ : `adhoc_${Date.now().toString(36)}`;
1905
+ const worktreePath = path.join(projectPath, '.formation', 'worktrees', `task_${idBase}`);
1906
+ const branchName = `task/${idBase}`;
1907
+ // createWorktree logs progress via console.log (fine on the Formation path),
1908
+ // but subagent mode's stdout is machine-readable JSON — redirect to stderr
1909
+ // for the duration of the call so the payload stays parseable.
1910
+ const origLog = console.log;
1911
+ console.log = (...a) => console.error(...a);
1912
+ let created;
1913
+ try {
1914
+ ensureWorktreeDirIgnored(projectPath);
1915
+ created = createWorktree(projectPath, worktreePath, branchName);
1916
+ } finally {
1917
+ console.log = origLog;
1918
+ }
1919
+ // TASK_2067: createWorktree returns { reusedBranch, divergence } when it
1920
+ // attached to a pre-existing task/<id> branch instead of creating a new
1921
+ // one (e.g. a cancelled task resumed) -- surface it so the caller can
1922
+ // report reuse in the dispatch payload instead of only in stderr logs.
1923
+ return {
1924
+ worktreePath,
1925
+ branchName,
1926
+ reusedBranch: !!(created && created.reusedBranch),
1927
+ divergence: (created && created.divergence) || null,
1928
+ };
1929
+ }
1930
+
1931
+ module.exports = { dispatch, getSubagentDispatchParams, checkDispatchScopeGate, releaseDispatchLock, resolveDispatchIsolation, _getProvenSessionId, _getOwnConversationId, _isOwnClaimMarker, _buildCortexContext: buildCortexContext };