kenaz 0.3.18 → 0.3.20

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 (329) hide show
  1. package/core/.claude/commands/agent-worker.md +1 -1
  2. package/core/.claude/commands/architect.md +1 -2
  3. package/core/.claude/commands/spec.md +1 -1
  4. package/core/.claude/commands//347/224/242/345/223/201.md +1 -1
  5. package/core/.claude/hooks/__tests__/task-1977-dedupe-guard.test.js +8 -8
  6. package/core/.claude/skills/architect_agent/SKILL.md +11 -92
  7. package/core/.claude/skills/assessment_agent/SKILL.md +0 -1
  8. package/core/.claude/skills/backend_engineer/SKILL.md +3 -6
  9. package/core/.claude/skills/code_reviewer/SKILL.md +1 -1
  10. package/core/.claude/skills/code_reviewer/patterns.yaml +1 -1
  11. package/core/.claude/skills/designer/SKILL.md +3 -6
  12. package/core/.claude/skills/dev_agent/SKILL.md +30 -491
  13. package/core/.claude/skills/developer/SKILL.md +3 -6
  14. package/core/.claude/skills/feature_agent/SKILL.md +3 -17
  15. package/core/.claude/skills/product_manager/SKILL.md +29 -1064
  16. package/core/.claude/skills/qa_engineer/SKILL.md +12 -17
  17. package/core/.claude/skills/spec_optimizer/SKILL.md +25 -275
  18. package/core/.claude/skills/sre_agent/SKILL.md +3 -6
  19. package/core/.collaboration/README.md +2 -3
  20. package/core/.collaboration/core/task-api.js +5 -138
  21. package/core/.collaboration/docs/CLI.md +0 -2
  22. package/core/.failure/INDEX.yaml +6 -40
  23. package/core/.failure/agent-execution/FAIL-013-search-cwd-drift-and-case-mismatch.yaml +1 -1
  24. package/core/.failure/tools/README.md +9 -227
  25. package/core/.formation/bifrost/launch.js +1 -6
  26. package/core/.formation/bifrost/launch.test.js +1 -1
  27. package/core/.formation/bifrost/shared/ansuz-boot-policy.js +3 -3
  28. package/core/.formation/bifrost/shared/ansuz-boot-policy.test.js +1 -2
  29. package/core/.formation/tools/__tests__/arms.test.js +41 -0
  30. package/core/.formation/tools/__tests__/diagnose-bug.test.js +10 -0
  31. package/core/.formation/tools/__tests__/m1-hmap-convid.test.js +1 -124
  32. package/core/.formation/tools/arms.js +48 -0
  33. package/core/.formation/tools/dispatch.js +24 -15
  34. package/core/.formation/tools/kenaz-stats.js +32 -8
  35. package/core/.formation/tools/kenaz-stats.test.js +15 -2
  36. package/core/.formation/tools/loader.js +17 -140
  37. package/core/.formation/tools/post-complete.js +0 -31
  38. package/core/.formation/tools/prompt.js +16 -1
  39. package/core/.formation/tools/prompt.test.js +20 -0
  40. package/core/.rule/INDEX.yaml +0 -18
  41. package/core/.rule/general/agent-workflow.yaml +14 -164
  42. package/core/.rule/general/project-self-containment.yaml +8 -19
  43. package/core/.rule/general/rust-verify-target.yaml +6 -5
  44. package/core/.rule/general/synapse-code-intelligence.yaml +3 -3
  45. package/core/.specialist/Amelia/capability.yaml +12 -12
  46. package/core/.specialist/Amelia/workflow.yaml +2 -2
  47. package/core/.specialist/Ansuz/SYSTEM_DOC.md +20 -578
  48. package/core/.specialist/Ansuz/cognitive_principles.yaml +2 -3
  49. package/core/.specialist/Ansuz/concepts/boot_rules_summary.yaml +0 -1
  50. package/core/.specialist/Ansuz/concepts/deep_knowledge_pointers.yaml +1 -2
  51. package/core/.specialist/Ansuz/core.yaml +6 -108
  52. package/core/.specialist/Ansuz/guards/lesson_guards.yaml +0 -3
  53. package/core/.specialist/Ansuz/identity_contract.yaml +0 -1
  54. package/core/.specialist/Ansuz/knowledge.yaml +0 -4
  55. package/core/.specialist/Ansuz/rule.yaml +0 -1
  56. package/core/.specialist/Ansuz/tools/handoff-session-identity.test.js +6 -150
  57. package/core/.specialist/tests/runtime-discovery/README.md +1 -1
  58. package/core/.specialist/tools/__tests__/task-2374-usage-counter.test.js +1 -12
  59. package/core/.specialist/tools/ansuz-boot-fast.js +7 -4
  60. package/core/.specialist/tools/ansuz-boot-fast.test.js +10 -3
  61. package/core/.specialist/tools/prompt-files.test.js +1 -0
  62. package/core/.specialist/tools/task-bridge.js +1 -66
  63. package/core/.system/README.md +11 -552
  64. package/core/.system/collaboration/README.md +10 -174
  65. package/core/CLAUDE.md +1 -6
  66. package/core/KENAZ_CORE_VERSION +1 -1
  67. package/core/dev/scripts/js-yaml-resolution.test.js +1 -1
  68. package/core/dev/scripts/peer-identity-e2e.js +402 -0
  69. package/core/dev/scripts/peer-identity-e2e.md +47 -0
  70. package/core/dev/scripts/relay-admin.js +94 -0
  71. package/core/dev/scripts/relay-admin.test.js +131 -0
  72. package/core/dev/scripts/run-rust-tests.js +9 -45
  73. package/core/dev/scripts/rust-verify-worktree.js +4 -4
  74. package/core/dev/scripts/verify-target-dir.js +6 -6
  75. package/core/plugins/kenaz/INVENTORY.md +8 -8
  76. package/core/plugins/kenaz/README.md +10 -0
  77. package/core/plugins/kenaz/commands/architect.md +1 -2
  78. package/core/plugins/kenaz/commands/spec.md +1 -1
  79. package/core/plugins/kenaz/commands//347/224/242/345/223/201.md +1 -1
  80. package/core/plugins/kenaz/guidance.md +1 -1
  81. package/core/plugins/kenaz/hooks/kenaz-hook.js +2 -1
  82. package/core/plugins/kenaz/hooks/sdk-gate.js +9 -0
  83. package/core/plugins/kenaz/scripts/kenaz.test.js +15 -3
  84. package/core/plugins/kenaz/scripts/sync.js +1 -1
  85. package/core/plugins/kenaz/scripts/ygg.js +8 -0
  86. package/core/plugins/kenaz/scripts/ygg.test.js +72 -0
  87. package/core/plugins/kenaz/skills/architect_agent/SKILL.md +11 -92
  88. package/core/plugins/kenaz/skills/assessment_agent/SKILL.md +0 -1
  89. package/core/plugins/kenaz/skills/backend_engineer/SKILL.md +3 -6
  90. package/core/plugins/kenaz/skills/code_reviewer/SKILL.md +1 -1
  91. package/core/plugins/kenaz/skills/code_reviewer/patterns.yaml +1 -1
  92. package/core/plugins/kenaz/skills/designer/SKILL.md +3 -6
  93. package/core/plugins/kenaz/skills/dev_agent/SKILL.md +30 -491
  94. package/core/plugins/kenaz/skills/developer/SKILL.md +3 -6
  95. package/core/plugins/kenaz/skills/feature_agent/SKILL.md +3 -17
  96. package/core/plugins/kenaz/skills/product_manager/SKILL.md +29 -1064
  97. package/core/plugins/kenaz/skills/qa_engineer/SKILL.md +12 -17
  98. package/core/plugins/kenaz/skills/spec_optimizer/SKILL.md +25 -275
  99. package/core/plugins/kenaz/skills/sre_agent/SKILL.md +3 -6
  100. package/core/plugins/kenaz-peer/hooks/register.test.ts +32 -0
  101. package/core/plugins/kenaz-peer/hooks/register.ts +9 -0
  102. package/package.json +6 -6
  103. package/core/.claude/commands/archive.md +0 -24
  104. package/core/.claude/commands/init.md +0 -112
  105. package/core/.claude/commands/legacy_dev.md +0 -18
  106. package/core/.claude/commands/product-review.md +0 -131
  107. package/core/.claude/commands/strategy.md +0 -141
  108. package/core/.claude/commands/sunny.md +0 -1
  109. package/core/.claude/commands//347/224/242/345/223/201/346/252/242/350/246/226.md +0 -129
  110. package/core/.claude/commands//351/200/262/345/272/246.md +0 -15
  111. package/core/.claude/hooks/__tests__/substrate.test.js +0 -122
  112. package/core/.claude/hooks/_substrate-paths.js +0 -95
  113. package/core/.claude/hooks/context-check.js +0 -51
  114. package/core/.claude/hooks/fatigue-check.js +0 -52
  115. package/core/.claude/hooks/handoff-snapshot-on-commit.js +0 -154
  116. package/core/.claude/hooks/handoff-snapshot-on-question.js +0 -158
  117. package/core/.claude/hooks/handoff-staleness.js +0 -197
  118. package/core/.claude/hooks/jev-thalamus-context.js +0 -17
  119. package/core/.claude/hooks/jev-thalamus-context.test.js +0 -41
  120. package/core/.claude/hooks/lease-release.js +0 -119
  121. package/core/.claude/hooks/lease-touch.js +0 -96
  122. package/core/.claude/hooks/reflex-feedback.js +0 -5
  123. package/core/.claude/hooks/session-init.ps1 +0 -49
  124. package/core/.claude/hooks/sound-event.js +0 -70
  125. package/core/.claude/hooks/sound-event.sh +0 -37
  126. package/core/.claude/hooks/stream-delta.js +0 -169
  127. package/core/.claude/no-hooks.settings.json +0 -3
  128. package/core/.claude/skills/legacy_dev/SKILL.md +0 -202
  129. package/core/.claude/skills/sunny/SKILL.md +0 -74
  130. package/core/.collaboration/cli/commands/assign.js +0 -39
  131. package/core/.collaboration/cli/commands/claim.js +0 -33
  132. package/core/.collaboration/cli/commands/complete.js +0 -44
  133. package/core/.collaboration/cli/commands/create.js +0 -110
  134. package/core/.collaboration/cli/commands/get.js +0 -83
  135. package/core/.collaboration/cli/commands/index.js +0 -52
  136. package/core/.collaboration/cli/commands/list.js +0 -51
  137. package/core/.collaboration/cli/commands/lock.js +0 -45
  138. package/core/.collaboration/cli/commands/rebuild.js +0 -39
  139. package/core/.collaboration/cli/commands/search.js +0 -61
  140. package/core/.collaboration/cli/commands/stats.js +0 -61
  141. package/core/.collaboration/cli/commands/transfer.js +0 -41
  142. package/core/.collaboration/cli/commands/unlock.js +0 -48
  143. package/core/.collaboration/cli/formatters/help-formatter.js +0 -70
  144. package/core/.collaboration/cli/formatters/index.js +0 -7
  145. package/core/.collaboration/cli/task-cli.js +0 -46
  146. package/core/.collaboration/cli/utils/arg-parser.js +0 -74
  147. package/core/.collaboration/cli/utils/git-user.js +0 -25
  148. package/core/.collaboration/cli/utils/index.js +0 -9
  149. package/core/.collaboration/cli/utils/output.js +0 -10
  150. package/core/.collaboration/config/default.yaml +0 -189
  151. package/core/.collaboration/core/conflict-resolver.js +0 -461
  152. package/core/.collaboration/core/conflict-resolver.test.js +0 -389
  153. package/core/.collaboration/core/migrate-legacy.js +0 -260
  154. package/core/.collaboration/docs/API.md +0 -787
  155. package/core/.collaboration/docs/ARCHITECTURE.md +0 -596
  156. package/core/.collaboration/docs/FAQ.md +0 -695
  157. package/core/.collaboration/docs/MIGRATION.md +0 -804
  158. package/core/.collaboration/docs/examples/README.md +0 -320
  159. package/core/.collaboration/docs/examples/advanced-queries.js +0 -261
  160. package/core/.collaboration/docs/examples/basic-usage.js +0 -184
  161. package/core/.collaboration/docs/examples/team-workflow.js +0 -352
  162. package/core/.failure/agent-execution/FAIL-001-agent-no-output.yaml +0 -391
  163. package/core/.failure/agent-execution/FAIL-007-pm-lead-wrong-team-invocation.yaml +0 -0
  164. package/core/.failure/agent-execution/FAIL-010-phase0-poem-format-skipped.yaml +0 -28
  165. package/core/.failure/agent-execution/FAIL-010-skipping-cognitive-checkpoint-after-verification.yaml +0 -59
  166. package/core/.failure/agent-execution/FAIL-012-grep-shortcut-during-investigation.yaml +0 -85
  167. package/core/.failure/architecture/FAIL-006-python-version-compatibility.yaml +0 -445
  168. package/core/.failure/pipeline/FAIL-003-queue-pollution.yaml +0 -335
  169. package/core/.failure/pipeline/README.md +0 -95
  170. package/core/.failure/retired/FAIL-009-skipping-synapse-pulse-before-code-change.yaml +0 -49
  171. package/core/.failure/tools/USAGE_GUIDE.md +0 -323
  172. package/core/.failure/tools/check_failures.ps1 +0 -387
  173. package/core/.failure/tools/log_failure.ps1 +0 -474
  174. package/core/.formation/.episode-input.json +0 -10
  175. package/core/.formation/.merge-lock +0 -1
  176. package/core/.formation/lead.yaml +0 -118
  177. package/core/.formation/legacy.bak/designer.yaml +0 -57
  178. package/core/.formation/legacy.bak/pm.yaml +0 -57
  179. package/core/.formation/legacy.bak/qa.yaml +0 -57
  180. package/core/.formation/legacy.bak/review.yaml +0 -62
  181. package/core/.formation/legacy.bak/scheduler.yaml +0 -129
  182. package/core/.formation/legacy.bak/sre.yaml +0 -57
  183. package/core/.formation/role-map.yaml +0 -274
  184. package/core/.formation/roles/_shared/modules/code_review.yaml +0 -98
  185. package/core/.formation/roles/_shared/modules/security.yaml +0 -103
  186. package/core/.formation/roles/_shared/modules/testing.yaml +0 -14
  187. package/core/.formation/roles/backend/role.yaml +0 -93
  188. package/core/.formation/roles/code_reviewer/role.yaml +0 -102
  189. package/core/.formation/roles/database_optimizer/role.yaml +0 -107
  190. package/core/.formation/roles/designer/role.yaml +0 -66
  191. package/core/.formation/roles/developer/role.yaml +0 -75
  192. package/core/.formation/roles/frontend/role.yaml +0 -134
  193. package/core/.formation/roles/incident_response/role.yaml +0 -89
  194. package/core/.formation/roles/qa/role.yaml +0 -89
  195. package/core/.formation/roles/security/role.yaml +0 -87
  196. package/core/.formation/roles/sre/role.yaml +0 -66
  197. package/core/.formation/skills/coordinator.yaml +0 -52
  198. package/core/.formation/solo/diagnosis.yaml +0 -78
  199. package/core/.formation/solo/strategy.yaml +0 -121
  200. package/core/.formation/tests/hello.txt +0 -2
  201. package/core/.formation/tools/coordinator.js +0 -350
  202. package/core/.formation/tools/jev-correction.js +0 -214
  203. package/core/.formation/tools/jev-correction.test.js +0 -178
  204. package/core/.formation/tools/log-reader.js +0 -232
  205. package/core/.formation/tools/revert-daemon-state.js +0 -162
  206. package/core/.formation/tools/test-drift.js +0 -148
  207. package/core/.formation/unit/heimdall.yaml +0 -96
  208. package/core/.formation/unit/plan.yaml +0 -67
  209. package/core/.formation/unit/think.yaml +0 -58
  210. package/core/.kenaz/MUNINN_SNAPSHOT9_EPISODE.json +0 -32
  211. package/core/.kenaz/MUNINN_SNAPSHOT9_RUNE.json +0 -23
  212. package/core/.kenaz/MUNINN_SNAPSHOT9_SUMMARY.md +0 -89
  213. package/core/.kenaz/ash_TASK_1428-20260507.json +0 -14
  214. package/core/.kenaz/muninn_episode_write.ps1 +0 -17
  215. package/core/.kenaz/muninn_snapshot11_rune_candidates.md +0 -63
  216. package/core/.kenaz/muninn_snapshot1_rune_candidates.md +0 -49
  217. package/core/.kenaz/runes_TASK_1428.json +0 -57
  218. package/core/.kenaz/tmp_heimdall_proposal_8d3e392.json +0 -13
  219. package/core/.kenaz/tmp_props.json +0 -1
  220. package/core/.kenaz/tmp_sounddrop_t1_prompt.txt +0 -371
  221. package/core/.rule/MECHANIZED.md +0 -61
  222. package/core/.rule/general/cortex-memory-recall.yaml +0 -446
  223. package/core/.rule/general/pipeline.yaml +0 -246
  224. package/core/.rule/general/sunny-access-control.yaml +0 -60
  225. package/core/.rule/general/system-invariants.yaml +0 -231
  226. package/core/.rule/pipeline/PPL-002-completed-task-archival.yaml +0 -528
  227. package/core/.rule/pipeline/auto-update.yaml +0 -282
  228. package/core/.rule/pipeline/task-execution.yaml +0 -365
  229. package/core/.specialist/Ansuz/concepts/phase_protocol.yaml +0 -65
  230. package/core/.specialist/Ansuz/experiments/boot_ablation_replay.js +0 -197
  231. package/core/.specialist/Ansuz/tools/bootstrap-anchors.js +0 -289
  232. package/core/.specialist/Ansuz/workflow.yaml +0 -1225
  233. package/core/.specialist/experiments/rg_benchmark.js +0 -523
  234. package/core/.specialist/experiments/rg_benchmark_results.json +0 -27
  235. package/core/.specialist/tools/jev-optional-context.js +0 -107
  236. package/core/.specialist/tools/jev-optional-context.test.js +0 -152
  237. package/core/.specialist/tools/memory-action-log.js +0 -839
  238. package/core/.specialist/tools/phase-gate.js +0 -3534
  239. package/core/.specialist/tools/phase-gate.test.js +0 -85
  240. package/core/.specialist/tools/precompute-runner.js +0 -444
  241. package/core/.specialist/tools/rule-engine.js +0 -621
  242. package/core/.specialist/tools/task-bridge-jev.test.js +0 -170
  243. package/core/.synapse/memory-shared.json.sync +0 -1
  244. package/core/.system/agent-skills/README.md +0 -724
  245. package/core/.system/cli-tools/README.md +0 -724
  246. package/core/.system/cortex/MODULES.md +0 -1046
  247. package/core/.system/dashboard/FRONTEND.md +0 -812
  248. package/core/.system/dashboard/README.md +0 -737
  249. package/core/.system/failure/README.md +0 -723
  250. package/core/.system/formation/LEGACY_SKILLS.md +0 -974
  251. package/core/.system/formation/POST_COMPLETE.md +0 -602
  252. package/core/.system/formation/README.md +0 -1094
  253. package/core/.system/formation/TOOLS_REFERENCE.md +0 -1145
  254. package/core/.system/kenaz/README.md +0 -787
  255. package/core/.system/memory/README.md +0 -719
  256. package/core/.system/pipeline/README.md +0 -712
  257. package/core/.system/rule/README.md +0 -794
  258. package/core/.system/sunny/README.md +0 -476
  259. package/core/.system/sunny/RULES.json +0 -89
  260. package/core/.system/sunny/knowledge/INDEX.md +0 -37
  261. package/core/.system/sunny/knowledge/agent-teams-api.md +0 -0
  262. package/core/.system/sunny/knowledge/ansuz-specialist.md +0 -500
  263. package/core/.system/sunny/knowledge/claude-cli-spawn.md +0 -177
  264. package/core/.system/sunny/knowledge/collaboration-api.md +0 -925
  265. package/core/.system/sunny/teammates/README.md +0 -107
  266. package/core/.system/sunny/teammates/how_to_use.yaml +0 -101
  267. package/core/.system/sunny/teammates/tools/headless/launcher.js +0 -318
  268. package/core/.system/sunny/teammates/tools/powershell/launcher.js +0 -241
  269. package/core/.system/sunny/teammates/tools/powershell/start.bat +0 -50
  270. package/core/.system/sunny/teammates/tools/utils/env.js +0 -96
  271. package/core/.system/sunny/teammates/tools/utils/format-output.js +0 -329
  272. package/core/.system/sunny/tools.json +0 -101
  273. package/core/dev/scripts/cleanup-queue.js +0 -184
  274. package/core/dev/scripts/cleanup_queue.js +0 -86
  275. package/core/dev/scripts/legacy/README.md +0 -39
  276. package/core/dev/scripts/legacy/dev_agent_scheduler.ps1.bak +0 -536
  277. package/core/dev/scripts/legacy/multi_agent_scheduler.ps1.bak +0 -1978
  278. package/core/dev/scripts/matrix/CLI_README.md +0 -214
  279. package/core/dev/scripts/matrix/README.md +0 -310
  280. package/core/dev/scripts/matrix/package-lock.json +0 -4266
  281. package/core/dev/scripts/matrix/package.json +0 -55
  282. package/core/dev/scripts/matrix/src/abbreviations.ts +0 -295
  283. package/core/dev/scripts/matrix/src/cli/commands/convert.ts +0 -211
  284. package/core/dev/scripts/matrix/src/cli/commands/create.ts +0 -95
  285. package/core/dev/scripts/matrix/src/cli/commands/delete.ts +0 -102
  286. package/core/dev/scripts/matrix/src/cli/commands/list-tags.ts.wip +0 -140
  287. package/core/dev/scripts/matrix/src/cli/commands/manage-tags.ts.wip +0 -173
  288. package/core/dev/scripts/matrix/src/cli/commands/query.ts +0 -261
  289. package/core/dev/scripts/matrix/src/cli/commands/read.ts +0 -77
  290. package/core/dev/scripts/matrix/src/cli/commands/stats.ts.wip +0 -168
  291. package/core/dev/scripts/matrix/src/cli/commands/tokens.ts.wip +0 -126
  292. package/core/dev/scripts/matrix/src/cli/commands/update.ts +0 -147
  293. package/core/dev/scripts/matrix/src/cli/commands/validate.ts +0 -275
  294. package/core/dev/scripts/matrix/src/cli/index.ts +0 -350
  295. package/core/dev/scripts/matrix/src/cli/utils/file-handler.ts +0 -72
  296. package/core/dev/scripts/matrix/src/cli/utils/logger.ts +0 -65
  297. package/core/dev/scripts/matrix/src/index.ts +0 -62
  298. package/core/dev/scripts/matrix/src/indexer/tag-indexer.ts +0 -165
  299. package/core/dev/scripts/matrix/src/parser.ts +0 -281
  300. package/core/dev/scripts/matrix/src/serializer.ts +0 -151
  301. package/core/dev/scripts/matrix/src/validator.ts +0 -301
  302. package/core/dev/scripts/matrix/tests/abbreviations.test.ts +0 -122
  303. package/core/dev/scripts/matrix/tests/cli.test.ts +0 -177
  304. package/core/dev/scripts/matrix/tests/convert.test.ts +0 -143
  305. package/core/dev/scripts/matrix/tests/parser.test.ts +0 -203
  306. package/core/dev/scripts/matrix/tests/query.test.ts +0 -85
  307. package/core/dev/scripts/matrix/tests/serializer.test.ts +0 -197
  308. package/core/dev/scripts/matrix/tests/validate.test.ts +0 -141
  309. package/core/dev/scripts/matrix/tests/validator.test.ts +0 -167
  310. package/core/dev/scripts/matrix/tsconfig.json +0 -20
  311. package/core/dev/scripts/matrix/types/index.d.ts +0 -111
  312. package/core/dev/scripts/matrix/types/index.d.ts.map +0 -1
  313. package/core/dev/scripts/matrix/types/index.js +0 -8
  314. package/core/dev/scripts/matrix/types/index.js.map +0 -1
  315. package/core/dev/scripts/matrix/types/index.ts +0 -124
  316. package/core/dev/scripts/memory-usage-report.js +0 -152
  317. package/core/dev/scripts/probe/ansuz-scaffold-ablation.js +0 -579
  318. package/core/dev/scripts/probe/ansuz-scaffold-ablation.test.js +0 -244
  319. package/core/dev/scripts/probe/hook-latency-probe.js +0 -315
  320. package/core/dev/scripts/probe/hook-latency-probe.test.js +0 -105
  321. package/core/dev/scripts/probe/prediction-signal-auc.js +0 -483
  322. package/core/dev/scripts/probe/prediction-signal-auc.test.js +0 -200
  323. package/core/dev/scripts/test-pty-ws-tunnel.js +0 -229
  324. package/core/dev/scripts/validate_pipeline.js +0 -197
  325. package/core/dev/spikes/task2145-evidence-20261004/backend-log-excerpt.txt +0 -56
  326. package/core/dev/spikes/task2145-evidence-20261004/graph.shadow +0 -0
  327. package/core/dev/spikes/task2145-evidence-20261004/graph.wal +0 -0
  328. package/core/dev/spikes/task2145-evidence-20261004/graph_corrupt_suspect.marker +0 -1
  329. package/core/plugins/kenaz/commands/strategy.md +0 -141
@@ -41,11 +41,6 @@ categories:
41
41
  description: "架構決策失敗(設計缺陷、技術選型錯誤)"
42
42
  icon: "🏗️"
43
43
 
44
- pipeline:
45
- path: "pipeline/"
46
- description: "Pipeline 系統失敗(任務管理、佇列、統計)"
47
- icon: "⚙️"
48
-
49
44
  data_integrity:
50
45
  path: "data-integrity/"
51
46
  description: "數據完整性問題(JSON 損壞、編碼錯誤)"
@@ -83,7 +78,7 @@ failure_template: |
83
78
 
84
79
  _meta:
85
80
  id: "FAIL-XXX"
86
- category: "agent_execution | code_quality | architecture | pipeline | data_integrity"
81
+ category: "agent_execution | code_quality | architecture | data_integrity"
87
82
  severity: "critical | high | medium | low"
88
83
  date: "YYYY-MM-DD"
89
84
  related_tasks: ["TASK_XXX"]
@@ -118,7 +113,7 @@ failure_template: |
118
113
  - [ ] 檢查項目 1
119
114
  - [ ] 檢查項目 2
120
115
 
121
- ### 三級預防(由 Ansuz Phase 9 prevention_analysis 自動填入)
116
+ ### 三級預防
122
117
  prevention:
123
118
  primary: "防止再發 — 架構加固、測試覆蓋、代碼重構"
124
119
  secondary: "早期偵測 — 監控指標、日誌告警、健康檢查"
@@ -137,18 +132,10 @@ failure_template: |
137
132
  # 載入順序(按嚴重程度)
138
133
  # ============================================================
139
134
  load_order:
140
- - path: "agent-execution/FAIL-001-agent-no-output.yaml"
141
- title: "Agent 執行無輸出問題"
142
- severity: "critical"
143
-
144
135
  - path: "data-integrity/FAIL-002-json-bom.yaml"
145
136
  title: "JSON BOM 編碼問題"
146
137
  severity: "high"
147
138
 
148
- - path: "pipeline/FAIL-003-queue-pollution.yaml"
149
- title: "TASK_QUEUE 污染問題"
150
- severity: "high"
151
-
152
139
  - path: "agent-execution/FAIL-004_agent_platform_specific_commands.md"
153
140
  title: "Agent 使用平台特定命令導致失敗"
154
141
  severity: "high"
@@ -157,18 +144,10 @@ load_order:
157
144
  title: "背景 Agent 無寫入權限"
158
145
  severity: "critical"
159
146
 
160
- - path: "architecture/FAIL-006-python-version-compatibility.yaml"
161
- title: "Python 3.14 依賴兼容性問題"
162
- severity: "high"
163
-
164
147
  - path: "agent-execution/FAIL-008-bypass-api-direct-yaml-write.yaml"
165
148
  title: "Agent 繞過 API 直接寫 YAML 任務檔案"
166
149
  severity: "high"
167
150
 
168
- - path: "agent-execution/FAIL-010-phase0-poem-format-skipped.yaml"
169
- title: "Phase 0 記憶之烏鴉歸巢段落持續缺失"
170
- severity: "medium"
171
-
172
151
  - path: "agent-execution/FAIL-014-shared-worktree-premature-death-verdict.yaml"
173
152
  title: "並發 Agent worktree 共用路徑被提前清理 + 沉默誤判死亡 → 重複派工"
174
153
  severity: "high"
@@ -178,19 +157,11 @@ load_order:
178
157
  # 統計數據
179
158
  # ============================================================
180
159
  statistics:
181
- total_failures: 10
160
+ total_failures: 5
182
161
  by_category:
183
- agent_execution: 6
162
+ agent_execution: 4
184
163
  data_integrity: 1
185
- pipeline: 1
186
- architecture: 1
187
- by_severity:
188
- critical: 2
189
- high: 5
190
- medium: 1
191
- low: 0
192
- resolved: 7
193
- converted_to_rules: 2 # 已轉化為 .rule/ 規則
164
+ resolved: 5
194
165
 
195
166
  # ============================================================
196
167
  # Agent 使用指南
@@ -220,12 +191,7 @@ system_integration:
220
191
  priority_order: |
221
192
  1. .rule/ (最高優先級 - 必須遵守的規則)
222
193
  2. .failure/ (失敗經驗 - 應避免的模式)
223
- 3. .memory/ (經驗記錄 - 一般性筆記)
224
- 4. CLAUDE.md (專案指導)
194
+ 3. CLAUDE.md (專案指導)
225
195
 
226
196
  workflow: |
227
197
  失敗 → 記錄到 .failure/ → 分析根因 → 如重複發生 → 提升為 .rule/
228
-
229
- example:
230
- failure: "FAIL-003: TASK_QUEUE 被 completed 任務污染"
231
- rule: "PPL-002: 已完成任務必須封存到 .memory/"
@@ -72,7 +72,7 @@ prevention:
72
72
  → Grep -i pattern path=ABSOLUTE_PATH (找內容)
73
73
 
74
74
  「我想理解一個概念的拓撲」
75
- → synapse_search / synapse_pulse (理解關係)
75
+ → kenaz_lsp_callers / kenaz_lsp_references (理解關係)
76
76
 
77
77
  「我搜了但什麼都沒找到」
78
78
  → 檢查 cwd(Bash pwd)
@@ -1,230 +1,12 @@
1
- # 🔧 Failure Learning Tools
1
+ # .failure/tools
2
2
 
3
- ## 目錄說明
3
+ Small Node helpers for the JSON/BOM failure pattern (`data-integrity/FAIL-002-json-bom.yaml`). All take a file or directory path.
4
4
 
5
- 此目錄包含自動化工具腳本,幫助 Agent 和開發者快速記錄和檢查失敗經驗。
5
+ | Tool | Use |
6
+ |---|---|
7
+ | `check_bom.js <file\|dir> [--recursive]` | Report files that start with a UTF-8 BOM |
8
+ | `remove_bom.js <file>` | Strip the BOM |
9
+ | `fix_json.js <file>` | Strip the BOM, validate, and reformat a JSON file |
10
+ | `validate_json.js <file>` | Exit non-zero if the file is not valid JSON |
6
11
 
7
- ## 工具列表
8
-
9
- ### 1. log_failure.ps1
10
- 自動化建立失敗記錄文件的 PowerShell 腳本。
11
-
12
- #### 使用方式
13
- ```powershell
14
- # 互動式建立失敗記錄
15
- .\.failure\tools\log_failure.ps1
16
-
17
- # 指定參數建立
18
- .\.failure\tools\log_failure.ps1 `
19
- -Category "pipeline" `
20
- -Title "TASK_QUEUE 污染問題" `
21
- -Severity "high" `
22
- -TaskID "TASK_088"
23
- ```
24
-
25
- #### 功能
26
- - 自動生成 FAIL-XXX ID(根據 INDEX.yaml 中的最大 ID)
27
- - 根據分類選擇正確的目錄
28
- - 使用標準模板建立 YAML 文件
29
- - 自動更新 INDEX.yaml 的 load_order 和統計數據
30
- - 支援互動式和參數化兩種模式
31
-
32
- ### 2. check_failures.ps1
33
- 檢查當前任務是否匹配已知失敗模式的腳本。
34
-
35
- #### 使用方式
36
- ```powershell
37
- # 檢查特定任務的失敗模式
38
- .\.failure\tools\check_failures.ps1 -TaskID "TASK_077"
39
-
40
- # 檢查特定類型的任務
41
- .\.failure\tools\check_failures.ps1 -AgentType "developer"
42
-
43
- # 檢查特定路徑的失敗模式
44
- .\.failure\tools\check_failures.ps1 -ScopePath "dev/pipeline/"
45
-
46
- # 使用關鍵詞搜尋
47
- .\.failure\tools\check_failures.ps1 -Keywords "JSON,BOM,encoding"
48
-
49
- # 過濾特定分類和嚴重程度
50
- .\.failure\tools\check_failures.ps1 -Category "pipeline" -Severity "critical"
51
- ```
52
-
53
- #### 功能
54
- - 根據任務 ID 自動載入 TASK_QUEUE.json 詳情
55
- - 根據 agent_type 匹配相關失敗記錄
56
- - 根據 scope_paths 匹配相關失敗記錄
57
- - 支援關鍵詞模糊搜尋
58
- - 輸出預防檢查清單和解決方案參考
59
- - 按嚴重程度排序顯示結果
60
-
61
- ### 3. validate_json.js
62
- 驗證 JSON 文件完整性的 Node.js 腳本。
63
-
64
- #### 使用方式
65
- ```bash
66
- # 驗證單個文件
67
- node .failure/tools/validate_json.js dev/pipeline/TASK_QUEUE.json
68
- ```
69
-
70
- #### 功能
71
- - 驗證 JSON 語法正確性
72
- - 檢測 BOM (Byte Order Mark)
73
- - 提供錯誤診斷提示
74
-
75
- ### 3.1 remove_bom.js
76
- 移除 UTF-8 文件開頭的 BOM (Byte Order Mark)。
77
-
78
- #### 使用方式
79
- ```bash
80
- # 移除 BOM
81
- node .failure/tools/remove_bom.js dev/pipeline/TASK_QUEUE.json
82
- ```
83
-
84
- #### 功能
85
- - 檢測並移除 BOM (0xFEFF)
86
- - 不修改其他內容
87
- - 無 BOM 時不做任何操作
88
-
89
- ### 3.2 fix_json.js
90
- 一鍵修復 JSON 文件(移除 BOM + 驗證 + 重新格式化)。
91
-
92
- #### 使用方式
93
- ```bash
94
- # 修復 JSON 文件
95
- node .failure/tools/fix_json.js dev/pipeline/TASK_QUEUE.json
96
- ```
97
-
98
- #### 功能
99
- - 自動移除 BOM
100
- - 驗證 JSON 語法
101
- - 重新格式化(統一縮排 2 空格)
102
- - 寫回無 BOM 的 UTF-8 文件
103
-
104
- ### 3.3 check_bom.js
105
- 批量檢查 JSON 文件是否有 BOM(用於 CI/CD 或 pre-commit hook)。
106
-
107
- #### 使用方式
108
- ```bash
109
- # 檢查單個文件
110
- node .failure/tools/check_bom.js dev/pipeline/TASK_QUEUE.json
111
-
112
- # 遞迴檢查目錄中所有 JSON 文件
113
- node .failure/tools/check_bom.js dev/pipeline --recursive
114
- ```
115
-
116
- #### 功能
117
- - 批量檢查 JSON 文件
118
- - 遞迴掃描目錄(使用 --recursive)
119
- - 列出所有有 BOM 的文件
120
- - 退出碼:0(無 BOM)或 1(檢測到 BOM)
121
-
122
- #### Pre-commit Hook 整合
123
- ```bash
124
- #!/bin/bash
125
- # .git/hooks/pre-commit
126
- node .failure/tools/check_bom.js dev/pipeline --recursive || exit 1
127
- ```
128
-
129
- ### 4. failure-report.ps1 (計劃中)
130
- 生成失敗經驗報告的腳本。
131
-
132
- #### 使用方式
133
- ```powershell
134
- # 生成完整報告
135
- .\.failure\tools\failure-report.ps1
136
-
137
- # 只生成特定分類的報告
138
- .\.failure\tools\failure-report.ps1 -Category "pipeline"
139
-
140
- # 只生成特定嚴重程度的報告
141
- .\.failure\tools\failure-report.ps1 -Severity "critical,high"
142
-
143
- # 輸出為 Markdown 格式
144
- .\.failure\tools\failure-report.ps1 -Format "markdown" -Output "failure-report.md"
145
- ```
146
-
147
- #### 功能(計劃中)
148
- - 統計失敗記錄數量
149
- - 按分類和嚴重程度分組
150
- - 列出已轉化為規則的失敗
151
- - 生成 Markdown 報告
152
-
153
- ### 5. failure-to-rule.ps1 (計劃中)
154
- 將重複發生的失敗轉化為規則的輔助工具。
155
-
156
- #### 使用方式
157
- ```powershell
158
- # 檢查哪些失敗應該轉化為規則
159
- .\.failure\tools\failure-to-rule.ps1 -Analyze
160
-
161
- # 將特定失敗轉化為規則
162
- .\.failure\tools\failure-to-rule.ps1 -FailureID "FAIL-003" -RuleID "PPL-002"
163
- ```
164
-
165
- #### 功能(計劃中)
166
- - 分析失敗記錄,建議哪些應該轉化為規則
167
- - 自動生成規則文件草稿
168
- - 更新失敗記錄的 `converted_to_rules` 狀態
169
- - 更新 INDEX.yaml 統計數據
170
-
171
- ## 開發新工具
172
-
173
- 如果需要開發新的失敗學習工具,請遵循以下指南:
174
-
175
- ### 1. 工具命名規範
176
- - PowerShell 腳本:`action-noun.ps1`(如 `check-failure-patterns.ps1`)
177
- - Node.js 腳本:`action-noun.js`(如 `validate-json.js`)
178
- - Python 腳本:`action_noun.py`(如 `analyze_failures.py`)
179
-
180
- ### 2. 必須包含的功能
181
- - **幫助訊息**:`-Help` 或 `--help` 參數
182
- - **錯誤處理**:優雅處理錯誤,提供清晰的錯誤訊息
183
- - **日誌輸出**:使用一致的日誌格式
184
- - **返回碼**:成功返回 0,失敗返回非 0
185
-
186
- ### 3. 文檔要求
187
- - 在此 README.md 中添加工具說明
188
- - 在腳本開頭添加註解說明用途和使用方式
189
- - 提供使用範例
190
-
191
- ### 4. 測試要求
192
- - 提供測試用例
193
- - 在 `.failure/tools/tests/` 目錄中
194
-
195
- ## 工具使用最佳實踐
196
-
197
- ### Agent 使用場景
198
-
199
- #### 任務開始前
200
- ```powershell
201
- # 檢查相關失敗模式
202
- .\.failure\tools\check_failures.ps1 -TaskID $TASK_ID
203
- ```
204
-
205
- #### 任務執行中
206
- ```bash
207
- # 驗證 JSON 文件
208
- node .failure/tools/validate_json.js dev/pipeline/TASK_QUEUE.json
209
- ```
210
-
211
- #### 任務失敗後
212
- ```powershell
213
- # 建立失敗記錄
214
- .\.failure\tools\log_failure.ps1 -Interactive
215
- ```
216
-
217
- ### 定期維護
218
- ```powershell
219
- # 每週生成失敗報告
220
- .\failure\tools\failure-report.ps1 -Output "weekly-failure-report.md"
221
-
222
- # 分析哪些失敗應該轉化為規則
223
- .\failure\tools\failure-to-rule.ps1 -Analyze
224
- ```
225
-
226
- ## 相關資源
227
-
228
- - **失敗記錄索引**:`.failure/INDEX.yaml`
229
- - **規則系統**:`.rule/INDEX.yaml`
230
- - **Agent 工作流程**:`.rule/general/agent-workflow.yaml`
12
+ Looking up known failures: read `.failure/INDEX.yaml`, then Grep `.failure/` for the task's scope or error text. Record a new failure by adding a YAML file from the template in INDEX.yaml and listing it in `load_order`; lessons that are not reproducible failure patterns go to `kenaz learn add`.
@@ -286,12 +286,7 @@ function renderOverride(prompt, bootContext, { policy = BOOT_POLICY, projectPath
286
286
  const content = `${projectInstruction}${bootContext}${memoryStartupDoc}${codexDdxInjection}You have been activated as ${policy.specialist} via Bifröst.
287
287
 
288
288
  IMPORTANT — Shell compatibility (you are running under Codex which uses PowerShell on Windows):
289
- - When calling phase-gate.js exit with --data, do NOT pass JSON inline. PowerShell mangles JSON quotes.
290
- - Instead: write JSON to a temp file, then use --data-file=path. Example:
291
- 1. Write: Set-Content -Path _phase_data.json -Value '{"ash_loaded":true,"poem_displayed":true,"session_handoff_loaded":false}'
292
- 2. Run: node .specialist/tools/phase-gate.js exit --phase=0 --data-file=_phase_data.json
293
- 3. Cleanup: Remove-Item _phase_data.json
294
- - This applies to ALL phase-gate.js exit calls, not just Phase 0.
289
+ - Do not pass inline JSON on the command line; PowerShell mangles JSON quotes. Write it to a temp file and pass the path instead.
295
290
 
296
291
  ${prompt}
297
292
 
@@ -104,7 +104,7 @@ test('override ends with fast precedence and retains full project pin', () => {
104
104
  assert.equal((fast.match(/## Codex Bootstrap Policy/g) || []).length, 1);
105
105
  assert.ok(fast.includes(`projectPath="${projectPath}"`));
106
106
  const full = api.renderOverride('fixture', '', { projectPath, policy: resolveBootPolicy({ depth: 'kernel' }) });
107
- assert.ok(full.includes(`--project-path="${projectPath}"`));
107
+ assert.ok(full.includes(`projectPath="${projectPath}"`));
108
108
  assert.match(full, /HALT and emit recovery/);
109
109
  assert.doesNotMatch(full, /Ansuz fast boot/);
110
110
  });
@@ -19,11 +19,11 @@ function renderBootstrap({ policy, projectPath, port = '18080', contextual = fal
19
19
  const fast = [
20
20
  'Ansuz fast boot (elixir) is the default. This bootstrap policy supersedes any older instruction to run Phase 0, including the Phase 0 sentence inside elixir.',
21
21
  'Check kenaz_ping with the active projectPath when available. If unavailable, report that the Kenaz server is unavailable and continue only read-only inspection and analysis using local evidence.',
22
- 'Lightweight Phase 0 uses the supplied boot context and local project evidence; do not run phase-gate Phase 0 or its boot rituals in fast mode. This also supersedes legacy handoff instructions that promise Phase 0 archival. When offline, defer state-changing execution and memory-dependent work until the required service is restored.',
22
+ 'Lightweight Phase 0 uses the supplied boot context and local project evidence; do not run Phase 0 boot rituals in fast mode. This also supersedes legacy handoff instructions that promise Phase 0 archival. When offline, defer state-changing execution and memory-dependent work until the required service is restored.',
23
23
  'Existing authorization, scope, verification, task tracking, and merge restrictions remain in force.',
24
24
  ].join('\n');
25
- const command = `node .specialist/tools/phase-gate.js enter --phase=0 --specialist=${(policy?.specialist || 'Ansuz').toLowerCase()}${projectPath ? ` --project-path="${projectPath}"` : ''}`;
26
- const full = `Before running phase-gate enter, call kenaz_ping with the active projectPath. If it errors or times out, HALT and emit recovery: confirm Kenaz Dashboard on port ${port}, re-run setup-codex, and restart the Codex session.\nExecute Phase 0 initialization now: run \`${command}\` and follow its checklist.`;
25
+ const full = `Before starting Phase 0, call kenaz_ping with the active projectPath${projectPath ? ` ("${projectPath}")` : ''}. If it errors or times out, HALT and emit recovery: confirm the Kenaz server on port ${port}, re-run setup-codex, and restart the Codex session.
26
+ Execute Phase 0 initialization now using the supplied boot context and local project evidence.`;
27
27
  if (contextual) return `## Codex Bootstrap Policy\n\nFor Ansuz without an explicit full boot or legacy depth:\n${fast}\n\nFor explicit --full / --boot-mode full or kernel depth, and for other specialists: retain the full bootstrap guard; call kenaz_ping before Phase 0 and HALT with recovery instructions if it is unavailable. Use the active specialist and project-path for Phase 0.\n`;
28
28
  return `## Codex Bootstrap Policy (${policy.mode})\n\n${policy.mode === 'fast' ? fast : full}\n`;
29
29
  }
@@ -28,8 +28,7 @@ test('renderer preserves full project pin and limits fast offline work without r
28
28
  const projectPath = 'C:\\example project\\quotation';
29
29
  const full = renderBootstrap({ policy: resolveBootPolicy({ full: true }), projectPath });
30
30
  assert.match(full, /HALT/);
31
- assert.ok(full.includes(`--project-path="${projectPath}"`));
32
- assert.match(full, /--specialist=ansuz/);
31
+ assert.ok(full.includes(`"${projectPath}"`));
33
32
  const fast = renderBootstrap({ policy: resolveBootPolicy() });
34
33
  assert.match(fast, /Lightweight Phase 0/);
35
34
  assert.match(fast, /supersedes any older instruction/);
@@ -0,0 +1,41 @@
1
+ // TASK_2440: arm registry. Usage: node .formation/tools/__tests__/arms.test.js
2
+ const assert = require('assert');
3
+ const { ARMS, assignArms } = require('../arms');
4
+ const D = require('../dispatch');
5
+
6
+ // Control: the hash exactly as dispatch.js had it before the registry (TASK_2429 / TASK_2439).
7
+ function oldHash(s) { let h = 2166136261; for (const ch of String(s)) { h ^= ch.charCodeAt(0); h = Math.imul(h, 16777619) >>> 0; } return (h >>> 7) % 2 === 0; }
8
+ const NOW = Date.parse('2026-10-20');
9
+ const all = { bug: true, criteria: true };
10
+
11
+ for (let i = 1; i < 400; i++) {
12
+ const id = 'TASK_' + i;
13
+ const a = assignArms(id, all, { now: NOW });
14
+ assert.strictEqual(a.diagnose, oldHash(id) ? 'with' : 'without', id);
15
+ assert.strictEqual(a.contract, oldHash('contract:' + id) ? 'contract' : 'generic', id);
16
+ assert.strictEqual(D.diagnoseArmFor(id), a.diagnose);
17
+ assert.strictEqual(D.contractArmFor(id), a.contract);
18
+ }
19
+
20
+ // Two arms are independent (not always agreeing) and eligibility gates each one.
21
+ let agree = 0; for (let i = 1; i < 400; i++) { const a = assignArms('TASK_' + i, all, { now: NOW }); if ((a.diagnose === 'with') === (a.contract === 'contract')) agree++; }
22
+ assert.ok(agree > 120 && agree < 280, 'independent: ' + agree);
23
+ assert.deepStrictEqual(Object.keys(assignArms('TASK_5', { bug: false, criteria: true }, { now: NOW })), ['contract']);
24
+ assert.deepStrictEqual(assignArms('TASK_5', { bug: false, criteria: false }, { now: NOW }), {});
25
+
26
+ // Dates: before start and after end nothing is assigned; a forced override still works.
27
+ const fake = [{ name: 'x', field: 'x_arm', on: 'new', off: 'old', salt: 'x:', applies: 'bug', start: '2026-10-15', end: '2026-10-20' }];
28
+ const run = (now, overrides) => assignArms('TASK_1', { bug: true }, { now, arms: fake, overrides });
29
+ assert.deepStrictEqual(run(Date.parse('2026-10-14')), {});
30
+ assert.ok(run(Date.parse('2026-10-20T12:00:00Z')).x);
31
+ assert.deepStrictEqual(run(Date.parse('2026-10-21')), {});
32
+ assert.strictEqual(run(Date.parse('2026-10-21'), { x: 'on' }).x, 'new');
33
+ assert.ok(ARMS.every((a) => a.decide && a.minSample > 0 && a.metric));
34
+
35
+ // The dispatch record carries every arm.
36
+ const fs = require('fs'), os = require('os'), path = require('path');
37
+ const sb = fs.mkdtempSync(path.join(os.tmpdir(), 'arms-'));
38
+ D.appendDispatchPromptStats({ taskId: 'TASK_3', promptText: 'p', formation: 'unit', model: 'm', projectPath: sb, arms: { diagnose: 'with', contract: 'generic' } });
39
+ const rec = JSON.parse(fs.readFileSync(path.join(sb, '.kenaz', 'specialist', 'dispatch_prompt_stats.jsonl'), 'utf8').trim());
40
+ assert.deepStrictEqual(rec.arms, { diagnose: 'with', contract: 'generic' });
41
+ console.log('arms.test.js ok');
@@ -66,6 +66,16 @@ if (bug && feat) {
66
66
  const fOn = dry(feat, ['--diagnose', 'on']); const fOff = dry(feat, ['--diagnose', 'off']);
67
67
  check('non-bug: no section, no arm, prompt identical whatever --diagnose says', !!fOn.promptText && !fOn.promptText.includes('## Bug diagnosis') && fOn.diagnoseArm === undefined && fOn.promptText === fOff.promptText, JSON.stringify(fOn).slice(0, 300));
68
68
  check('with-arm prompt = without-arm prompt + section only', !!on.promptText && !!off.promptText && on.promptText === off.promptText + '\n\n' + D.BUG_DIAGNOSIS_SECTION + '\n', '');
69
+ // TASK_2439: report-contract arm (independent of the diagnosis arm)
70
+ check('contract arm stable + forced', D.contractArmFor('TASK_2439') === D.contractArmFor('TASK_2439') && D.contractArmFor('TASK_1', 'on') === 'contract' && D.contractArmFor('TASK_1', 'off') === 'generic', '');
71
+ let cN = 0; for (let i = 1000; i < 1200; i++) if (D.contractArmFor('TASK_' + i) === 'contract') cN++;
72
+ check('contract split roughly 50/50', cN > 60 && cN < 140, String(cN));
73
+ const cOn = dry(feat, ['--contract', 'on']); const cOff = dry(feat, ['--contract', 'off']);
74
+ check('--contract on: numbered criteria + contractArm', cOn.contractArm === 'contract' && cOn.promptText.includes('1. a1\n2. a2\n3. a3\n'), JSON.stringify(cOn).slice(0, 300));
75
+ check('--contract off: generic arm, no numbered criteria', cOff.contractArm === 'generic' && !cOff.promptText.includes('not verified +'), JSON.stringify(cOff).slice(0, 300));
76
+ D.appendDispatchPromptStats({ taskId: 'TASK_8', promptText: 'p', formation: 'unit', model: 'm', projectPath: SB, diagnoseArm: 'with', contractArm: 'contract' });
77
+ const last = fs.readFileSync(path.join(SB, '.kenaz', 'specialist', 'dispatch_prompt_stats.jsonl'), 'utf8').trim().split('\n').pop();
78
+ check('record: contract_arm next to diagnose_arm', JSON.parse(last).contract_arm === 'contract' && JSON.parse(last).diagnose_arm === 'with', last);
69
79
  }
70
80
 
71
81
  try { fs.rmSync(SB, { recursive: true, force: true }); } catch { /* best effort */ }
@@ -1,5 +1,5 @@
1
1
  // TASK_1764 AMEND + TASK_1766 validation: scratch_<convId>.json as bind source.
2
- // Tests REG-0/1/2, T1-T5, T8 (TASK_1764), T9-T14 (TASK_1766 BUG-8/9/10).
2
+ // Tests REG-0, T11 (resolveOwnBinding), T15 (dispatch scope gate). The lease-touch/lease-release hook cases were removed with those hooks.
3
3
  // Usage: node .formation/tools/__tests__/m1-hmap-convid.test.js
4
4
  // Exit 0 = all pass, non-zero = failure.
5
5
  'use strict';
@@ -17,8 +17,6 @@ function resolveRoot() {
17
17
  throw new Error('Cannot resolve root from ' + __dirname);
18
18
  }
19
19
  const WT = resolveRoot();
20
- const LEASE_TOUCH = path.join(WT, '.claude/hooks/lease-touch.js');
21
- const LEASE_RELEASE = path.join(WT, '.claude/hooks/lease-release.js');
22
20
  const STREAM_LEASE = path.join(WT, '.specialist/tools/stream-lease.js');
23
21
  const SESSION_IDENT = path.join(WT, '.claude/hooks/_session-identity.js');
24
22
  const SB = path.join(os.tmpdir(), 'hmap_convid_' + process.pid);
@@ -34,7 +32,6 @@ function check(name, cond, detail) {
34
32
  cond ? pass++ : fail++;
35
33
  }
36
34
  const baseEnv = { ...process.env, CLAUDE_PROJECT_DIR: SB, KENAZ_SOURCE_DIR: SB };
37
- function runHook(hp, sj) { return cp.spawnSync(process.execPath, [hp], { input: JSON.stringify(sj), encoding: 'utf8', env: baseEnv, timeout: 5000 }); }
38
35
  function sbSL(a) { return cp.spawnSync(process.execPath, [path.join(SB, '.specialist/tools/stream-lease.js'), ...a], { encoding: 'utf8', env: baseEnv, timeout: 5000 }); }
39
36
  function readHmap(id) { try { return JSON.parse(fs.readFileSync(path.join(SB, '.kenaz/specialist/sessions/hmap_' + id + '.json'), 'utf8')); } catch { return null; } }
40
37
  function hmapExists(id) { return fs.existsSync(path.join(SB, '.kenaz/specialist/sessions/hmap_' + id + '.json')); }
@@ -52,96 +49,6 @@ console.log('\n--- REG-0: register writes scratch ---');
52
49
  check('REG-0b: scratch.session_id', sc&&sc.session_id===s, JSON.stringify(sc));
53
50
  check('REG-0c: scratch.conversation_id', sc&&sc.conversation_id===c, JSON.stringify(sc));
54
51
  try{sbSL(['release','--session-id='+s]);}catch(_){} }
55
- // --- REG-1: hmap bind source is scratch (TASK_1766) ---
56
- console.log('\n--- REG-1: hmap bind source is scratch ---');
57
- { const cA='conv-aaa-111', sA='sid-aaa-001'; reg(sA,cA);
58
- runHook(LEASE_TOUCH, { session_id: 'harness-abc', transcript_path: '/fake/'+cA+'.jsonl' });
59
- const h=readHmap(cA);
60
- check('REG-1a: hmap created after first touch', !!h, 'file not found');
61
- check('REG-1b: hmap.conversation_id', h&&h.conversation_id===cA, JSON.stringify(h));
62
- check('REG-1c: hmap.boot_sid=sA', h&&h.boot_sid===sA, JSON.stringify(h));
63
- check('REG-1d: no hmap_harness-abc', !fs.existsSync(path.join(SB,'.kenaz/specialist/sessions/hmap_harness-abc.json')),'');
64
- runHook(LEASE_TOUCH, { session_id: 'harness-xyz', transcript_path: '/fake/'+cA+'.jsonl' });
65
- const h2=readHmap(cA);
66
- check('REG-2a: hmap still present after rotated session_id', !!h2,'');
67
- check('REG-2b: boot_sid unchanged', h2&&h2.boot_sid===sA, JSON.stringify(h2));
68
- try{sbSL(['release','--session-id='+sA]);}catch(_){} }
69
- // --- T1: transcript conv has no scratch -> no bind ---
70
- console.log('\n--- T1: transcript conv has no scratch -> no bind ---');
71
- { const cA='conv-aaa-bind-guard', cB='conv-bbb-different', sA='sid-t1-aaa'; reg(sA,cA);
72
- runHook(LEASE_TOUCH, { transcript_path: '/fake/'+cB+'.jsonl' });
73
- check('T1: no hmap for convBBB (no scratch)', !hmapExists(cB), 'hmap_'+cB+' created');
74
- try{sbSL(['release','--session-id='+sA]);}catch(_){} }
75
- // --- T2: lease-release resolves hmap by convId ---
76
- console.log('\n--- T2: lease-release resolves hmap by convId ---');
77
- { const cC='conv-ccc-release', sC='sid-ccc-003'; reg(sC,cC); writeHmap(cC,sC);
78
- check('T2-pre: sC lease exists', leaseExists(sC), '');
79
- runHook(LEASE_RELEASE, { hook_event_name:'SessionEnd', source:'logout', transcript_path:'/fake/'+cC+'.jsonl' });
80
- check('T2: lease removed', !leaseExists(sC), 'still present');
81
- check('T2: hmap cleaned', !hmapExists(cC), ''); }
82
- // --- T3: SessionEnd source=resume -> no release ---
83
- console.log('\n--- T3: SessionEnd source=resume -> no release ---');
84
- { const cD='conv-ddd-resume', sD='sid-ddd-004'; reg(sD,cD); writeHmap(cD,sD);
85
- check('T3-pre: sD lease exists', leaseExists(sD), '');
86
- runHook(LEASE_RELEASE, { hook_event_name:'SessionEnd', source:'resume', transcript_path:'/fake/'+cD+'.jsonl' });
87
- check('T3: lease NOT released on source=resume', leaseExists(sD), 'deleted');
88
- check('T3: hmap NOT cleaned', hmapExists(cD), '');
89
- try{sbSL(['release','--session-id='+sD]);}catch(_){} }
90
- // --- T4: no transcript_path -> headless no-op (BUG-10) ---
91
- console.log('\n--- T4: no transcript_path -> headless no-op ---');
92
- { const sH='sid-headless-005'; reg(sH,null); writeStream(sH,null);
93
- const t4=runHook(LEASE_TOUCH, { tool_name:'UserPromptSubmit' });
94
- check('T4: hook exits cleanly', t4.status===0||t4.signal===null, 'status='+t4.status);
95
- try{sbSL(['release','--session-id='+sH]);}catch(_){} }
96
- // --- T5: SessionEnd no transcript_path -> no-op ---
97
- console.log('\n--- T5: SessionEnd no transcript_path -> no-op ---');
98
- { const cE='conv-eee-noop', sE='sid-eee-006'; reg(sE,cE); writeStream(sE,cE);
99
- check('T5-pre: sE lease exists', leaseExists(sE), '');
100
- runHook(LEASE_RELEASE, { hook_event_name:'SessionEnd', source:'logout' });
101
- check('T5: lease present (no transcript_path -> no-op)', leaseExists(sE), 'deleted');
102
- try{sbSL(['release','--session-id='+sE]);}catch(_){} }
103
- // --- T8: compact rotation - session_id rotates, hmap key stays convId ---
104
- console.log('\n--- T8: compact rotation ---');
105
- { const cF='conv-fff-compact', sF1='sid-fff-pre-compact', sF2='sid-fff-post-compact';
106
- reg(sF1,cF);
107
- runHook(LEASE_TOUCH, { session_id:sF1, transcript_path:'/fake/'+cF+'.jsonl' });
108
- const hPre=readHmap(cF);
109
- check('T8-pre: hmap written with sF1', hPre&&hPre.boot_sid===sF1, JSON.stringify(hPre));
110
- reg(sF2,cF);
111
- runHook(LEASE_TOUCH, { session_id:sF2, transcript_path:'/fake/'+cF+'.jsonl' });
112
- const hPost=readHmap(cF);
113
- check('T8-post: hmap still exists', !!hPost, 'missing');
114
- check('T8-post: boot_sid unchanged (sF1)', hPost&&hPost.boot_sid===sF1, JSON.stringify(hPost));
115
- check('T8-post: no orphan hmap for sF2', !fs.existsSync(path.join(SB,'.kenaz/specialist/sessions/hmap_'+sF2+'.json')), '');
116
- check('T8-pre-release: sF1 lease exists', leaseExists(sF1), '');
117
- runHook(LEASE_RELEASE, { hook_event_name:'SessionEnd', source:'logout', transcript_path:'/fake/'+cF+'.jsonl' });
118
- check('T8: sF1 lease removed', !leaseExists(sF1), 'sF1.json still exists');
119
- check('T8: hmap cleaned', !hmapExists(cF), '');
120
- try{sbSL(['release','--session-id='+sF2]);}catch(_){} }
121
- // --- T9 (BUG-8): dual register A-first -> both bind independently ---
122
- console.log('\n--- T9 (BUG-8): dual register A-first -> both bind ---');
123
- { const cG1='conv-g1-dual-a', sG1='sid-g1-stream-a', cG2='conv-g2-dual-b', sG2='sid-g2-stream-b';
124
- reg(sG1,cG1); reg(sG2,cG2);
125
- runHook(LEASE_TOUCH, { transcript_path:'/fake/'+cG1+'.jsonl' });
126
- runHook(LEASE_TOUCH, { transcript_path:'/fake/'+cG2+'.jsonl' });
127
- const hG1=readHmap(cG1), hG2=readHmap(cG2);
128
- check('T9a: stream-A hmap created (not starved)', !!hG1, 'hmap missing for cG1');
129
- check('T9b: stream-A boot_sid=sG1', hG1&&hG1.boot_sid===sG1, JSON.stringify(hG1));
130
- check('T9c: stream-B hmap created independently', !!hG2, 'hmap missing for cG2');
131
- check('T9d: stream-B boot_sid=sG2', hG2&&hG2.boot_sid===sG2, JSON.stringify(hG2));
132
- try{sbSL(['release','--session-id='+sG1]);}catch(_){} try{sbSL(['release','--session-id='+sG2]);}catch(_){} }
133
- // --- T10 (BUG-8 reverse): register B first then A -> both bind ---
134
- console.log('\n--- T10 (BUG-8 reverse): register B first then A -> both bind ---');
135
- { const cH1='conv-h1-rev-a', sH1='sid-h1-stream-a', cH2='conv-h2-rev-b', sH2='sid-h2-stream-b';
136
- reg(sH2,cH2); reg(sH1,cH1);
137
- runHook(LEASE_TOUCH, { transcript_path:'/fake/'+cH1+'.jsonl' });
138
- runHook(LEASE_TOUCH, { transcript_path:'/fake/'+cH2+'.jsonl' });
139
- const hH1=readHmap(cH1), hH2=readHmap(cH2);
140
- check('T10a: stream-A hmap exists', !!hH1, 'missing');
141
- check('T10b: stream-A boot_sid', hH1&&hH1.boot_sid===sH1, JSON.stringify(hH1));
142
- check('T10c: stream-B hmap exists', !!hH2, 'missing');
143
- check('T10d: stream-B boot_sid', hH2&&hH2.boot_sid===sH2, JSON.stringify(hH2));
144
- try{sbSL(['release','--session-id='+sH1]);}catch(_){} try{sbSL(['release','--session-id='+sH2]);}catch(_){} }
145
52
  // --- T11 (BUG-9): resolveOwnBinding ignores current_stream singleton ---
146
53
  console.log('\n--- T11 (BUG-9): resolveOwnBinding ignores current_stream ---');
147
54
  { const cI1='conv-i1-a', sI1='sid-i1-a', cI2='conv-i2-b', sI2='sid-i2-b', cI3='conv-i3-c', sI3='sid-i3-c';
@@ -158,36 +65,6 @@ console.log('\n--- T11 (BUG-9): resolveOwnBinding ignores current_stream ---');
158
65
  check('T11d: resolveOwnBinding via scratch (no hmap)', bI3.bootSid===sI3, JSON.stringify(bI3));
159
66
  check('T11e: source=scratch', bI3.source==='scratch', JSON.stringify(bI3));
160
67
  try{sbSL(['release','--session-id='+sI1]);}catch(_){} try{sbSL(['release','--session-id='+sI2]);}catch(_){} try{sbSL(['release','--session-id='+sI3]);}catch(_){} }
161
- // --- T12 (BUG-10): foreign convId -> lease-touch no-op ---
162
- console.log('\n--- T12 (BUG-10): foreign convId -> no-op ---');
163
- { const cJ='conv-j1-main', sJ='sid-j1-main', cJC='conv-jchild';
164
- reg(sJ,cJ); writeHmap(cJ,sJ);
165
- const lb=leaseExists(sJ);
166
- runHook(LEASE_TOUCH, { transcript_path:'/fake/'+cJC+'.jsonl' });
167
- check('T12a: main lease untouched after child hook', leaseExists(sJ)===lb, 'missing');
168
- check('T12b: no hmap for child convId', !hmapExists(cJC), 'created unexpectedly');
169
- try{sbSL(['release','--session-id='+sJ]);}catch(_){} }
170
- // --- T13 (open-question repro + FIXED): stream bind blocked by current_stream overwrite ---
171
- console.log('\n--- T13 (open-question): bind blocked by current_stream -> FIXED ---');
172
- { const cK1='conv-k1-a', sK1='sid-k1-a', cK2='conv-k2-b', sK2='sid-k2-b';
173
- reg(sK1,cK1); reg(sK2,cK2);
174
- runHook(LEASE_TOUCH, { transcript_path:'/fake/'+cK1+'.jsonl' });
175
- const hK1=readHmap(cK1);
176
- check('T13a: stream-A hmap created despite stream-B overwriting current_stream (BUG-8 FIXED)', !!hK1, 'hmap missing');
177
- check('T13b: stream-A boot_sid=sK1', hK1&&hK1.boot_sid===sK1, JSON.stringify(hK1));
178
- runHook(LEASE_TOUCH, { transcript_path:'/fake/'+cK2+'.jsonl' });
179
- const hK2=readHmap(cK2);
180
- check('T13c: stream-B hmap created', !!hK2, 'missing');
181
- check('T13d: stream-B boot_sid=sK2', hK2&&hK2.boot_sid===sK2, JSON.stringify(hK2));
182
- try{sbSL(['release','--session-id='+sK1]);}catch(_){} try{sbSL(['release','--session-id='+sK2]);}catch(_){} }
183
- // --- T14: lease-release cleans up scratch ---
184
- console.log('\n--- T14: lease-release cleans scratch ---');
185
- { const cL='conv-l1-cleanup', sL='sid-l1-cleanup'; reg(sL,cL); writeHmap(cL,sL);
186
- check('T14-pre: scratch exists', scratchExists(cL), 'not found');
187
- runHook(LEASE_RELEASE, { hook_event_name:'SessionEnd', source:'logout', transcript_path:'/fake/'+cL+'.jsonl' });
188
- check('T14a: lease removed', !leaseExists(sL), 'still present');
189
- check('T14b: hmap cleaned', !hmapExists(cL), '');
190
- check('T14c: scratch cleaned', !scratchExists(cL), 'scratch still present'); }
191
68
  // --- dispatch.js env name ---
192
69
  // --- T15 (TASK_1767): empty scope_paths must not bypass same-task-id guard ---
193
70
  console.log('\n--- T15: empty-scope same-task gate (TASK_1767) ---');