kenaz 0.3.18 → 0.3.19

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 (308) 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__/m1-hmap-convid.test.js +1 -124
  30. package/core/.formation/tools/dispatch.js +1 -1
  31. package/core/.formation/tools/loader.js +17 -140
  32. package/core/.formation/tools/post-complete.js +0 -31
  33. package/core/.rule/INDEX.yaml +0 -18
  34. package/core/.rule/general/agent-workflow.yaml +14 -164
  35. package/core/.rule/general/project-self-containment.yaml +8 -19
  36. package/core/.rule/general/rust-verify-target.yaml +6 -5
  37. package/core/.rule/general/synapse-code-intelligence.yaml +3 -3
  38. package/core/.specialist/Amelia/capability.yaml +12 -12
  39. package/core/.specialist/Amelia/workflow.yaml +2 -2
  40. package/core/.specialist/Ansuz/SYSTEM_DOC.md +20 -578
  41. package/core/.specialist/Ansuz/cognitive_principles.yaml +2 -3
  42. package/core/.specialist/Ansuz/concepts/boot_rules_summary.yaml +0 -1
  43. package/core/.specialist/Ansuz/concepts/deep_knowledge_pointers.yaml +1 -2
  44. package/core/.specialist/Ansuz/core.yaml +6 -108
  45. package/core/.specialist/Ansuz/guards/lesson_guards.yaml +0 -3
  46. package/core/.specialist/Ansuz/identity_contract.yaml +0 -1
  47. package/core/.specialist/Ansuz/knowledge.yaml +0 -4
  48. package/core/.specialist/Ansuz/rule.yaml +0 -1
  49. package/core/.specialist/Ansuz/tools/handoff-session-identity.test.js +6 -150
  50. package/core/.specialist/tests/runtime-discovery/README.md +1 -1
  51. package/core/.specialist/tools/__tests__/task-2374-usage-counter.test.js +1 -12
  52. package/core/.specialist/tools/prompt-files.test.js +1 -0
  53. package/core/.specialist/tools/task-bridge.js +1 -66
  54. package/core/.system/README.md +11 -552
  55. package/core/.system/collaboration/README.md +10 -174
  56. package/core/CLAUDE.md +1 -6
  57. package/core/KENAZ_CORE_VERSION +1 -1
  58. package/core/dev/scripts/js-yaml-resolution.test.js +1 -1
  59. package/core/dev/scripts/run-rust-tests.js +9 -45
  60. package/core/dev/scripts/rust-verify-worktree.js +4 -4
  61. package/core/dev/scripts/verify-target-dir.js +6 -6
  62. package/core/plugins/kenaz/INVENTORY.md +8 -8
  63. package/core/plugins/kenaz/commands/architect.md +1 -2
  64. package/core/plugins/kenaz/commands/spec.md +1 -1
  65. package/core/plugins/kenaz/commands//347/224/242/345/223/201.md +1 -1
  66. package/core/plugins/kenaz/guidance.md +1 -1
  67. package/core/plugins/kenaz/scripts/sync.js +1 -1
  68. package/core/plugins/kenaz/skills/architect_agent/SKILL.md +11 -92
  69. package/core/plugins/kenaz/skills/assessment_agent/SKILL.md +0 -1
  70. package/core/plugins/kenaz/skills/backend_engineer/SKILL.md +3 -6
  71. package/core/plugins/kenaz/skills/code_reviewer/SKILL.md +1 -1
  72. package/core/plugins/kenaz/skills/code_reviewer/patterns.yaml +1 -1
  73. package/core/plugins/kenaz/skills/designer/SKILL.md +3 -6
  74. package/core/plugins/kenaz/skills/dev_agent/SKILL.md +30 -491
  75. package/core/plugins/kenaz/skills/developer/SKILL.md +3 -6
  76. package/core/plugins/kenaz/skills/feature_agent/SKILL.md +3 -17
  77. package/core/plugins/kenaz/skills/product_manager/SKILL.md +29 -1064
  78. package/core/plugins/kenaz/skills/qa_engineer/SKILL.md +12 -17
  79. package/core/plugins/kenaz/skills/spec_optimizer/SKILL.md +25 -275
  80. package/core/plugins/kenaz/skills/sre_agent/SKILL.md +3 -6
  81. package/package.json +6 -6
  82. package/core/.claude/commands/archive.md +0 -24
  83. package/core/.claude/commands/init.md +0 -112
  84. package/core/.claude/commands/legacy_dev.md +0 -18
  85. package/core/.claude/commands/product-review.md +0 -131
  86. package/core/.claude/commands/strategy.md +0 -141
  87. package/core/.claude/commands/sunny.md +0 -1
  88. package/core/.claude/commands//347/224/242/345/223/201/346/252/242/350/246/226.md +0 -129
  89. package/core/.claude/commands//351/200/262/345/272/246.md +0 -15
  90. package/core/.claude/hooks/__tests__/substrate.test.js +0 -122
  91. package/core/.claude/hooks/_substrate-paths.js +0 -95
  92. package/core/.claude/hooks/context-check.js +0 -51
  93. package/core/.claude/hooks/fatigue-check.js +0 -52
  94. package/core/.claude/hooks/handoff-snapshot-on-commit.js +0 -154
  95. package/core/.claude/hooks/handoff-snapshot-on-question.js +0 -158
  96. package/core/.claude/hooks/handoff-staleness.js +0 -197
  97. package/core/.claude/hooks/jev-thalamus-context.js +0 -17
  98. package/core/.claude/hooks/jev-thalamus-context.test.js +0 -41
  99. package/core/.claude/hooks/lease-release.js +0 -119
  100. package/core/.claude/hooks/lease-touch.js +0 -96
  101. package/core/.claude/hooks/reflex-feedback.js +0 -5
  102. package/core/.claude/hooks/session-init.ps1 +0 -49
  103. package/core/.claude/hooks/sound-event.js +0 -70
  104. package/core/.claude/hooks/sound-event.sh +0 -37
  105. package/core/.claude/hooks/stream-delta.js +0 -169
  106. package/core/.claude/no-hooks.settings.json +0 -3
  107. package/core/.claude/skills/legacy_dev/SKILL.md +0 -202
  108. package/core/.claude/skills/sunny/SKILL.md +0 -74
  109. package/core/.collaboration/cli/commands/assign.js +0 -39
  110. package/core/.collaboration/cli/commands/claim.js +0 -33
  111. package/core/.collaboration/cli/commands/complete.js +0 -44
  112. package/core/.collaboration/cli/commands/create.js +0 -110
  113. package/core/.collaboration/cli/commands/get.js +0 -83
  114. package/core/.collaboration/cli/commands/index.js +0 -52
  115. package/core/.collaboration/cli/commands/list.js +0 -51
  116. package/core/.collaboration/cli/commands/lock.js +0 -45
  117. package/core/.collaboration/cli/commands/rebuild.js +0 -39
  118. package/core/.collaboration/cli/commands/search.js +0 -61
  119. package/core/.collaboration/cli/commands/stats.js +0 -61
  120. package/core/.collaboration/cli/commands/transfer.js +0 -41
  121. package/core/.collaboration/cli/commands/unlock.js +0 -48
  122. package/core/.collaboration/cli/formatters/help-formatter.js +0 -70
  123. package/core/.collaboration/cli/formatters/index.js +0 -7
  124. package/core/.collaboration/cli/task-cli.js +0 -46
  125. package/core/.collaboration/cli/utils/arg-parser.js +0 -74
  126. package/core/.collaboration/cli/utils/git-user.js +0 -25
  127. package/core/.collaboration/cli/utils/index.js +0 -9
  128. package/core/.collaboration/cli/utils/output.js +0 -10
  129. package/core/.collaboration/config/default.yaml +0 -189
  130. package/core/.collaboration/core/conflict-resolver.js +0 -461
  131. package/core/.collaboration/core/conflict-resolver.test.js +0 -389
  132. package/core/.collaboration/core/migrate-legacy.js +0 -260
  133. package/core/.collaboration/docs/API.md +0 -787
  134. package/core/.collaboration/docs/ARCHITECTURE.md +0 -596
  135. package/core/.collaboration/docs/FAQ.md +0 -695
  136. package/core/.collaboration/docs/MIGRATION.md +0 -804
  137. package/core/.collaboration/docs/examples/README.md +0 -320
  138. package/core/.collaboration/docs/examples/advanced-queries.js +0 -261
  139. package/core/.collaboration/docs/examples/basic-usage.js +0 -184
  140. package/core/.collaboration/docs/examples/team-workflow.js +0 -352
  141. package/core/.failure/agent-execution/FAIL-001-agent-no-output.yaml +0 -391
  142. package/core/.failure/agent-execution/FAIL-007-pm-lead-wrong-team-invocation.yaml +0 -0
  143. package/core/.failure/agent-execution/FAIL-010-phase0-poem-format-skipped.yaml +0 -28
  144. package/core/.failure/agent-execution/FAIL-010-skipping-cognitive-checkpoint-after-verification.yaml +0 -59
  145. package/core/.failure/agent-execution/FAIL-012-grep-shortcut-during-investigation.yaml +0 -85
  146. package/core/.failure/architecture/FAIL-006-python-version-compatibility.yaml +0 -445
  147. package/core/.failure/pipeline/FAIL-003-queue-pollution.yaml +0 -335
  148. package/core/.failure/pipeline/README.md +0 -95
  149. package/core/.failure/retired/FAIL-009-skipping-synapse-pulse-before-code-change.yaml +0 -49
  150. package/core/.failure/tools/USAGE_GUIDE.md +0 -323
  151. package/core/.failure/tools/check_failures.ps1 +0 -387
  152. package/core/.failure/tools/log_failure.ps1 +0 -474
  153. package/core/.formation/.episode-input.json +0 -10
  154. package/core/.formation/.merge-lock +0 -1
  155. package/core/.formation/lead.yaml +0 -118
  156. package/core/.formation/legacy.bak/designer.yaml +0 -57
  157. package/core/.formation/legacy.bak/pm.yaml +0 -57
  158. package/core/.formation/legacy.bak/qa.yaml +0 -57
  159. package/core/.formation/legacy.bak/review.yaml +0 -62
  160. package/core/.formation/legacy.bak/scheduler.yaml +0 -129
  161. package/core/.formation/legacy.bak/sre.yaml +0 -57
  162. package/core/.formation/role-map.yaml +0 -274
  163. package/core/.formation/roles/_shared/modules/code_review.yaml +0 -98
  164. package/core/.formation/roles/_shared/modules/security.yaml +0 -103
  165. package/core/.formation/roles/_shared/modules/testing.yaml +0 -14
  166. package/core/.formation/roles/backend/role.yaml +0 -93
  167. package/core/.formation/roles/code_reviewer/role.yaml +0 -102
  168. package/core/.formation/roles/database_optimizer/role.yaml +0 -107
  169. package/core/.formation/roles/designer/role.yaml +0 -66
  170. package/core/.formation/roles/developer/role.yaml +0 -75
  171. package/core/.formation/roles/frontend/role.yaml +0 -134
  172. package/core/.formation/roles/incident_response/role.yaml +0 -89
  173. package/core/.formation/roles/qa/role.yaml +0 -89
  174. package/core/.formation/roles/security/role.yaml +0 -87
  175. package/core/.formation/roles/sre/role.yaml +0 -66
  176. package/core/.formation/skills/coordinator.yaml +0 -52
  177. package/core/.formation/solo/diagnosis.yaml +0 -78
  178. package/core/.formation/solo/strategy.yaml +0 -121
  179. package/core/.formation/tests/hello.txt +0 -2
  180. package/core/.formation/tools/coordinator.js +0 -350
  181. package/core/.formation/tools/jev-correction.js +0 -214
  182. package/core/.formation/tools/jev-correction.test.js +0 -178
  183. package/core/.formation/tools/log-reader.js +0 -232
  184. package/core/.formation/tools/revert-daemon-state.js +0 -162
  185. package/core/.formation/tools/test-drift.js +0 -148
  186. package/core/.formation/unit/heimdall.yaml +0 -96
  187. package/core/.formation/unit/plan.yaml +0 -67
  188. package/core/.formation/unit/think.yaml +0 -58
  189. package/core/.kenaz/MUNINN_SNAPSHOT9_EPISODE.json +0 -32
  190. package/core/.kenaz/MUNINN_SNAPSHOT9_RUNE.json +0 -23
  191. package/core/.kenaz/MUNINN_SNAPSHOT9_SUMMARY.md +0 -89
  192. package/core/.kenaz/ash_TASK_1428-20260507.json +0 -14
  193. package/core/.kenaz/muninn_episode_write.ps1 +0 -17
  194. package/core/.kenaz/muninn_snapshot11_rune_candidates.md +0 -63
  195. package/core/.kenaz/muninn_snapshot1_rune_candidates.md +0 -49
  196. package/core/.kenaz/runes_TASK_1428.json +0 -57
  197. package/core/.kenaz/tmp_heimdall_proposal_8d3e392.json +0 -13
  198. package/core/.kenaz/tmp_props.json +0 -1
  199. package/core/.kenaz/tmp_sounddrop_t1_prompt.txt +0 -371
  200. package/core/.rule/MECHANIZED.md +0 -61
  201. package/core/.rule/general/cortex-memory-recall.yaml +0 -446
  202. package/core/.rule/general/pipeline.yaml +0 -246
  203. package/core/.rule/general/sunny-access-control.yaml +0 -60
  204. package/core/.rule/general/system-invariants.yaml +0 -231
  205. package/core/.rule/pipeline/PPL-002-completed-task-archival.yaml +0 -528
  206. package/core/.rule/pipeline/auto-update.yaml +0 -282
  207. package/core/.rule/pipeline/task-execution.yaml +0 -365
  208. package/core/.specialist/Ansuz/concepts/phase_protocol.yaml +0 -65
  209. package/core/.specialist/Ansuz/experiments/boot_ablation_replay.js +0 -197
  210. package/core/.specialist/Ansuz/tools/bootstrap-anchors.js +0 -289
  211. package/core/.specialist/Ansuz/workflow.yaml +0 -1225
  212. package/core/.specialist/experiments/rg_benchmark.js +0 -523
  213. package/core/.specialist/experiments/rg_benchmark_results.json +0 -27
  214. package/core/.specialist/tools/jev-optional-context.js +0 -107
  215. package/core/.specialist/tools/jev-optional-context.test.js +0 -152
  216. package/core/.specialist/tools/memory-action-log.js +0 -839
  217. package/core/.specialist/tools/phase-gate.js +0 -3534
  218. package/core/.specialist/tools/phase-gate.test.js +0 -85
  219. package/core/.specialist/tools/precompute-runner.js +0 -444
  220. package/core/.specialist/tools/rule-engine.js +0 -621
  221. package/core/.specialist/tools/task-bridge-jev.test.js +0 -170
  222. package/core/.synapse/memory-shared.json.sync +0 -1
  223. package/core/.system/agent-skills/README.md +0 -724
  224. package/core/.system/cli-tools/README.md +0 -724
  225. package/core/.system/cortex/MODULES.md +0 -1046
  226. package/core/.system/dashboard/FRONTEND.md +0 -812
  227. package/core/.system/dashboard/README.md +0 -737
  228. package/core/.system/failure/README.md +0 -723
  229. package/core/.system/formation/LEGACY_SKILLS.md +0 -974
  230. package/core/.system/formation/POST_COMPLETE.md +0 -602
  231. package/core/.system/formation/README.md +0 -1094
  232. package/core/.system/formation/TOOLS_REFERENCE.md +0 -1145
  233. package/core/.system/kenaz/README.md +0 -787
  234. package/core/.system/memory/README.md +0 -719
  235. package/core/.system/pipeline/README.md +0 -712
  236. package/core/.system/rule/README.md +0 -794
  237. package/core/.system/sunny/README.md +0 -476
  238. package/core/.system/sunny/RULES.json +0 -89
  239. package/core/.system/sunny/knowledge/INDEX.md +0 -37
  240. package/core/.system/sunny/knowledge/agent-teams-api.md +0 -0
  241. package/core/.system/sunny/knowledge/ansuz-specialist.md +0 -500
  242. package/core/.system/sunny/knowledge/claude-cli-spawn.md +0 -177
  243. package/core/.system/sunny/knowledge/collaboration-api.md +0 -925
  244. package/core/.system/sunny/teammates/README.md +0 -107
  245. package/core/.system/sunny/teammates/how_to_use.yaml +0 -101
  246. package/core/.system/sunny/teammates/tools/headless/launcher.js +0 -318
  247. package/core/.system/sunny/teammates/tools/powershell/launcher.js +0 -241
  248. package/core/.system/sunny/teammates/tools/powershell/start.bat +0 -50
  249. package/core/.system/sunny/teammates/tools/utils/env.js +0 -96
  250. package/core/.system/sunny/teammates/tools/utils/format-output.js +0 -329
  251. package/core/.system/sunny/tools.json +0 -101
  252. package/core/dev/scripts/cleanup-queue.js +0 -184
  253. package/core/dev/scripts/cleanup_queue.js +0 -86
  254. package/core/dev/scripts/legacy/README.md +0 -39
  255. package/core/dev/scripts/legacy/dev_agent_scheduler.ps1.bak +0 -536
  256. package/core/dev/scripts/legacy/multi_agent_scheduler.ps1.bak +0 -1978
  257. package/core/dev/scripts/matrix/CLI_README.md +0 -214
  258. package/core/dev/scripts/matrix/README.md +0 -310
  259. package/core/dev/scripts/matrix/package-lock.json +0 -4266
  260. package/core/dev/scripts/matrix/package.json +0 -55
  261. package/core/dev/scripts/matrix/src/abbreviations.ts +0 -295
  262. package/core/dev/scripts/matrix/src/cli/commands/convert.ts +0 -211
  263. package/core/dev/scripts/matrix/src/cli/commands/create.ts +0 -95
  264. package/core/dev/scripts/matrix/src/cli/commands/delete.ts +0 -102
  265. package/core/dev/scripts/matrix/src/cli/commands/list-tags.ts.wip +0 -140
  266. package/core/dev/scripts/matrix/src/cli/commands/manage-tags.ts.wip +0 -173
  267. package/core/dev/scripts/matrix/src/cli/commands/query.ts +0 -261
  268. package/core/dev/scripts/matrix/src/cli/commands/read.ts +0 -77
  269. package/core/dev/scripts/matrix/src/cli/commands/stats.ts.wip +0 -168
  270. package/core/dev/scripts/matrix/src/cli/commands/tokens.ts.wip +0 -126
  271. package/core/dev/scripts/matrix/src/cli/commands/update.ts +0 -147
  272. package/core/dev/scripts/matrix/src/cli/commands/validate.ts +0 -275
  273. package/core/dev/scripts/matrix/src/cli/index.ts +0 -350
  274. package/core/dev/scripts/matrix/src/cli/utils/file-handler.ts +0 -72
  275. package/core/dev/scripts/matrix/src/cli/utils/logger.ts +0 -65
  276. package/core/dev/scripts/matrix/src/index.ts +0 -62
  277. package/core/dev/scripts/matrix/src/indexer/tag-indexer.ts +0 -165
  278. package/core/dev/scripts/matrix/src/parser.ts +0 -281
  279. package/core/dev/scripts/matrix/src/serializer.ts +0 -151
  280. package/core/dev/scripts/matrix/src/validator.ts +0 -301
  281. package/core/dev/scripts/matrix/tests/abbreviations.test.ts +0 -122
  282. package/core/dev/scripts/matrix/tests/cli.test.ts +0 -177
  283. package/core/dev/scripts/matrix/tests/convert.test.ts +0 -143
  284. package/core/dev/scripts/matrix/tests/parser.test.ts +0 -203
  285. package/core/dev/scripts/matrix/tests/query.test.ts +0 -85
  286. package/core/dev/scripts/matrix/tests/serializer.test.ts +0 -197
  287. package/core/dev/scripts/matrix/tests/validate.test.ts +0 -141
  288. package/core/dev/scripts/matrix/tests/validator.test.ts +0 -167
  289. package/core/dev/scripts/matrix/tsconfig.json +0 -20
  290. package/core/dev/scripts/matrix/types/index.d.ts +0 -111
  291. package/core/dev/scripts/matrix/types/index.d.ts.map +0 -1
  292. package/core/dev/scripts/matrix/types/index.js +0 -8
  293. package/core/dev/scripts/matrix/types/index.js.map +0 -1
  294. package/core/dev/scripts/matrix/types/index.ts +0 -124
  295. package/core/dev/scripts/memory-usage-report.js +0 -152
  296. package/core/dev/scripts/probe/ansuz-scaffold-ablation.js +0 -579
  297. package/core/dev/scripts/probe/ansuz-scaffold-ablation.test.js +0 -244
  298. package/core/dev/scripts/probe/hook-latency-probe.js +0 -315
  299. package/core/dev/scripts/probe/hook-latency-probe.test.js +0 -105
  300. package/core/dev/scripts/probe/prediction-signal-auc.js +0 -483
  301. package/core/dev/scripts/probe/prediction-signal-auc.test.js +0 -200
  302. package/core/dev/scripts/test-pty-ws-tunnel.js +0 -229
  303. package/core/dev/scripts/validate_pipeline.js +0 -197
  304. package/core/dev/spikes/task2145-evidence-20261004/backend-log-excerpt.txt +0 -56
  305. package/core/dev/spikes/task2145-evidence-20261004/graph.shadow +0 -0
  306. package/core/dev/spikes/task2145-evidence-20261004/graph.wal +0 -0
  307. package/core/dev/spikes/task2145-evidence-20261004/graph_corrupt_suspect.marker +0 -1
  308. package/core/plugins/kenaz/commands/strategy.md +0 -141
@@ -1,85 +0,0 @@
1
- 'use strict';
2
- // phase-gate gate-shape tests (restored TASK_2340 after the Kuzu removal dropped the pulse/predicted_symbols/thalamus gates).
3
- // Everything runs against a temp --project-path; charts for the temp project land in the git-ignored .specialist/sessions/projects/.
4
- const test = require('node:test');
5
- const assert = require('node:assert/strict');
6
- const fs = require('node:fs');
7
- const os = require('node:os');
8
- const path = require('node:path');
9
-
10
- const proj = fs.mkdtempSync(path.join(os.tmpdir(), 'pg2340-'));
11
- fs.mkdirSync(path.join(proj, '.kenaz', 'specialist'), { recursive: true });
12
- process.argv.push('--project-path=' + proj); // read at module load by phase-gate
13
- const pg = require('./phase-gate');
14
-
15
- const coreRoot = path.resolve(__dirname, '../..');
16
- const taskId = 'TASK_PG2340_' + process.pid;
17
- const taskDir = path.join(coreRoot, '.kenaz', 'tasks', 'active');
18
- const taskFile = path.join(taskDir, taskId + '.yaml');
19
-
20
- // enterPhase/exitPhase print JSON; keep test output clean.
21
- function quiet(fn) {
22
- const log = console.log;
23
- console.log = () => {};
24
- try { return fn(); } finally { console.log = log; }
25
- }
26
-
27
- // enterPhase touches lesson_guards.yaml (injection bookkeeping); restore it so the suite leaves the tree clean.
28
- const guardsFile = path.join(coreRoot, '.specialist', 'Ansuz', 'guards', 'lesson_guards.yaml');
29
- const guardsBefore = fs.existsSync(guardsFile) ? fs.readFileSync(guardsFile) : null;
30
-
31
- test.before(() => {
32
- fs.mkdirSync(taskDir, { recursive: true });
33
- fs.writeFileSync(taskFile, `id: ${taskId}\ntitle: pg test\nscope_paths:\n - .specialist/tools/phase-gate.js\n`);
34
- });
35
- test.after(() => {
36
- if (guardsBefore) fs.writeFileSync(guardsFile, guardsBefore);
37
- fs.rmSync(taskFile, { force: true });
38
- try { fs.rmdirSync(taskDir); } catch { /* not empty or absent: leave tracked dirs alone */ }
39
- fs.rmSync(proj, { recursive: true, force: true });
40
- const sessions = path.join(coreRoot, '.specialist', 'sessions', 'projects');
41
- if (fs.existsSync(sessions)) {
42
- for (const d of fs.readdirSync(sessions)) {
43
- if (d.startsWith(path.basename(proj).toLowerCase())) fs.rmSync(path.join(sessions, d), { recursive: true, force: true });
44
- }
45
- }
46
- });
47
-
48
- test('the task fixture really declares scope_paths', () => {
49
- assert.deepEqual(pg.readTaskScopePaths(taskId), ['.specialist/tools/phase-gate.js']);
50
- });
51
-
52
- test('checklists no longer ask for removed tools (preamble, thalamus, pulse, search)', () => {
53
- const all = JSON.stringify(pg.PHASE_CHECKLISTS);
54
- for (const gone of ['synapse_preamble', 'preamble_loaded', 'Tier 2b', 'thalamus', 'synapse_pulse', 'synapse_search', 'synapse_impact']) {
55
- assert.equal(all.includes(gone), false, gone);
56
- }
57
- assert.ok(!pg.PHASE_CHECKLISTS[0].some(i => i.includes('cortex_recall') || i.includes('synapse_')));
58
- assert.ok(pg.PHASE_CHECKLISTS[2].some(i => i.includes('kenaz_lsp_callers')));
59
- assert.equal(JSON.stringify(pg.PHASE_CHECKLISTS).toLowerCase().includes('muninn'), false);
60
- });
61
-
62
- test('Phase 8 exit rule no longer requires predicted_symbols', () => {
63
- assert.equal(pg.PHASE_EXIT_RULES[8], undefined);
64
- assert.deepEqual(pg.PHASE_EXIT_RULES[1].required, ['ddx_hypotheses']);
65
- assert.deepEqual(pg.PHASE_EXIT_RULES[9].required, ['cognitive_checkpoint']);
66
- });
67
-
68
- test('Phase 3 enter is not blocked by a missing pulse log even when the task declares scope_paths', () => {
69
- const r = quiet(() => pg.enterPhase(3, taskId));
70
- assert.equal(r.blocked, false);
71
- assert.equal(r.block_reason, null);
72
- assert.equal(JSON.stringify(r.warnings).includes('pulse'), false);
73
- });
74
-
75
- test('Phase 8 enter no longer reports muninn / valence output', () => {
76
- const r = quiet(() => pg.enterPhase(8, taskId));
77
- assert.equal(r.blocked, false);
78
- assert.equal('valence' in r, false);
79
- assert.equal('muninn' in r, false);
80
- });
81
-
82
- test('Phase 8 exit passes with scope_paths and no predicted_symbols', () => {
83
- const r = quiet(() => pg.exitPhase(8, taskId, {}));
84
- assert.notEqual(r.blocked, true);
85
- });
@@ -1,444 +0,0 @@
1
- #!/usr/bin/env node
2
- 'use strict';
3
-
4
- /**
5
- * Precompute Runner — TASK_1162
6
- *
7
- * Executes safe, read-only named functions before phase entry and embeds
8
- * their output into blind-spot guard text. Eliminates "remember to check X"
9
- * compliance friction by making the result already present in instructions.
10
- *
11
- * Security model:
12
- * - execFileSync with argv array (never execSync + shell) — prevents shell injection
13
- * - env: SAFE_ENV (PATH-only) — drops GIT_EXEC_PATH, LD_PRELOAD, etc.
14
- * - Per-parameter regex validation BEFORE any execFileSync call
15
- * - File paths resolved within project root and rejected on escape
16
- * - Whitelist: 5 named functions only — gitShowStat, gitDiffStat, grepCount, wcLines, fileExists
17
- *
18
- * Budget:
19
- * - 3s total per phase enter (TOTAL_BUDGET_MS)
20
- * - 1s per command (PER_CMD_TIMEOUT_MS, enforced by execFileSync timeout option)
21
- * - Per-guard output capped at 200 chars (PER_GUARD_CAP)
22
- * - Total output capped at 4096 bytes (TOTAL_CAP)
23
- *
24
- * Kill switch:
25
- * KENAZ_PRECOMPUTE_DISABLE=1 → skip all precompute, fall back to text-only guard
26
- *
27
- * Guard YAML precompute field format:
28
- * precompute:
29
- * cmd: "gitShowStat" # one of 5 named functions
30
- * sha: "HEAD" # gitShowStat / gitDiffStat param
31
- * sha1: "HEAD~1" # gitDiffStat param
32
- * sha2: "HEAD" # gitDiffStat param
33
- * pattern: "TODO" # grepCount param (JS regex pattern)
34
- * file: "path/to/file" # grepCount / wcLines param (project-relative)
35
- * path: "path/to/check" # fileExists param (project-relative)
36
- * when: "always" # "always" | "never" | taskData key name
37
- * template: "Result: {{result}}" # {{result}} replaced with command output
38
- */
39
-
40
- const fs = require('fs');
41
- const path = require('path');
42
- const { execFileSync } = require('child_process');
43
-
44
- // ── Constants ───────────────────────────────────────────────
45
-
46
- const TOTAL_BUDGET_MS = 3000; // total per phase enter
47
- const PER_CMD_TIMEOUT_MS = 1000; // execFileSync timeout per command
48
- const PER_GUARD_CAP = 200; // max chars per guard output (truncated with …)
49
- const TOTAL_CAP = 4096; // max total chars across all guards per phase
50
- const MAX_BUFFER = 4096; // execFileSync maxBuffer
51
-
52
- // SHA validation: 7–40 lowercase hex chars (git short or full SHA)
53
- const SHA_RE = /^[0-9a-f]{7,40}$/;
54
-
55
- // Minimal safe environment — only PATH so git can be located.
56
- // Drops GIT_EXEC_PATH, GIT_SSH, GIT_TEMPLATE_DIR, LD_PRELOAD, etc.
57
- const SAFE_ENV = { PATH: process.env.PATH || process.env.Path || '' };
58
-
59
- // ── Kill switch ─────────────────────────────────────────────
60
-
61
- /**
62
- * Returns true if precompute is globally disabled via env var.
63
- * Evaluated lazily so tests can set the env var before calling runPrecompute.
64
- */
65
- function isDisabled() {
66
- return process.env.KENAZ_PRECOMPUTE_DISABLE === '1';
67
- }
68
-
69
- // ── Parameter validators ────────────────────────────────────
70
-
71
- /**
72
- * Validate a git SHA parameter.
73
- * @param {string} sha
74
- * @returns {string} validated sha
75
- * @throws {Error} if invalid
76
- */
77
- function validateSha(sha) {
78
- if (typeof sha !== 'string' || !SHA_RE.test(sha)) {
79
- throw new Error(`Invalid SHA "${sha}": must match /^[0-9a-f]{7,40}$/`);
80
- }
81
- return sha;
82
- }
83
-
84
- /**
85
- * Resolve and validate a file path within project root.
86
- * Rejects any path that escapes the project root (../ traversal).
87
- * @param {string} filePath - relative or absolute path
88
- * @param {string} projectRoot - absolute project root
89
- * @returns {string} validated absolute path
90
- * @throws {Error} if path escapes project root
91
- */
92
- function resolveFilePath(filePath, projectRoot) {
93
- if (typeof filePath !== 'string' || !filePath.trim()) {
94
- throw new Error('File path must be a non-empty string');
95
- }
96
- const abs = path.isAbsolute(filePath)
97
- ? filePath
98
- : path.resolve(projectRoot, filePath);
99
- const normalized = path.normalize(abs);
100
- const rootNormalized = path.normalize(projectRoot);
101
- // Must be within project root (starts with root + sep, or equals root)
102
- if (normalized !== rootNormalized &&
103
- !normalized.startsWith(rootNormalized + path.sep)) {
104
- throw new Error(`Path escape rejected: "${filePath}" resolves outside project root`);
105
- }
106
- return normalized;
107
- }
108
-
109
- // ── Named Function Library ──────────────────────────────────
110
- //
111
- // Each function validates its parameters, then either executes a read-only
112
- // git command via execFileSync (argv array, never shell) or reads files
113
- // using Node's fs module (grepCount, wcLines, fileExists — cross-platform,
114
- // no shell dependency).
115
-
116
- /**
117
- * Show stat for a single commit (files changed + insertions/deletions summary).
118
- * @param {string} sha - 7–40 hex git SHA
119
- * @param {string} projectRoot - absolute project root (cwd for git)
120
- * @returns {string} trimmed stdout
121
- */
122
- function gitShowStat(sha, projectRoot) {
123
- validateSha(sha);
124
- const result = execFileSync('git', ['show', '--stat', '--no-patch', sha], {
125
- env: SAFE_ENV,
126
- cwd: projectRoot,
127
- timeout: PER_CMD_TIMEOUT_MS,
128
- maxBuffer: MAX_BUFFER,
129
- encoding: 'utf8',
130
- windowsHide: true,
131
- });
132
- return result.trim();
133
- }
134
-
135
- /**
136
- * Diff stat between two commits (files changed summary).
137
- * @param {string} sha1 - base commit SHA
138
- * @param {string} sha2 - head commit SHA
139
- * @param {string} projectRoot - absolute project root
140
- * @returns {string} trimmed stdout
141
- */
142
- function gitDiffStat(sha1, sha2, projectRoot) {
143
- validateSha(sha1);
144
- validateSha(sha2);
145
- const result = execFileSync('git', ['diff', '--stat', sha1, sha2], {
146
- env: SAFE_ENV,
147
- cwd: projectRoot,
148
- timeout: PER_CMD_TIMEOUT_MS,
149
- maxBuffer: MAX_BUFFER,
150
- encoding: 'utf8',
151
- windowsHide: true,
152
- });
153
- return result.trim();
154
- }
155
-
156
- /**
157
- * Count lines matching a pattern in a file (pure Node — cross-platform).
158
- * Uses JavaScript RegExp — no grep binary required on Windows.
159
- * @param {string} pattern - JavaScript regex pattern string
160
- * @param {string} filePath - project-relative or absolute path
161
- * @param {string} projectRoot - absolute project root
162
- * @returns {string} match count as string
163
- */
164
- function grepCount(pattern, filePath, projectRoot) {
165
- if (typeof pattern !== 'string') throw new Error('pattern must be a string');
166
- const absPath = resolveFilePath(filePath, projectRoot);
167
- // Validate pattern compiles (throws SyntaxError on invalid regex)
168
- const re = new RegExp(pattern);
169
- const content = fs.readFileSync(absPath, 'utf8');
170
- const count = content.split('\n').filter(line => re.test(line)).length;
171
- return String(count);
172
- }
173
-
174
- /**
175
- * Count lines in a file (pure Node — cross-platform).
176
- * @param {string} filePath - project-relative or absolute path
177
- * @param {string} projectRoot - absolute project root
178
- * @returns {string} line count as string
179
- */
180
- function wcLines(filePath, projectRoot) {
181
- const absPath = resolveFilePath(filePath, projectRoot);
182
- const content = fs.readFileSync(absPath, 'utf8');
183
- // Split on \n — consistent with wc -l semantics (count \n occurrences)
184
- const count = content.split('\n').length - (content.endsWith('\n') ? 1 : 0);
185
- return String(count);
186
- }
187
-
188
- /**
189
- * Count commits between two refs: HEAD ahead of the given base ref.
190
- * Used by L-004 to detect stale worktree base (e.g. ahead origin/main by N commits).
191
- * @param {string} baseRef - base ref name (e.g. "origin/main", "main", "HEAD~10")
192
- * @param {string} projectRoot - absolute project root
193
- * @returns {string} "ahead {N} commits of {baseRef}" or "in sync with {baseRef}"
194
- */
195
- function gitCommitsAhead(baseRef, projectRoot) {
196
- // Only allow safe ref patterns: refs/, origin/x, local branch names, HEAD~N
197
- if (!/^[a-zA-Z0-9_./~-]{1,80}$/.test(baseRef)) {
198
- throw new Error(`Invalid baseRef "${baseRef}": must match /^[a-zA-Z0-9_./~-]{1,80}$/`);
199
- }
200
- let result;
201
- try {
202
- result = execFileSync('git', ['rev-list', '--count', `${baseRef}..HEAD`], {
203
- env: SAFE_ENV,
204
- cwd: projectRoot,
205
- timeout: PER_CMD_TIMEOUT_MS,
206
- maxBuffer: MAX_BUFFER,
207
- encoding: 'utf8',
208
- windowsHide: true,
209
- });
210
- } catch (e) {
211
- return `(unknown — ${baseRef} unreachable)`;
212
- }
213
- const n = parseInt(result.trim(), 10);
214
- if (!Number.isFinite(n)) return `(unknown count for ${baseRef})`;
215
- if (n === 0) return `in sync with ${baseRef}`;
216
- if (n > 50) return `⚠️ ahead ${n} commits of ${baseRef} — very stale base risk`;
217
- if (n > 10) return `ahead ${n} commits of ${baseRef} — stale base possible`;
218
- return `ahead ${n} commits of ${baseRef}`;
219
- }
220
-
221
- /**
222
- * Show recent commits touching a file (last 5).
223
- * Used by L-002 to surface what's recently changed in the file Ansuz is about to modify.
224
- * @param {string} filePath - project-relative path
225
- * @param {string} projectRoot - absolute project root
226
- * @returns {string} compact log lines
227
- */
228
- function gitLogShort(filePath, projectRoot) {
229
- const absPath = resolveFilePath(filePath, projectRoot);
230
- const relPath = path.relative(projectRoot, absPath);
231
- // Reject path traversal — relPath must not start with ..
232
- if (relPath.startsWith('..') || path.isAbsolute(relPath)) {
233
- throw new Error(`Path escape detected: ${filePath}`);
234
- }
235
- const result = execFileSync('git', ['log', '--oneline', '-5', '--', relPath], {
236
- env: SAFE_ENV,
237
- cwd: projectRoot,
238
- timeout: PER_CMD_TIMEOUT_MS,
239
- maxBuffer: MAX_BUFFER,
240
- encoding: 'utf8',
241
- windowsHide: true,
242
- });
243
- const lines = result.trim().split('\n').filter(Boolean);
244
- if (lines.length === 0) return `(no git history for ${relPath})`;
245
- return `${relPath}: last ${lines.length} commits — ${lines[0].substring(0, 60)}`;
246
- }
247
-
248
- /**
249
- * Check if a file exists within project root (pure Node — cross-platform).
250
- * @param {string} filePath - project-relative or absolute path
251
- * @param {string} projectRoot - absolute project root
252
- * @returns {string} "true" or "false"
253
- */
254
- function fileExists(filePath, projectRoot) {
255
- let absPath;
256
- try {
257
- absPath = resolveFilePath(filePath, projectRoot);
258
- } catch {
259
- return 'false'; // invalid/escaped path → treat as not-found
260
- }
261
- return fs.existsSync(absPath) ? 'true' : 'false';
262
- }
263
-
264
- // ── Template Rendering ──────────────────────────────────────
265
-
266
- /**
267
- * Render a template string, replacing {{result}} with the command output.
268
- * Truncates to PER_GUARD_CAP chars with ellipsis if needed.
269
- * @param {string} template
270
- * @param {string} result - raw command output
271
- * @returns {string} rendered and capped output
272
- */
273
- function renderTemplate(template, result) {
274
- const rendered = (template || '{{result}}').replace(/\{\{result\}\}/g, result);
275
- if (rendered.length > PER_GUARD_CAP) {
276
- return rendered.slice(0, PER_GUARD_CAP - 1) + '…';
277
- }
278
- return rendered;
279
- }
280
-
281
- // ── Single Guard Evaluator ──────────────────────────────────
282
-
283
- /**
284
- * Evaluate a single guard's precompute field.
285
- * Returns rendered string, or null if skipped (when=never or condition unmet).
286
- *
287
- * @param {object} guard - guard object with .precompute field
288
- * @param {object} taskData - phase data for when-condition evaluation
289
- * @param {string} projectRoot - absolute project root
290
- * @returns {string|null} rendered output or null
291
- */
292
- function evaluateGuard(guard, taskData, projectRoot) {
293
- const pc = guard.precompute;
294
- if (!pc || !pc.cmd) return null;
295
-
296
- // Evaluate when condition
297
- const when = (pc.when || 'always').trim();
298
- if (when === 'never') return null;
299
- if (when !== 'always') {
300
- // Treat as a taskData key name — run only if taskData[when] is truthy
301
- const safeData = taskData || {};
302
- if (!safeData[when]) return null;
303
- }
304
-
305
- let rawResult;
306
- try {
307
- const cmd = pc.cmd;
308
- switch (cmd) {
309
- case 'gitShowStat':
310
- rawResult = gitShowStat(pc.sha || 'HEAD', projectRoot);
311
- break;
312
-
313
- case 'gitDiffStat':
314
- rawResult = gitDiffStat(pc.sha1 || 'HEAD~1', pc.sha2 || 'HEAD', projectRoot);
315
- break;
316
-
317
- case 'grepCount':
318
- rawResult = grepCount(pc.pattern || '.', pc.file || '', projectRoot);
319
- break;
320
-
321
- case 'wcLines':
322
- rawResult = wcLines(pc.file || '', projectRoot);
323
- break;
324
-
325
- case 'fileExists':
326
- rawResult = fileExists(pc.path || pc.file || '', projectRoot);
327
- break;
328
-
329
- case 'gitCommitsAhead':
330
- rawResult = gitCommitsAhead(pc.baseRef || pc.ref || 'origin/main', projectRoot);
331
- break;
332
-
333
- case 'gitLogShort':
334
- rawResult = gitLogShort(pc.file || pc.path || '', projectRoot);
335
- break;
336
-
337
- default:
338
- return `[precompute: unknown cmd "${String(cmd).slice(0, 40)}"]`;
339
- }
340
- } catch (e) {
341
- // Surface error as result — guard still renders, just shows what went wrong
342
- return `[precompute error: ${String(e.message).slice(0, 150)}]`;
343
- }
344
-
345
- return renderTemplate(pc.template || '{{result}}', rawResult);
346
- }
347
-
348
- // ── Batch Runner ────────────────────────────────────────────
349
-
350
- /**
351
- * Run precompute for all guards that have a precompute field.
352
- * Mutates each matching guard object by adding a `precompute_result` field.
353
- *
354
- * Budget enforcement:
355
- * - Skips remaining guards if TOTAL_BUDGET_MS exceeded
356
- * - Skips remaining guards if TOTAL_CAP bytes exceeded
357
- * - Per-command timeout enforced by execFileSync timeout option (1s)
358
- *
359
- * Note: Uses synchronous execution (execFileSync). Promise.all is used
360
- * structurally for forward compatibility; true parallelism requires async
361
- * fs/child_process APIs which can be introduced in a follow-up.
362
- *
363
- * @param {Array<object>} guards - guard objects from readBlindSpotGuards
364
- * @param {object} taskData - current phase data (for when-condition evaluation)
365
- * @param {string} projectRoot - absolute project root path
366
- */
367
- function runPrecompute(guards, taskData, projectRoot) {
368
- // Kill switch: skip all precompute
369
- if (isDisabled()) {
370
- return;
371
- }
372
-
373
- if (!Array.isArray(guards) || guards.length === 0) return;
374
-
375
- const startMs = Date.now();
376
- let totalOutput = 0;
377
- let budgetExceeded = false;
378
-
379
- for (const guard of guards) {
380
- if (!guard.precompute) continue; // backward compat: guards without precompute unchanged
381
-
382
- // Budget gate: check elapsed time
383
- if (!budgetExceeded && (Date.now() - startMs) >= TOTAL_BUDGET_MS) {
384
- budgetExceeded = true;
385
- // Log warning to stderr (non-blocking — caller can inspect guard objects)
386
- process.stderr.write('[precompute] WARN: total budget (3s) exceeded — remaining guards skipped\n');
387
- }
388
-
389
- if (budgetExceeded) {
390
- guard.precompute_result = '[precompute: budget exceeded — skipped]';
391
- continue;
392
- }
393
-
394
- // Total output cap gate
395
- if (totalOutput >= TOTAL_CAP) {
396
- guard.precompute_result = '[precompute: total output cap (4096 bytes) reached — skipped]';
397
- continue;
398
- }
399
-
400
- const result = evaluateGuard(guard, taskData, projectRoot);
401
-
402
- if (result !== null && result !== undefined) {
403
- // Enforce total cap: trim result to fit remaining budget
404
- const remaining = TOTAL_CAP - totalOutput;
405
- if (result.length > remaining) {
406
- guard.precompute_result = result.slice(0, remaining - 1) + '…';
407
- totalOutput = TOTAL_CAP; // cap reached
408
- } else {
409
- guard.precompute_result = result;
410
- totalOutput += result.length;
411
- }
412
- }
413
- }
414
- }
415
-
416
- // ── Exports ─────────────────────────────────────────────────
417
-
418
- module.exports = {
419
- // Primary API
420
- runPrecompute,
421
-
422
- // Named functions (exported for unit testing)
423
- gitShowStat,
424
- gitDiffStat,
425
- grepCount,
426
- wcLines,
427
- fileExists,
428
- gitCommitsAhead,
429
- gitLogShort,
430
-
431
- // Validators (exported for unit testing)
432
- validateSha,
433
- resolveFilePath,
434
-
435
- // Helpers (exported for unit testing)
436
- renderTemplate,
437
- evaluateGuard,
438
-
439
- // Constants (exported for unit testing)
440
- TOTAL_BUDGET_MS,
441
- PER_CMD_TIMEOUT_MS,
442
- PER_GUARD_CAP,
443
- TOTAL_CAP,
444
- };