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
@@ -1,275 +0,0 @@
1
- /**
2
- * Validate command - 驗證 .matrix 文件語法並提供修復建議
3
- */
4
-
5
- import * as fs from 'fs';
6
- import { MatrixValidator } from '../../validator';
7
- import { MatrixParser } from '../../parser';
8
- import { MatrixSerializer } from '../../serializer';
9
- import { log, error as logError, success } from '../utils/logger';
10
- import type { ParseError } from '../../../types';
11
-
12
- interface ValidateOptions {
13
- fix?: boolean;
14
- }
15
-
16
- /**
17
- * Validate command handler
18
- */
19
- export async function validateCommand(file: string, options: ValidateOptions): Promise<void> {
20
- try {
21
- // 確保文件有 .matrix 擴展名
22
- const filePath = file.endsWith('.matrix') ? file : `${file}.matrix`;
23
-
24
- // 檢查文件是否存在
25
- if (!fs.existsSync(filePath)) {
26
- throw new Error(`File not found: ${filePath}`);
27
- }
28
-
29
- // 讀取文件
30
- const content = fs.readFileSync(filePath, 'utf-8');
31
-
32
- // 執行驗證
33
- const validator = new MatrixValidator();
34
- const result = validator.validate(content);
35
-
36
- // 顯示結果
37
- displayValidationResults(result.errors, result.warnings, filePath);
38
-
39
- // 如果有錯誤,提供修復建議
40
- if (!result.valid && result.errors.length > 0) {
41
- log('\n💡 Fix Suggestions:\n');
42
- provideFixSuggestions(result.errors, content, filePath);
43
-
44
- // 如果啟用了 --fix 選項,嘗試自動修復
45
- if (options.fix) {
46
- log('\n🔧 Attempting auto-fix...\n');
47
- const fixed = attemptAutoFix(content, result.errors, filePath);
48
- if (fixed) {
49
- success(`✅ File fixed successfully: ${filePath}`);
50
- } else {
51
- logError('⚠️ Some errors could not be auto-fixed. Please fix manually.');
52
- }
53
- }
54
- } else if (result.warnings.length > 0) {
55
- log('\n⚠️ File is valid but has warnings. Consider addressing them.\n');
56
- } else {
57
- success(`\n✅ File is valid: ${filePath}\n`);
58
- }
59
-
60
- } catch (err) {
61
- logError((err as Error).message);
62
- throw err;
63
- }
64
- }
65
-
66
- /**
67
- * 顯示驗證結果
68
- */
69
- function displayValidationResults(errors: ParseError[], warnings: ParseError[], filePath: string): void {
70
- log(`\n📋 Validation Report for: ${filePath}\n`);
71
- log('─'.repeat(80));
72
-
73
- // 顯示錯誤
74
- if (errors.length > 0) {
75
- log(`\n❌ Errors (${errors.length}):\n`);
76
- for (const error of errors) {
77
- const location = error.line ? ` at line ${error.line}` : '';
78
- log(` [${error.code}] ${error.message}${location}`);
79
- if (error.expected) {
80
- log(` Expected: ${error.expected}`);
81
- }
82
- if (error.got) {
83
- log(` Got: ${error.got}`);
84
- }
85
- }
86
- }
87
-
88
- // 顯示警告
89
- if (warnings.length > 0) {
90
- log(`\n⚠️ Warnings (${warnings.length}):\n`);
91
- for (const warning of warnings) {
92
- const location = warning.line ? ` at line ${warning.line}` : '';
93
- log(` [${warning.code}] ${warning.message}${location}`);
94
- }
95
- }
96
-
97
- log('\n' + '─'.repeat(80));
98
- }
99
-
100
- /**
101
- * 提供修復建議
102
- */
103
- function provideFixSuggestions(errors: ParseError[], content: string, filePath: string): void {
104
- const lines = content.split(/\r?\n/);
105
- const suggestions: string[] = [];
106
-
107
- for (const error of errors) {
108
- const suggestion = getSuggestionForError(error, lines);
109
- if (suggestion && !suggestions.includes(suggestion)) {
110
- suggestions.push(suggestion);
111
- }
112
- }
113
-
114
- for (let i = 0; i < suggestions.length; i++) {
115
- log(` ${i + 1}. ${suggestions[i]}`);
116
- }
117
-
118
- log('');
119
- }
120
-
121
- /**
122
- * 根據錯誤代碼生成具體的修復建議
123
- */
124
- function getSuggestionForError(error: ParseError, lines: string[]): string {
125
- switch (error.code) {
126
- case 'E000':
127
- return '文件為空。請添加至少包含 @meta 和 @index 的內容。\n 範例:\n # .matrix v1.0\n @meta |v=1.0|c=T|\n @index |tot=0|';
128
-
129
- case 'E001':
130
- if (error.message.includes('@meta')) {
131
- return '缺少 @meta 層。請在文件開頭加入:\n @meta |v=1.0|c=T| (v=版本號, c=分類)';
132
- }
133
- if (error.message.includes('@index')) {
134
- return '缺少 @index 層。請在 @meta 之後加入:\n @index |tot=0| (tot=總數)';
135
- }
136
- return '缺少必要的層級。請確保文件包含 @meta 和 @index。';
137
-
138
- case 'E002':
139
- if (error.message.includes('Duplicate')) {
140
- return `刪除重複的 ${error.message.includes('@meta') ? '@meta' : '@index'} 層,每個文件只能有一個。`;
141
- }
142
- if (error.message.includes('order')) {
143
- return '調整層級順序:@meta 必須在最前面,接著是 @index,最後是 @data(可選)。';
144
- }
145
- return '檢查層級順序和重複性。';
146
-
147
- case 'E003':
148
- if (error.line && lines[error.line - 1]) {
149
- const line = lines[error.line - 1].trim();
150
- return `第 ${error.line} 行格式錯誤。正確格式應為:\n ${error.expected || '|field=value|...|}'}`;
151
- }
152
- return '檢查分隔符 | 是否正確。每行應以 | 開始和結束。';
153
-
154
- case 'E004':
155
- return '欄位格式錯誤。每個欄位應為 key=value 格式,使用 | 分隔。\n 範例:|field1=value1|field2=value2|';
156
-
157
- case 'E005':
158
- if (error.message.includes('v')) {
159
- return '@meta 必須包含 v (version) 欄位。請加入:v=1.0';
160
- }
161
- if (error.message.includes('c')) {
162
- return '@meta 必須包含 c (category) 欄位。請加入:c=T (T/M/R/P 或自訂)';
163
- }
164
- return '@meta 必須包含 v (version) 和 c (category) 欄位。';
165
-
166
- case 'E006':
167
- return '時間戳格式錯誤。應使用 YYMMDD-HHMM 格式,例如:260207-1430';
168
-
169
- case 'E007':
170
- return '偵測到重複的記錄 ID。每個記錄的 ID 必須唯一。請檢查 @data 層的 ID。';
171
-
172
- case 'E008':
173
- return '未知的欄位鍵名。請確認欄位名稱是否正確或是否為自訂欄位。';
174
-
175
- case 'E009':
176
- return '值類型錯誤。請檢查欄位值是否符合預期類型(數字、布林、字串等)。';
177
-
178
- case 'E010':
179
- return '版本號格式錯誤。應使用語意化版本號,例如:1.0.0 或 2.1.3';
180
-
181
- default:
182
- return `錯誤代碼 ${error.code}: ${error.message}`;
183
- }
184
- }
185
-
186
- /**
187
- * 嘗試自動修復常見錯誤
188
- */
189
- function attemptAutoFix(content: string, errors: ParseError[], filePath: string): boolean {
190
- let fixedContent = content;
191
- let hasChanges = false;
192
-
193
- // 修復 E000: 空文件
194
- if (errors.some(e => e.code === 'E000')) {
195
- fixedContent = `# .matrix v1.0\n@meta |v=1.0|c=T|\n@index |tot=0|\n@data\n`;
196
- hasChanges = true;
197
- }
198
-
199
- // 修復 E001: 缺少 @meta
200
- if (errors.some(e => e.code === 'E001' && e.message.includes('@meta'))) {
201
- const lines = fixedContent.split(/\r?\n/);
202
- // 在第一個非註釋行之前插入 @meta
203
- let insertIndex = 0;
204
- while (insertIndex < lines.length && lines[insertIndex].trim().startsWith('#')) {
205
- insertIndex++;
206
- }
207
- lines.splice(insertIndex, 0, '@meta |v=1.0|c=T|');
208
- fixedContent = lines.join('\n');
209
- hasChanges = true;
210
- }
211
-
212
- // 修復 E001: 缺少 @index
213
- if (errors.some(e => e.code === 'E001' && e.message.includes('@index'))) {
214
- const lines = fixedContent.split(/\r?\n/);
215
- // 在 @meta 之後插入 @index
216
- const metaIndex = lines.findIndex(l => l.trim().startsWith('@meta'));
217
- if (metaIndex >= 0) {
218
- lines.splice(metaIndex + 1, 0, '@index |tot=0|');
219
- fixedContent = lines.join('\n');
220
- hasChanges = true;
221
- }
222
- }
223
-
224
- // 修復 E003: 分隔符錯誤(簡單情況)
225
- const delimiterErrors = errors.filter(e => e.code === 'E003');
226
- if (delimiterErrors.length > 0) {
227
- const lines = fixedContent.split(/\r?\n/);
228
- for (const error of delimiterErrors) {
229
- if (error.line && error.line <= lines.length) {
230
- const lineIndex = error.line - 1;
231
- let line = lines[lineIndex].trim();
232
-
233
- // 如果缺少開頭或結尾的 |
234
- if (line.startsWith('@meta') || line.startsWith('@index')) {
235
- const match = line.match(/^(@\w+)\s+(.+)$/);
236
- if (match) {
237
- const section = match[1];
238
- let content = match[2];
239
- if (!content.startsWith('|')) content = '|' + content;
240
- if (!content.endsWith('|')) content = content + '|';
241
- lines[lineIndex] = `${section} ${content}`;
242
- hasChanges = true;
243
- }
244
- }
245
- }
246
- }
247
- fixedContent = lines.join('\n');
248
- }
249
-
250
- // 如果有修改,保存文件
251
- if (hasChanges) {
252
- // 備份原文件
253
- const backupPath = `${filePath}.backup`;
254
- fs.writeFileSync(backupPath, content, 'utf-8');
255
- log(` 📦 Original file backed up to: ${backupPath}`);
256
-
257
- // 寫入修復後的內容
258
- fs.writeFileSync(filePath, fixedContent, 'utf-8');
259
- log(` ✅ Fixed ${errors.length} error(s)`);
260
-
261
- // 重新驗證
262
- const validator = new MatrixValidator();
263
- const revalidateResult = validator.validate(fixedContent);
264
-
265
- if (revalidateResult.valid) {
266
- log(` ✅ File is now valid!`);
267
- return true;
268
- } else {
269
- log(` ⚠️ Some errors remain (${revalidateResult.errors.length}). Manual fix may be required.`);
270
- return false;
271
- }
272
- }
273
-
274
- return false;
275
- }
@@ -1,350 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * matrix CLI - Command line tool for .matrix file operations
4
- * @version 1.0.0
5
- */
6
-
7
- import { Command } from 'commander';
8
- import { createCommand } from './commands/create';
9
- import { readCommand } from './commands/read';
10
- import { updateCommand } from './commands/update';
11
- import { deleteCommand } from './commands/delete';
12
- import { queryCommand } from './commands/query';
13
- import { convertCommand } from './commands/convert';
14
- import { validateCommand } from './commands/validate';
15
- // TODO: Import new commands after fixing parser adaptation
16
- // import { statsCommand } from './commands/stats';
17
- // import { tokensCommand } from './commands/tokens';
18
- // import { listTagsCommand } from './commands/list-tags';
19
- // import { addTagCommand, removeTagCommand, showRuleTagsCommand } from './commands/manage-tags';
20
-
21
- const program = new Command();
22
-
23
- program
24
- .name('matrix')
25
- .description('CLI tool for managing .matrix format files')
26
- .version('1.1.0');
27
-
28
- // CREATE command
29
- program
30
- .command('create <file>')
31
- .description('Create a new .matrix file')
32
- .option('-v, --version <version>', 'Version number (e.g., 1.0.0)')
33
- .option('-c, --category <category>', 'Category (T/M/R/P or custom)')
34
- .option('-i, --interactive', 'Use interactive mode', false)
35
- .action(async (file, options) => {
36
- try {
37
- await createCommand(file, options);
38
- } catch (error) {
39
- console.error('Error:', (error as Error).message);
40
- process.exit(1);
41
- }
42
- })
43
- .addHelpText(
44
- 'after',
45
- `
46
- Examples:
47
- $ matrix create tasks.matrix -v 1.0.0 -c T
48
- $ matrix create memory -i
49
- $ matrix create project_status --version 2.0.0 --category P
50
- `
51
- );
52
-
53
- // READ command
54
- program
55
- .command('read <file>')
56
- .description('Read and display .matrix file content')
57
- .option('-l, --level <level>', 'Display level (1=overview, 2=recent 10, 3=all)', '3')
58
- .action((file, options) => {
59
- try {
60
- const level = parseInt(options.level, 10);
61
- if (isNaN(level) || level < 1 || level > 3) {
62
- console.error('Error: Level must be 1, 2, or 3');
63
- process.exit(1);
64
- }
65
- readCommand(file, { level });
66
- } catch (error) {
67
- console.error('Error:', (error as Error).message);
68
- process.exit(1);
69
- }
70
- })
71
- .addHelpText(
72
- 'after',
73
- `
74
- Examples:
75
- $ matrix read tasks.matrix
76
- $ matrix read tasks.matrix --level 1
77
- $ matrix read memory.matrix -l 2
78
- `
79
- );
80
-
81
- // UPDATE command
82
- program
83
- .command('update <file> <rule-id>')
84
- .description('Update a specific rule in .matrix file')
85
- .option('-f, --field <field>', 'Field name to update')
86
- .option('-v, --value <value>', 'New value for the field')
87
- .option('-i, --interactive', 'Use interactive mode', false)
88
- .action(async (file, ruleId, options) => {
89
- try {
90
- await updateCommand(file, ruleId, options);
91
- } catch (error) {
92
- console.error('Error:', (error as Error).message);
93
- process.exit(1);
94
- }
95
- })
96
- .addHelpText(
97
- 'after',
98
- `
99
- Examples:
100
- $ matrix update tasks.matrix TASK_001 -f status -v completed
101
- $ matrix update tasks.matrix TASK_002 -i
102
- $ matrix update memory.matrix MEM_005 --field priority --value high
103
- `
104
- );
105
-
106
- // DELETE command
107
- program
108
- .command('delete <file> <rule-id>')
109
- .description('Delete a rule from .matrix file')
110
- .option('-f, --force', 'Skip confirmation prompt', false)
111
- .action(async (file, ruleId, options) => {
112
- try {
113
- await deleteCommand(file, ruleId, options);
114
- } catch (error) {
115
- console.error('Error:', (error as Error).message);
116
- process.exit(1);
117
- }
118
- })
119
- .addHelpText(
120
- 'after',
121
- `
122
- Examples:
123
- $ matrix delete tasks.matrix TASK_001
124
- $ matrix delete tasks.matrix TASK_002 -f
125
- $ matrix delete memory.matrix MEM_OLD --force
126
- `
127
- );
128
-
129
- // QUERY command
130
- program
131
- .command('query <file>')
132
- .description('Query .matrix file with filters')
133
- .option('-t, --tag <tag>', 'Filter by tag')
134
- .option('-p, --priority <priority>', 'Filter by priority (P0/P1/P2/P3)')
135
- .option('-s, --status <status>', 'Filter by status (pending/in_progress/completed/blocked)')
136
- .option('-k, --keyword <keyword>', 'Search by keyword (in all fields)')
137
- .option('-f, --format <format>', 'Output format (table/json/compact)', 'table')
138
- .action(async (file, options) => {
139
- try {
140
- await queryCommand(file, options);
141
- } catch (error) {
142
- console.error('Error:', (error as Error).message);
143
- process.exit(1);
144
- }
145
- })
146
- .addHelpText(
147
- 'after',
148
- `
149
- Examples:
150
- $ matrix query tasks.matrix --status pending
151
- $ matrix query tasks.matrix -s completed -p P0
152
- $ matrix query tasks.matrix --tag feature --format json
153
- $ matrix query tasks.matrix -k "authentication" -f compact
154
- `
155
- );
156
-
157
- // CONVERT command
158
- program
159
- .command('convert <input> <output>')
160
- .description('Convert between .matrix and JSON formats')
161
- .option('--from <format>', 'Input format (json/matrix, auto-detected if not specified)')
162
- .option('--to <format>', 'Output format (json/matrix, auto-detected if not specified)')
163
- .action(async (input, output, options) => {
164
- try {
165
- await convertCommand(input, output, options);
166
- } catch (error) {
167
- console.error('Error:', (error as Error).message);
168
- process.exit(1);
169
- }
170
- })
171
- .addHelpText(
172
- 'after',
173
- `
174
- Examples:
175
- $ matrix convert tasks.matrix tasks.json
176
- $ matrix convert tasks.json tasks.matrix
177
- $ matrix convert input.matrix output.json --from matrix --to json
178
- `
179
- );
180
-
181
- // VALIDATE command
182
- program
183
- .command('validate <file>')
184
- .description('Validate .matrix file syntax and provide fix suggestions')
185
- .option('--fix', 'Attempt to auto-fix simple errors', false)
186
- .action(async (file, options) => {
187
- try {
188
- await validateCommand(file, options);
189
- } catch (error) {
190
- console.error('Error:', (error as Error).message);
191
- process.exit(1);
192
- }
193
- })
194
- .addHelpText(
195
- 'after',
196
- `
197
- Examples:
198
- $ matrix validate tasks.matrix
199
- $ matrix validate tasks.matrix --fix
200
- $ matrix validate memory.matrix
201
- `
202
- );
203
-
204
- // TODO: New commands (WIP - parser adaptation needed)
205
- /*
206
- // STATS command
207
- program
208
- .command('stats <file>')
209
- .description('Display statistics about .matrix file')
210
- .option('-v, --verbose', 'Show detailed statistics', false)
211
- .action(async (file, options) => {
212
- try {
213
- await statsCommand(file, options);
214
- } catch (error) {
215
- console.error('Error:', (error as Error).message);
216
- process.exit(1);
217
- }
218
- })
219
- .addHelpText(
220
- 'after',
221
- `
222
- Examples:
223
- $ matrix stats tasks.matrix
224
- $ matrix stats tasks.matrix --verbose
225
- $ matrix stats .rule/INDEX.matrix -v
226
- `
227
- );
228
-
229
- // TOKENS command
230
- program
231
- .command('tokens <file>')
232
- .description('Calculate token count and compression ratio')
233
- .option('-v, --verbose', 'Show detailed token analysis', false)
234
- .action(async (file, options) => {
235
- try {
236
- await tokensCommand(file, options);
237
- } catch (error) {
238
- console.error('Error:', (error as Error).message);
239
- process.exit(1);
240
- }
241
- })
242
- .addHelpText(
243
- 'after',
244
- `
245
- Examples:
246
- $ matrix tokens tasks.matrix
247
- $ matrix tokens tasks.matrix --verbose
248
- $ matrix tokens .rule/INDEX.matrix
249
- `
250
- );
251
-
252
- // LIST-TAGS command
253
- program
254
- .command('list-tags <file>')
255
- .description('List all tags and their usage counts')
256
- .option('-t, --type <type>', 'Filter by tag type (source/category/priority/domain/custom)')
257
- .option('-s, --sort <sort>', 'Sort by name or count (default: count)', 'count')
258
- .action(async (file, options) => {
259
- try {
260
- await listTagsCommand(file, options);
261
- } catch (error) {
262
- console.error('Error:', (error as Error).message);
263
- process.exit(1);
264
- }
265
- })
266
- .addHelpText(
267
- 'after',
268
- `
269
- Examples:
270
- $ matrix list-tags tasks.matrix
271
- $ matrix list-tags tasks.matrix --type priority
272
- $ matrix list-tags tasks.matrix -t custom --sort name
273
- `
274
- );
275
-
276
- // ADD-TAG command
277
- program
278
- .command('add-tag <file> <rule-id> <tag>')
279
- .description('Add a tag to a rule')
280
- .option('-f, --force', 'Skip confirmation', false)
281
- .action(async (file, ruleId, tag, options) => {
282
- try {
283
- await addTagCommand(file, ruleId, tag, options);
284
- } catch (error) {
285
- console.error('Error:', (error as Error).message);
286
- process.exit(1);
287
- }
288
- })
289
- .addHelpText(
290
- 'after',
291
- `
292
- Examples:
293
- $ matrix add-tag tasks.matrix TASK_001 feature
294
- $ matrix add-tag tasks.matrix TASK_002 "#urgent"
295
- $ matrix add-tag memory.matrix MEM_005 archived -f
296
- `
297
- );
298
-
299
- // REMOVE-TAG command
300
- program
301
- .command('remove-tag <file> <rule-id> <tag>')
302
- .description('Remove a tag from a rule')
303
- .option('-f, --force', 'Skip confirmation', false)
304
- .action(async (file, ruleId, tag, options) => {
305
- try {
306
- await removeTagCommand(file, ruleId, tag, options);
307
- } catch (error) {
308
- console.error('Error:', (error as Error).message);
309
- process.exit(1);
310
- }
311
- })
312
- .addHelpText(
313
- 'after',
314
- `
315
- Examples:
316
- $ matrix remove-tag tasks.matrix TASK_001 feature
317
- $ matrix remove-tag tasks.matrix TASK_002 "#urgent"
318
- $ matrix remove-tag memory.matrix MEM_005 archived -f
319
- `
320
- );
321
-
322
- // SHOW-RULE-TAGS command
323
- program
324
- .command('show-tags <file> <rule-id>')
325
- .description('Show all tags for a specific rule')
326
- .action(async (file, ruleId) => {
327
- try {
328
- await showRuleTagsCommand(file, ruleId);
329
- } catch (error) {
330
- console.error('Error:', (error as Error).message);
331
- process.exit(1);
332
- }
333
- })
334
- .addHelpText(
335
- 'after',
336
- `
337
- Examples:
338
- $ matrix show-tags tasks.matrix TASK_001
339
- $ matrix show-tags memory.matrix MEM_005
340
- `
341
- );
342
- */
343
-
344
- // Parse arguments
345
- program.parse(process.argv);
346
-
347
- // Show help if no command provided
348
- if (!process.argv.slice(2).length) {
349
- program.outputHelp();
350
- }
@@ -1,72 +0,0 @@
1
- /**
2
- * File Handler Utility
3
- * Handles file I/O operations with error handling
4
- */
5
-
6
- import * as fs from 'fs';
7
- import * as path from 'path';
8
- import { Logger } from './logger';
9
-
10
- export class FileHandler {
11
- /**
12
- * Read .matrix file content
13
- * @param filePath Path to .matrix file
14
- * @returns File content or null if error
15
- */
16
- static read(filePath: string): string | null {
17
- try {
18
- if (!fs.existsSync(filePath)) {
19
- Logger.error(`File not found: ${filePath}`);
20
- return null;
21
- }
22
-
23
- return fs.readFileSync(filePath, 'utf-8');
24
- } catch (error) {
25
- Logger.error(`Failed to read file: ${(error as Error).message}`);
26
- return null;
27
- }
28
- }
29
-
30
- /**
31
- * Write content to .matrix file
32
- * @param filePath Path to .matrix file
33
- * @param content File content
34
- * @returns Success status
35
- */
36
- static write(filePath: string, content: string): boolean {
37
- try {
38
- // Ensure directory exists
39
- const dir = path.dirname(filePath);
40
- if (!fs.existsSync(dir)) {
41
- fs.mkdirSync(dir, { recursive: true });
42
- }
43
-
44
- fs.writeFileSync(filePath, content, 'utf-8');
45
- return true;
46
- } catch (error) {
47
- Logger.error(`Failed to write file: ${(error as Error).message}`);
48
- return false;
49
- }
50
- }
51
-
52
- /**
53
- * Check if file exists
54
- * @param filePath Path to file
55
- * @returns True if exists
56
- */
57
- static exists(filePath: string): boolean {
58
- return fs.existsSync(filePath);
59
- }
60
-
61
- /**
62
- * Ensure file has .matrix extension
63
- * @param filePath Original file path
64
- * @returns File path with .matrix extension
65
- */
66
- static ensureExtension(filePath: string): string {
67
- if (!filePath.endsWith('.matrix')) {
68
- return `${filePath}.matrix`;
69
- }
70
- return filePath;
71
- }
72
- }