kenaz 0.3.22 → 0.3.24

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 (474) hide show
  1. package/core/.claude/hooks/_user-scope.js +1 -1
  2. package/core/.claude/hooks/core-resolve.js +1 -1
  3. package/core/.claude/hooks/worktree-create.js +11 -29
  4. package/core/.claude/hooks/worktree-remove.js +12 -38
  5. package/core/.collaboration/core/reconcile.js +16 -1
  6. package/core/.collaboration/core/task-2467-lifecycle.test.js +63 -0
  7. package/core/.collaboration/core/task-api.js +37 -7
  8. package/core/.formation/bifrost/launch.js +1 -1
  9. package/core/.formation/tools/dispatch-detail/worktree-subagent-mode.md +6 -1
  10. package/core/.formation/tools/kenaz-stats.js +1 -1
  11. package/core/.formation/tools/post-complete/git-merge.js +1 -1
  12. package/core/.formation/tools/prompt.js +1 -1
  13. package/core/.formation/tools/utils.js +5 -5
  14. package/core/.formation/tools/worktree-reclaim.js +73 -2
  15. package/core/.formation/tools/worktree-reclaim.test.js +113 -0
  16. package/core/.kenaz/specialist/ansuz_rules.yaml +7 -51
  17. package/core/.kenaz/specialist/ansuz_session_handoff.schema.json +2 -6
  18. package/core/.rule/general/project-self-containment.yaml +2 -2
  19. package/core/.specialist/Amelia/README.md +1 -1
  20. package/core/.specialist/Amelia/rule.yaml +1 -1
  21. package/core/.specialist/Ansuz/RULES.md +6 -2
  22. package/core/.specialist/Ansuz/concepts/commitment_layer.yaml +1 -1
  23. package/core/.specialist/Ansuz/concepts/evolvable_guardrails.yaml +1 -1
  24. package/core/.specialist/Ansuz/knowledge.yaml +1 -3
  25. package/core/.specialist/tools/__tests__/task-2409-lessons.test.js +10 -0
  26. package/core/.specialist/tools/__tests__/task-2427-harvest.test.js +25 -0
  27. package/core/.specialist/tools/ansuz-boot-fast.js +1 -1
  28. package/core/.specialist/tools/failure-detector.js +4 -4
  29. package/core/.specialist/tools/handoff-doc.js +1 -1
  30. package/core/.specialist/tools/lessons.js +2 -2
  31. package/core/CLAUDE.md +5 -5
  32. package/core/KENAZ_CORE_VERSION +1 -1
  33. package/core/dashboard/scripts/install-kenaz-cli.js +56 -30
  34. package/core/dev/scripts/check-file-size.js +1 -1
  35. package/core/dev/scripts/ci-feedback.js +1 -1
  36. package/core/dev/scripts/gc-agent-worktrees.js +13 -12
  37. package/core/dev/scripts/kenaz-session.js +3 -3
  38. package/core/dev/scripts/peer-identity-e2e.js +6 -4
  39. package/core/dev/scripts/run-rust-tests.js +2 -2
  40. package/core/dev/scripts/skill-routing-replay.js +3 -3
  41. package/core/dev/scripts/task1961/selftest.js +2 -2
  42. package/core/dev/scripts/windows-hide-guard.test.js +112 -0
  43. package/core/plugins/kenaz/guidance.md +1 -0
  44. package/core/plugins/kenaz/hooks/core-resolve.js +1 -1
  45. package/core/plugins/kenaz/hooks/hooks.json +9 -0
  46. package/core/plugins/kenaz/hooks/kenaz-hook.js +58 -4
  47. package/core/plugins/kenaz/hooks/worktree-guard.js +121 -0
  48. package/core/plugins/kenaz/hooks/worktree-guard.test.js +75 -0
  49. package/core/plugins/kenaz/scripts/kenaz.test.js +72 -5
  50. package/core/plugins/kenaz-peer/hooks/register.test.ts +14 -2
  51. package/core/plugins/kenaz-peer/hooks/register.ts +6 -1
  52. package/lib/cli.js +9 -5
  53. package/package.json +6 -6
  54. package/vendor/install-kenaz-cli.js +56 -30
  55. package/core/.kenaz/designs/METAPLASTICITY_CONFIDENCE_DESIGN.md +0 -537
  56. package/core/.kenaz/designs/REFLEX_INITIATOR_DESIGN.md +0 -501
  57. package/core/.kenaz/designs/TASK_1385_handoff_mcp_design.md +0 -426
  58. package/core/.kenaz/designs/TASK_932_hippocampus_consolidation.md +0 -103
  59. package/core/.kenaz/designs/TASK_934_efe_signal_engine.md +0 -97
  60. package/core/.kenaz/designs/TASK_935_self_evolution_framework.md +0 -154
  61. package/core/.kenaz/designs/VISION_cognitive_architecture_roadmap.md +0 -159
  62. package/core/.kenaz/designs/metaplasticity_simulation_results.json +0 -696
  63. package/core/.kenaz/main-memory/README.md +0 -230
  64. package/core/.kenaz/main-memory/kenaz/cortex/001_cortex_overview.md +0 -168
  65. package/core/.kenaz/main-memory/kenaz/cortex/001_rag_engine_overview.md +0 -30
  66. package/core/.kenaz/main-memory/kenaz/memory-system/001_three_tier_architecture.md +0 -361
  67. package/core/.kenaz/main-memory/kenaz/pipeline/001_task_execution_flow.md +0 -117
  68. package/core/.kenaz/main-memory/kenaz/pipeline/001_task_granularity.md +0 -154
  69. package/core/.kenaz/main-memory/kenaz/pipeline/002_team_priority.md +0 -51
  70. package/core/.kenaz/main-memory/kenaz/pipeline/003_feature_id_system.md +0 -46
  71. package/core/.kenaz/main-memory/kenaz/rules/001_gen_007_self_containment.md +0 -108
  72. package/core/.kenaz/main-memory/kenaz/rules/001_rule_priority_system.md +0 -121
  73. package/core/.kenaz/main-memory/kenaz/rules/002_agt_006_pre_check.md +0 -0
  74. package/core/.kenaz/main-memory/kenaz/rules/003_ppl_002_task_archival.md +0 -48
  75. package/core/.kenaz/main-memory/kenaz/system/001_dual_track_task_system.md +0 -197
  76. package/core/.kenaz/main-memory/knowledge/patterns/001_json_bom_issue.md +0 -78
  77. package/core/.kenaz/main-memory/knowledge/patterns/001_leader_worker_pattern.md +0 -0
  78. package/core/.kenaz/main-memory/knowledge/patterns/002_scope_path_conflict.md +0 -115
  79. package/core/.kenaz/main-memory/knowledge/patterns/002_task_dependency_resolution.md +0 -223
  80. package/core/.kenaz/main-memory/knowledge/patterns/003_question_protocol.md +0 -242
  81. package/core/.kenaz/main-memory/knowledge/patterns/004_user_insight_value.md +0 -111
  82. package/core/.kenaz/main-memory/knowledge/patterns/005_file_lock_pattern.md +0 -274
  83. package/core/.kenaz/main-memory/knowledge/references/001_ppl_rules.md +0 -28
  84. package/core/.kenaz/main-memory/knowledge/solutions/001_json_bom_issue.md +0 -137
  85. package/core/.kenaz/main-memory/knowledge/solutions/001_team_invocation.md +0 -0
  86. package/core/.kenaz/main-memory/knowledge/solutions/002_passive_monitoring.md +0 -0
  87. package/core/.kenaz/main-memory/knowledge/solutions/003_windows_file_race_condition.md +0 -239
  88. package/core/.kenaz/main-memory/registry.json +0 -326
  89. package/core/.kenaz/main-memory/version.yaml +0 -58
  90. package/core/.kenaz/specialist/memory_guard_fired.json +0 -1
  91. package/core/.kenaz/specialist/memory_guard_trigger_cache.json +0 -1
  92. package/core/.kenaz/specialist/memory_source_priority.yaml +0 -260
  93. package/core/.kenaz/specialist/prompt_1775.txt +0 -317
  94. package/core/.kenaz/specialist/prompt_1776.txt +0 -326
  95. package/core/.kenaz/specialist/prompt_1791.txt +0 -320
  96. package/core/.kenaz/specialist/prompt_1792.txt +0 -320
  97. package/core/.kenaz/specialist/prompt_1795.txt +0 -281
  98. package/core/.kenaz/specialist/prompt_1813.txt +0 -332
  99. package/core/.kenaz/specialist/prompt_1814.txt +0 -401
  100. package/core/.kenaz/specialist/prompt_1815.txt +0 -394
  101. package/core/.kenaz/specialist/prompt_1816.txt +0 -437
  102. package/core/.kenaz/specialist/prompt_1818.txt +0 -361
  103. package/core/.kenaz/specialist/prompt_1819.txt +0 -421
  104. package/core/.kenaz/specialist/prompt_1821.txt +0 -345
  105. package/core/.kenaz/specialist/prompt_1822.txt +0 -313
  106. package/core/.kenaz/specialist/prompt_1824.txt +0 -348
  107. package/core/.kenaz/specialist/prompt_1826.txt +0 -388
  108. package/core/.kenaz/specialist/rune_efe_salience_gap.md +0 -21
  109. package/core/.kenaz/specialist/task1825_update.json +0 -43
  110. package/core/.kenaz/specialist/taskgen/consolidation_i.json +0 -38
  111. package/core/.kenaz/specialist/taskgen/csharp_a.json +0 -44
  112. package/core/.kenaz/specialist/taskgen/csharp_b.json +0 -40
  113. package/core/.kenaz/specialist/taskgen/embedding_e.json +0 -34
  114. package/core/.kenaz/specialist/taskgen/hygiene_fg.json +0 -39
  115. package/core/.kenaz/specialist/taskgen/pathology_h.json +0 -36
  116. package/core/.kenaz/specialist/taskgen/unity_noise_d.json +0 -38
  117. package/core/.kenaz/specialist/taskgen/visibility_c.json +0 -38
  118. package/core/.specialist/Ansuz/decisions/ADR-requirement-graph-layer.md +0 -390
  119. package/core/.specialist/Ansuz/self_model_seed.backup.json +0 -100
  120. package/core/.specialist/ansuz_session_handoff.json +0 -96
  121. package/core/dev/ALAYA_FIELD_FEEDBACK_DESIGN.md +0 -126
  122. package/core/dev/ANSUZ_SCAFFOLD_DIET_2026-09-20.md +0 -231
  123. package/core/dev/ANSUZ_STARTUP_INJECTION_REVIEW.md +0 -355
  124. package/core/dev/ANSUZ_WORKFLOW_MODERNIZATION.md +0 -143
  125. package/core/dev/CORTEX_META_GRAPH_ASSESSMENT.md +0 -99
  126. package/core/dev/FREYA_DOWNSTREAM_BUGS_2026-09-19.md +0 -44
  127. package/core/dev/GLOBAL_MEMORY_IDENTITY_CONSOLIDATION.md +0 -263
  128. package/core/dev/GUARD_EFFECTIVENESS_DESIGN.md +0 -180
  129. package/core/dev/HEALTH_GATE_VARIANCE_ASSESSMENT.md +0 -271
  130. package/core/dev/HOOK_DIET_2026-09-21.md +0 -126
  131. package/core/dev/JEV_INTEGRATION_PLAN.md +0 -189
  132. package/core/dev/KENAZ_AGENT_CONNECT_v1_SPEC.md +0 -139
  133. package/core/dev/MOBILE_DESIGN_SPEC.md +0 -569
  134. package/core/dev/MULTI_ANSUZ_SPEC.md +0 -136
  135. package/core/dev/MUNINN_RETIREMENT.md +0 -115
  136. package/core/dev/PHASE3_ATTRIBUTION_POPULATION_DIAGNOSIS.md +0 -211
  137. package/core/dev/PHASE3_P3-2B_TASKLEVEL_PROBE.md +0 -83
  138. package/core/dev/PHASE3_P3-2_POPULATION_DISJOINTNESS.md +0 -83
  139. package/core/dev/PHASE3_P3-2_REMEASURE_REPORT.md +0 -231
  140. package/core/dev/PREDICTION_GROUNDING_DESIGN.md +0 -376
  141. package/core/dev/PRODUCT_SPEC.md +0 -317
  142. package/core/dev/PROJECT_REGISTRY_DUPLICATE_ASSESSMENT.md +0 -86
  143. package/core/dev/STARTUP_TIMELINE_TASK_1995.md +0 -181
  144. package/core/dev/SYNAPSE_WORKER_PER_PROJECT.md +0 -881
  145. package/core/dev/TASK_1680_P3-3_DISPATCH_SPEC.md +0 -96
  146. package/core/dev/TASK_1684_CALIBRATION_IMPACT_ANALYSIS.md +0 -170
  147. package/core/dev/TASK_1684_FORK_A_GOODHART_DESIGN.md +0 -171
  148. package/core/dev/TASK_1684_P3_2_REMEASURE_VALIDATION.md +0 -262
  149. package/core/dev/TASK_1903_SIGNAL_AUC_MEASUREMENT.md +0 -207
  150. package/core/dev/TASK_1904_BRANCH_INTEGRITY_AUDIT.md +0 -146
  151. package/core/dev/ansuz-eval/README.md +0 -38
  152. package/core/dev/ansuz-eval/build-fixtures.js +0 -87
  153. package/core/dev/ansuz-eval/grade.js +0 -96
  154. package/core/dev/ansuz-eval/grader.test.js +0 -117
  155. package/core/dev/ansuz-eval/tasks.md +0 -32
  156. package/core/dev/archive/ansuz/BOOT_FULL.md +0 -141
  157. package/core/dev/archive/ansuz/agents/ansuz-boot.md +0 -176
  158. package/core/dev/archive/ansuz/designs/alaya-passive-surfacing.md +0 -84
  159. package/core/dev/archive/ansuz/designs/cc_memory_indexing.md +0 -307
  160. package/core/dev/archive/ansuz/designs/check_guard.md +0 -322
  161. package/core/dev/archive/ansuz/designs/consequence_loop.md +0 -227
  162. package/core/dev/archive/ansuz/designs/mcp_kuzudb_lock_architecture.md +0 -312
  163. package/core/dev/archive/ansuz/designs/phase0_git_enrichment.md +0 -278
  164. package/core/dev/archive/ansuz/designs/refactor_mcp_tools_synapse.md +0 -490
  165. package/core/dev/archive/ansuz/designs/semantic_markdown_extraction.md +0 -167
  166. package/core/dev/archive/ansuz/designs/task_1372_prompt_injects_into.md +0 -193
  167. package/core/dev/archive/ansuz/designs/thought_stack.md +0 -286
  168. package/core/dev/archive/ansuz/investigations/reachability_unified_api_2026-04-11.md +0 -330
  169. package/core/dev/archive/ansuz/investigations/synapse_orphans_indexing_bug_2026-04-11.md +0 -352
  170. package/core/dev/archive/ansuz/investigations/synapse_orphans_reindex_verification_2026-04-11.md +0 -48
  171. package/core/dev/archive/ansuz/investigations/synapse_orphans_verification_2026-04-11.md +0 -170
  172. package/core/dev/archive/ansuz/legacy/kernel.yaml +0 -399
  173. package/core/dev/archive/ansuz/legacy/phases/phase_0.yaml +0 -418
  174. package/core/dev/archive/ansuz/legacy/phases/phase_1.yaml +0 -376
  175. package/core/dev/archive/ansuz/legacy/phases/phase_10.yaml +0 -35
  176. package/core/dev/archive/ansuz/legacy/phases/phase_11.yaml +0 -582
  177. package/core/dev/archive/ansuz/legacy/phases/phase_2.yaml +0 -94
  178. package/core/dev/archive/ansuz/legacy/phases/phase_3.yaml +0 -274
  179. package/core/dev/archive/ansuz/legacy/phases/phase_4.yaml +0 -67
  180. package/core/dev/archive/ansuz/legacy/phases/phase_5.yaml +0 -32
  181. package/core/dev/archive/ansuz/legacy/phases/phase_6.yaml +0 -91
  182. package/core/dev/archive/ansuz/legacy/phases/phase_7.yaml +0 -58
  183. package/core/dev/archive/ansuz/legacy/phases/phase_8.yaml +0 -146
  184. package/core/dev/archive/ansuz/legacy/phases/phase_9.yaml +0 -424
  185. package/core/dev/archive/ansuz/specs/INDEX_bifrost_hook_parity.yaml +0 -92
  186. package/core/dev/archive/ansuz/specs/active-inference-formation.yaml +0 -453
  187. package/core/dev/archive/ansuz/specs/brief_TASK_1228_userpromptsubmit.yaml +0 -191
  188. package/core/dev/archive/ansuz/specs/brief_TASK_1229_pretooluse_posttooluse.yaml +0 -250
  189. package/core/dev/archive/ansuz/specs/brief_TASK_1230_sessionstart_stop.yaml +0 -301
  190. package/core/dev/archive/ansuz/specs/brief_TASK_1231_verification.yaml +0 -272
  191. package/core/dev/archive/skills/feature_agent/SKILL.md +0 -289
  192. package/core/dev/design/PHASE4_DESIGN.md +0 -559
  193. package/core/dev/design/dashboard_docs_integration_PLAN.md +0 -388
  194. package/core/dev/design/matrix_format_ABBREVIATIONS.md +0 -655
  195. package/core/dev/design/matrix_format_DESIGN_SPEC.md +0 -601
  196. package/core/dev/design/matrix_format_DISCUSSION_SUMMARY.md +0 -484
  197. package/core/dev/design/matrix_format_EXAMPLE_memory.matrix +0 -13
  198. package/core/dev/design/matrix_format_EXAMPLE_project_status.matrix +0 -9
  199. package/core/dev/design/matrix_format_EXAMPLE_tasks.matrix +0 -14
  200. package/core/dev/design/matrix_format_SYNTAX_BNF.md +0 -754
  201. package/core/dev/design/matrix_format_TOKEN_COMPARISON.md +0 -484
  202. package/core/dev/design/matrix_v2_COGNITIVE_DESIGN.md +0 -503
  203. package/core/dev/design/matrix_v2_DISCUSSION_SUMMARY.md +0 -414
  204. package/core/dev/design/matrix_v2_EXAMPLE.matrix +0 -67
  205. package/core/dev/designs/EXPANDABLE_CARD_DESIGN_SPEC.md +0 -509
  206. package/core/dev/jev-eval/ACTIVE_CORRECTION.md +0 -52
  207. package/core/dev/jev-eval/ANNOTATION_GUIDE.md +0 -68
  208. package/core/dev/jev-eval/BASELINE_COMPARISON.md +0 -45
  209. package/core/dev/jev-eval/CONTEXT_REVIEW.md +0 -31
  210. package/core/dev/jev-eval/EVALUATION_STATUS.md +0 -39
  211. package/core/dev/jev-eval/HISTORICAL_CORPUS.md +0 -33
  212. package/core/dev/jev-eval/PACKAGING_VERIFICATION.md +0 -42
  213. package/core/dev/jev-eval/README.md +0 -101
  214. package/core/dev/jev-eval/THALAMUS_RANKING.md +0 -58
  215. package/core/dev/jev-eval/VALIDATION_PROGRESS.md +0 -54
  216. package/core/dev/jev-eval/cli.mjs +0 -50
  217. package/core/dev/jev-eval/context.mjs +0 -183
  218. package/core/dev/jev-eval/corpus.mjs +0 -186
  219. package/core/dev/jev-eval/fixtures/conversation-review.seed.jsonl +0 -6
  220. package/core/dev/jev-eval/fixtures/synthetic.jsonl +0 -11
  221. package/core/dev/jev-eval/metrics.mjs +0 -67
  222. package/core/dev/jev-eval/muninn-baseline.mjs +0 -119
  223. package/core/dev/jev-eval/providers.mjs +0 -95
  224. package/core/dev/jev-eval/reports/annotation-pilot-2026-09-20.json +0 -32
  225. package/core/dev/jev-eval/reports/context-review-2026-09-20.json +0 -48
  226. package/core/dev/jev-eval/reports/conversation-review.pending.json +0 -151
  227. package/core/dev/jev-eval/reports/history-corpus-2026-09-20.json +0 -52
  228. package/core/dev/jev-eval/reports/length-probe-2026-09-20.json +0 -133
  229. package/core/dev/jev-eval/reports/live-smoke-2026-09-20.json +0 -616
  230. package/core/dev/jev-eval/reports/muninn-baseline-2026-09-20.json +0 -52
  231. package/core/dev/jev-eval/reports/resilience-2026-09-20.json +0 -520
  232. package/core/dev/jev-eval/reports/rules-baseline.json +0 -197
  233. package/core/dev/jev-eval/reports/synthetic-review.pending.json +0 -357
  234. package/core/dev/jev-eval/resilience.mjs +0 -71
  235. package/core/dev/jev-eval/review.mjs +0 -78
  236. package/core/dev/jev-eval/schema.mjs +0 -87
  237. package/core/dev/jev-eval/test/context.test.mjs +0 -95
  238. package/core/dev/jev-eval/test/corpus.test.mjs +0 -102
  239. package/core/dev/jev-eval/test/eval.test.mjs +0 -146
  240. package/core/dev/jev-eval/test/muninn-baseline.test.mjs +0 -71
  241. package/core/dev/jev-eval/test/resilience.test.mjs +0 -72
  242. package/core/dev/jev-eval/test/review.test.mjs +0 -61
  243. package/core/dev/pipeline/PHASE3_PLANNING_SUMMARY.md +0 -338
  244. package/core/dev/pipeline/PROGRESS.md +0 -113
  245. package/core/dev/pipeline/PROGRESS_template.md +0 -860
  246. package/core/dev/pipeline/QA_REPORT_F008.md +0 -431
  247. package/core/dev/pipeline/QA_REPORT_LOCAL_CLAUDE_DIAGNOSIS.md +0 -583
  248. package/core/dev/pipeline/README.md +0 -210
  249. package/core/dev/pipeline/WORKFLOW_GUIDE.md +0 -824
  250. package/core/dev/pipeline/archived/TASK_015_tauri_init.yaml +0 -53
  251. package/core/dev/pipeline/archived/TASK_016_tauri_commands.yaml +0 -54
  252. package/core/dev/pipeline/archived/TASK_017_rust_pty.yaml +0 -54
  253. package/core/dev/pipeline/archived/TASK_018_tauri_bundle.yaml +0 -53
  254. package/core/dev/pipeline/archived/TASK_019_release_workflow.yaml +0 -56
  255. package/core/dev/pipeline/archived/TASK_020_update_ui.yaml +0 -54
  256. package/core/dev/pipeline/archived/TASK_021_update_notification_ui.yaml +0 -55
  257. package/core/dev/pipeline/archived/TASK_022_remove_node_pty.yaml +0 -65
  258. package/core/dev/pipeline/archived/TASK_023_api_routes_migration.yaml +0 -86
  259. package/core/dev/pipeline/archived/TASK_024_feature_id_system.yaml +0 -51
  260. package/core/dev/pipeline/archived/TASK_025_executable_acceptance.yaml +0 -66
  261. package/core/dev/pipeline/archived/TASK_026_spec_versioning.yaml +0 -56
  262. package/core/dev/pipeline/archived/TASK_027_drift_detection.yaml +0 -60
  263. package/core/dev/pipeline/archived/TASK_028_tauri_pty_manager.yaml +0 -60
  264. package/core/dev/pipeline/archived/TASK_029_tauri_pty_commands.yaml +0 -62
  265. package/core/dev/pipeline/archived/TASK_030_frontend_session_adapter.yaml +0 -54
  266. package/core/dev/pipeline/archived/TASK_031_terminal_tauri_events.yaml +0 -56
  267. package/core/dev/pipeline/archived/TASK_041_scheduler_data_models.yaml +0 -54
  268. package/core/dev/pipeline/archived/TASK_042_path_lock_manager.yaml +0 -53
  269. package/core/dev/pipeline/archived/TASK_043_process_manager.yaml +0 -57
  270. package/core/dev/pipeline/archived/TASK_044_git_integration.yaml +0 -85
  271. package/core/dev/pipeline/archived/TASK_045_task_queue_manager.yaml +0 -54
  272. package/core/dev/pipeline/archived/TASK_046_scheduler_dispatcher.yaml +0 -60
  273. package/core/dev/pipeline/archived/TASK_047_tauri_scheduler_commands.yaml +0 -55
  274. package/core/dev/pipeline/archived/TASK_048_realtime_status_push.yaml +0 -92
  275. package/core/dev/pipeline/archived/TASK_049_frontend_scheduler_integration.yaml +0 -58
  276. package/core/dev/pipeline/archived/TASK_050_error_recovery.yaml +0 -56
  277. package/core/dev/pipeline/archived/TASK_051_optimization_proposals_backend.yaml +0 -53
  278. package/core/dev/pipeline/archived/TASK_052_optimization_proposals_ui.yaml +0 -58
  279. package/core/dev/pipeline/archived/TASK_053_optimization_proposals_diff_view.yaml +0 -54
  280. package/core/dev/pipeline/archived/TASK_054_multi_project_scheduler_state.yaml +0 -76
  281. package/core/dev/pipeline/archived/TASK_055_scheduler_api_project_scope.yaml +0 -64
  282. package/core/dev/pipeline/archived/TASK_056_frontend_scheduler_project_scope.yaml +0 -62
  283. package/core/dev/pipeline/archived/TASK_057_scheduler_module_structure.yaml +0 -54
  284. package/core/dev/pipeline/archived/TASK_058_scheduler_models_extract.yaml +0 -51
  285. package/core/dev/pipeline/archived/TASK_059_scheduler_core_extract.yaml +0 -51
  286. package/core/dev/pipeline/archived/TASK_060_scheduler_commands_extract.yaml +0 -51
  287. package/core/dev/pipeline/archived/TASK_061_scheduler_specialized_commands.yaml +0 -53
  288. package/core/dev/pipeline/archived/TASK_062_process_manager_module_structure.yaml +0 -56
  289. package/core/dev/pipeline/archived/TASK_063_process_manager_core_extract.yaml +0 -56
  290. package/core/dev/pipeline/archived/TASK_064_recovery_module_structure.yaml +0 -57
  291. package/core/dev/pipeline/archived/TASK_065_recovery_core_extract.yaml +0 -56
  292. package/core/dev/pipeline/archived/TASK_066_self_enhancement_scheduler_models.yaml +0 -60
  293. package/core/dev/pipeline/archived/TASK_067_agents_section_quick_actions.yaml +0 -53
  294. package/core/dev/pipeline/archived/TASK_067_self_enhancement_scheduler_core.yaml +0 -65
  295. package/core/dev/pipeline/archived/TASK_068_agent_workflow_rule_enhancement.yaml +0 -46
  296. package/core/dev/pipeline/archived/TASK_068_self_enhancement_tauri_commands.yaml +0 -61
  297. package/core/dev/pipeline/archived/TASK_069_agent_wizard_responsive.yaml +0 -46
  298. package/core/dev/pipeline/archived/TASK_069_self_enhancement_ui.yaml +0 -62
  299. package/core/dev/pipeline/archived/TASK_070_preview_panel_redesign.yaml +0 -62
  300. package/core/dev/pipeline/archived/TASK_070_self_enhancement_integration.yaml +0 -57
  301. package/core/dev/pipeline/archived/TASK_071_preview_panel_qa.yaml +0 -98
  302. package/core/dev/pipeline/archived/TASK_071_single_agent_config.yaml +0 -57
  303. package/core/dev/pipeline/archived/TASK_072_preview_modal_esc_fix.yaml +0 -71
  304. package/core/dev/pipeline/archived/TASK_072_product_review_module.yaml +0 -57
  305. package/core/dev/pipeline/archived/TASK_073_agents_page_component_refactor.yaml +0 -68
  306. package/core/dev/pipeline/archived/TASK_073_rename_single_agent.yaml +0 -64
  307. package/core/dev/pipeline/archived/TASK_074_preview_mode_ui_diagnosis.yaml +0 -71
  308. package/core/dev/pipeline/archived/TASK_074_single_agent_ui_toggle.yaml +0 -56
  309. package/core/dev/pipeline/archived/TASK_075_agents_page_component_refactor.yaml +0 -69
  310. package/core/dev/pipeline/archived/TASK_075_single_agent_integration_test.yaml +0 -75
  311. package/core/dev/pipeline/archived/TASK_076_preview_mode_ui_diagnosis.yaml +0 -70
  312. package/core/dev/pipeline/archived/TASK_076_single_agent_continuous_mode.yaml +0 -65
  313. package/core/dev/pipeline/archived/TASK_077_failure_directory_structure.yaml +0 -51
  314. package/core/dev/pipeline/archived/TASK_077_single_agent_typescript_types.yaml +0 -59
  315. package/core/dev/pipeline/archived/TASK_078_fail_001_agent_no_output.yaml +0 -53
  316. package/core/dev/pipeline/archived/TASK_078_single_agent_ui_simplify.yaml +0 -74
  317. package/core/dev/pipeline/archived/TASK_079_dashboard_rwd_responsive.yaml +0 -63
  318. package/core/dev/pipeline/archived/TASK_079_fail_002_json_bom.yaml +0 -56
  319. package/core/dev/pipeline/archived/TASK_080_fail_003_queue_pollution.yaml +0 -56
  320. package/core/dev/pipeline/archived/TASK_080_http_server_module.yaml +0 -55
  321. package/core/dev/pipeline/archived/TASK_081_failure_logging_tools.yaml +0 -57
  322. package/core/dev/pipeline/archived/TASK_081_http_api_routes.yaml +0 -62
  323. package/core/dev/pipeline/archived/TASK_082_frontend_api_adapter.yaml +0 -51
  324. package/core/dev/pipeline/archived/TASK_082_integrate_failure_to_workflow.yaml +0 -60
  325. package/core/dev/pipeline/archived/TASK_083_cleanup_nextjs_api.yaml +0 -48
  326. package/core/dev/pipeline/archived/TASK_083_task_queue_cleanup.yaml +0 -67
  327. package/core/dev/pipeline/archived/TASK_084_rust_dead_code_cleanup.yaml +0 -66
  328. package/core/dev/pipeline/archived/TASK_084_scheduler_sync_logic_fix.yaml +0 -68
  329. package/core/dev/pipeline/archived/TASK_085_http_api_web_mode_fixes.yaml +0 -46
  330. package/core/dev/pipeline/archived/TASK_085_memory_consolidation_0204_0205.yaml +0 -98
  331. package/core/dev/pipeline/archived/TASK_086_collapsible_preview_panel.yaml +0 -161
  332. package/core/dev/pipeline/archived/TASK_086_web_mode_feature_parity.yaml +0 -62
  333. package/core/dev/pipeline/archived/TASK_087_manual_memory_archival.yaml +0 -163
  334. package/core/dev/pipeline/archived/TASK_087_mobile_http_control.yaml +0 -68
  335. package/core/dev/pipeline/archived/TASK_088_fail_003_to_ppl_002_rule.yaml +0 -63
  336. package/core/dev/pipeline/archived/TASK_088_mobile_http_qa.yaml +0 -121
  337. package/core/dev/pipeline/archived/TASK_089_agent_collaboration_topic.yaml +0 -60
  338. package/core/dev/pipeline/archived/TASK_089_web_mode_monitor_fix.yaml +0 -58
  339. package/core/dev/pipeline/archived/TASK_090_cli_detection_fix.yaml +0 -61
  340. package/core/dev/pipeline/archived/TASK_090_ui_ux_lessons_topic.yaml +0 -63
  341. package/core/dev/pipeline/archived/TASK_091_expandable_card_design.yaml +0 -56
  342. package/core/dev/pipeline/archived/TASK_091_move_agent_section_components.yaml +0 -65
  343. package/core/dev/pipeline/archived/TASK_092_expandable_card_component.yaml +0 -60
  344. package/core/dev/pipeline/archived/TASK_092_refactor_agent_create_wizard.yaml +0 -84
  345. package/core/dev/pipeline/archived/TASK_093_taskcard_detail_integration.yaml +0 -57
  346. package/core/dev/pipeline/archived/TASK_093_update_barrel_exports_test.yaml +0 -84
  347. package/core/dev/pipeline/archived/TASK_094_ai_agent_generation_enhancement.yaml +0 -115
  348. package/core/dev/pipeline/archived/TASK_094_proposalcard_detail_integration.yaml +0 -55
  349. package/core/dev/pipeline/archived/TASK_095_preview_fixes.yaml +0 -129
  350. package/core/dev/pipeline/archived/TASK_095_single_agent_task_selector.yaml +0 -60
  351. package/core/dev/pipeline/archived/TASK_096_agents_page_ux_improvements.yaml +0 -163
  352. package/core/dev/pipeline/archived/TASK_096_single_agent_status_sync.yaml +0 -60
  353. package/core/dev/pipeline/archived/TASK_097_local_claude_error_logging.yaml +0 -59
  354. package/core/dev/pipeline/archived/TASK_097_single_agent_monitor_events.yaml +0 -59
  355. package/core/dev/pipeline/archived/TASK_098_product_manager_team_phase2.yaml +0 -60
  356. package/core/dev/pipeline/archived/TASK_098_single_agent_refactor_test.yaml +0 -58
  357. package/core/dev/pipeline/archived/TASK_099_backend_team_creation.yaml +0 -258
  358. package/core/dev/pipeline/archived/TASK_100_frontend_team_creation.yaml +0 -61
  359. package/core/dev/pipeline/archived/TASK_101_orchestrator_system.yaml +0 -403
  360. package/core/dev/pipeline/archived/TASK_102_designer_sre_teams.yaml +0 -90
  361. package/core/dev/pipeline/archived/TASK_103_integration_testing.yaml +0 -86
  362. package/core/dev/pipeline/archived/TASK_128_integration_testing.yaml +0 -83
  363. package/core/dev/pipeline/archived/TASK_134_cortex_v2_phase3_file_watcher.yaml +0 -65
  364. package/core/dev/pipeline/archived/TASK_134_team_http_api.yaml +0 -96
  365. package/core/dev/pipeline/archived/TASK_135_cortex_v2_phase3_git_monitor.yaml +0 -63
  366. package/core/dev/pipeline/archived/TASK_136_cortex_v2_phase3_change_analyzer.yaml +0 -69
  367. package/core/dev/pipeline/archived/TASK_137_cortex_v2_phase3_cache_invalidator.yaml +0 -67
  368. package/core/dev/pipeline/archived/TASK_137_team_orchestrator_integration.yaml +0 -93
  369. package/core/dev/pipeline/archived/TASK_138_cortex_v2_phase3_distributed_cache.yaml +0 -68
  370. package/core/dev/pipeline/archived/TASK_138_matrix_folder_structure.yaml +0 -61
  371. package/core/dev/pipeline/archived/TASK_139_cortex_v2_phase3_cache_prewarming.yaml +0 -65
  372. package/core/dev/pipeline/archived/TASK_146_unified_documentation.yaml +0 -141
  373. package/core/dev/pipeline/archived/TASK_147_pipeline_execution_rules.yaml +0 -76
  374. package/core/dev/pipeline/archived/TASK_148_update_claude_md.yaml +0 -77
  375. package/core/dev/pipeline/archived/TASK_149_fix_nextjs_mdx_serialization.yaml +0 -63
  376. package/core/dev/pipeline/archived/TASK_149_update_team_docs.yaml +0 -77
  377. package/core/dev/pipeline/archived/TASK_150_pipeline_workflow_guide.yaml +0 -82
  378. package/core/dev/pipeline/archived/TASK_164_fix_smart_context_switch.yaml +0 -49
  379. package/core/dev/pipeline/archived/TASK_165_ctags_symbol_index.yaml +0 -53
  380. package/core/dev/pipeline/archived/TASK_166_symbol_search_mcp_tool.yaml +0 -48
  381. package/core/dev/pipeline/archived/TASK_167_llm_module_summary.yaml +0 -55
  382. package/core/dev/pipeline/archived/TASK_168_map_reduce_context.yaml +0 -51
  383. package/core/dev/pipeline/archived/TASK_169_v2_integration_testing.yaml +0 -52
  384. package/core/dev/pipeline/backups/archive_2026-02-04T22-07-22/TASK_QUEUE_backup.json +0 -95
  385. package/core/dev/pipeline/docs/multi-agent-coordination.md +0 -446
  386. package/core/dev/pipeline/docs/overview.md +0 -406
  387. package/core/dev/pipeline/docs/task-management.md +0 -412
  388. package/core/dev/pipeline/docs/workflows.md +0 -32
  389. package/core/dev/pipeline/orchestrator/schemas/task_queue_schema.json +0 -58
  390. package/core/dev/pipeline/orchestrator/schemas/task_schema.json +0 -139
  391. package/core/dev/pipeline/plans/PLAN_task_cli_refactor.md +0 -281
  392. package/core/dev/pipeline/test_results/TASK_TEST_PARALLEL_002_result.txt +0 -27
  393. package/core/dev/plans/ANSUZ_SLIM_PLAN.md +0 -68
  394. package/core/dev/plans/CLI_FIRST_INSTALL_FLOW.md +0 -120
  395. package/core/dev/plans/FORMATION_RETIREMENT_PLAN.md +0 -313
  396. package/core/dev/plans/KUZU_REPLACEMENT_PLAN.md +0 -126
  397. package/core/dev/scripts/CRASH_DIAGNOSIS.md +0 -47
  398. package/core/dev/scripts/README.md +0 -142
  399. package/core/dev/scripts/RUN_ONCE.bat +0 -40
  400. package/core/dev/scripts/START_DEV_AGENT.bat +0 -63
  401. package/core/dev/scripts/START_MULTI_AGENT.bat +0 -80
  402. package/core/dev/scripts/dev_agent_scheduler.ps1 +0 -536
  403. package/core/dev/scripts/init_git.ps1 +0 -396
  404. package/core/dev/scripts/init_git.sh +0 -337
  405. package/core/dev/scripts/init_project.ps1 +0 -851
  406. package/core/dev/scripts/init_project.sh +0 -477
  407. package/core/dev/scripts/multi_agent_scheduler.ps1 +0 -2021
  408. package/core/dev/scripts/multi_agent_scheduler.sh +0 -1344
  409. package/core/dev/scripts/run_once.sh +0 -47
  410. package/core/dev/scripts/setup_rag.ps1 +0 -304
  411. package/core/dev/scripts/setup_rag.sh +0 -230
  412. package/core/dev/scripts/start_dev_agent.sh +0 -137
  413. package/core/dev/scripts/start_multi_agent.sh +0 -41
  414. package/core/dev/scripts/sync_task_queue.ps1 +0 -505
  415. package/core/dev/scripts/sync_task_queue.sh +0 -392
  416. package/core/dev/specs/agent-connect/PROTOCOL.md +0 -177
  417. package/core/dev/specs/agent-connect/SDK_GUIDE.md +0 -915
  418. package/core/dev/specs/agent-connect/examples/minimal-site/README.md +0 -137
  419. package/core/dev/specs/agent-connect/examples/minimal-site/package.json +0 -12
  420. package/core/dev/specs/agent-connect/examples/minimal-site/public/index.html +0 -116
  421. package/core/dev/specs/agent-connect/examples/minimal-site/public/install-redirect.js +0 -73
  422. package/core/dev/specs/agent-connect/examples/minimal-site/server.js +0 -516
  423. package/core/dev/specs/agent-connect/examples/minimal-site/test/smoke.test.mjs +0 -263
  424. package/core/dev/specs/agent-connect/history/DEFECT_REPORT_kenaz-agent-hub_2026-09-09_v0.4-empty-prompt-no-first-turn.md +0 -77
  425. package/core/dev/specs/agent-connect/history/DEFECT_REPORT_kenaz-agent-hub_2026-09-09_v0.4-prompt-mojibake.md +0 -90
  426. package/core/dev/specs/agent-connect/history/FEATURE_REQUEST_kenaz-agent-hub_2026-09-07.md +0 -61
  427. package/core/dev/specs/agent-connect/history/FEATURE_REQUEST_kenaz-agent-hub_2026-09-08_relay-v1-conformance.md +0 -76
  428. package/core/dev/specs/agent-connect/history/FEATURE_REQUEST_kenaz-agent-hub_2026-09-09_v0.4-session-channel.md +0 -87
  429. package/core/dev/specs/agent-connect/history/FLOWPIX_REPLY_agent-hub_2026-09-08_relay-v1-answers.md +0 -68
  430. package/core/dev/specs/agent-connect/history/FLOWPIX_bridge_CONTRACT.md +0 -642
  431. package/core/dev/specs/agent-connect/history/FLOWPIX_spikes_relay_spike_relay.mjs +0 -244
  432. package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-07.md +0 -77
  433. package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-08_direction-change-v0.3.md +0 -44
  434. package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-08_relay-v1-answers-ack.md +0 -37
  435. package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-08_relay-v1-conformance.md +0 -56
  436. package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-09_annotations-install-coldstart.md +0 -44
  437. package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-09_empty-prompt-first-turn.md +0 -56
  438. package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-09_prompt-mojibake-fixed.md +0 -48
  439. package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-09_session-channel.md +0 -57
  440. package/core/dev/specs/agent-connect/history/PROTOCOL_v0.3_snapshot.md +0 -379
  441. package/core/dev/specs/agent-connect/history/README.md +0 -47
  442. package/core/dev/specs/peer/CODEX_INTERACTIVE_PUSH.md +0 -65
  443. package/core/dev/specs/peer/CODEX_MANAGED_DAEMON.md +0 -54
  444. package/core/dev/specs/peer/CODEX_PEER_PULL_SPIKE.md +0 -54
  445. package/core/dev/specs/peer/MODS_SPIKE.md +0 -133
  446. package/core/dev/specs/peer/PER_PROJECT_ADDRESSING.md +0 -143
  447. package/core/dev/specs/peer/SWARM_PROTOCOLS.md +0 -256
  448. package/core/dev/specs/peer/codex-hook-shim-peer.test.js +0 -113
  449. package/core/dev/specs/peer/codex-push-launcher.test.js +0 -142
  450. package/core/dev/specs/peer/setup-codex-hooks.test.js +0 -60
  451. package/core/dev/specs/peer-ansuz/DELIVERY_SPIKE.md +0 -397
  452. package/core/dev/specs/peer-ansuz/DESIGN.md +0 -109
  453. package/core/dev/specs/peer-ansuz/spike/claude_poke.js +0 -129
  454. package/core/dev/specs/peer-ansuz/spike/claude_session_start_hook.js +0 -37
  455. package/core/dev/specs/peer-ansuz/spike/claude_settings_hook.json +0 -14
  456. package/core/dev/specs/peer-ansuz/spike/codex_appserver_client.js +0 -105
  457. package/core/dev/specs/peer-ansuz/spike/codex_appserver_query.js +0 -29
  458. package/core/dev/specs/peer-ansuz/spike/extract_timeline.js +0 -26
  459. package/core/dev/specs/synapse/SYMBOL_IDENTITY.md +0 -305
  460. package/core/dev/spikes/A4-cypher-varlen.md +0 -176
  461. package/core/dev/spikes/bloat-rounds.sh +0 -25
  462. package/core/dev/spikes/mods/clean-claude.js +0 -9
  463. package/core/dev/spikes/mods/drive-probe.js +0 -29
  464. package/core/dev/spikes/mods/e2e-peer.js +0 -71
  465. package/core/dev/spikes/mods/evidence/e2e-peer-control.json +0 -17
  466. package/core/dev/spikes/mods/evidence/e2e-peer-mod.json +0 -17
  467. package/core/dev/spikes/mods/evidence/probe-006a6e65-d807-4bc1-b648-fd7d1edfe0b4.jsonl +0 -4
  468. package/core/dev/spikes/mods/evidence/probe-cebdf1f7-f9c4-47a8-83cd-7c0786177404.jsonl +0 -12
  469. package/core/dev/spikes/mods/evidence/probe-eb21147d-10ce-4c32-93ed-37ca37d88d5a.jsonl +0 -11
  470. package/core/dev/spikes/mods/evidence/stream-cebdf1f7.jsonl +0 -18
  471. package/core/dev/spikes/mods/kenaz-mod-probe/.claude-plugin/plugin.json +0 -1
  472. package/core/dev/spikes/mods/kenaz-mod-probe/hooks/hooks.json +0 -1
  473. package/core/dev/spikes/mods/kenaz-mod-probe/hooks/register.ts +0 -65
  474. package/core/dev/spikes/mods/kenaz-mod-probe/tsconfig.json +0 -3
@@ -1,78 +0,0 @@
1
- import { createHash, randomUUID } from 'node:crypto';
2
- import { readFile, stat, writeFile, link, unlink } from 'node:fs/promises';
3
- import { resolve } from 'node:path';
4
- import { fileURLToPath } from 'node:url';
5
- import { check, keys, identity, stateHash, readJsonl, validateDataset, MAX_FILE_BYTES } from './schema.mjs';
6
-
7
- export const REVIEW_VERSION = 'jev-review-v1';
8
- const canonical = value => JSON.stringify(value, function (key, item) {
9
- return item && typeof item === 'object' && !Array.isArray(item) ? Object.fromEntries(Object.keys(item).sort().map(k => [k, item[k]])) : item;
10
- });
11
- export const datasetHash = rows => createHash('sha256').update(canonical(rows)).digest('hex');
12
- export function exportReview(rows) {
13
- validateDataset(rows);
14
- return { schema_version: 1, review_version: REVIEW_VERSION, dataset_hash: datasetHash(rows), items: rows.map(row => ({
15
- ...identity(row), state_hash: stateHash(row), purpose: row.purpose, language: row.language, context: structuredClone(row.state),
16
- ...(row.purpose === 'relevance' ? { candidates: row.candidates.map(({ id, text }) => ({ id, text })) } : {}),
17
- decision: row.purpose === 'correction' ? { correction: null } : { grades: row.candidates.map(c => ({ id: c.id, grade: null })) },
18
- reviewed: false, reviewer: null, reviewed_at: null,
19
- })) };
20
- }
21
- function validTime(value) {
22
- if (typeof value !== 'string' || !/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/.test(value)) return false;
23
- const time = Date.parse(value);
24
- return Number.isFinite(time) && new Date(time).toISOString() === value.replace(/(?<!\.\d{3})Z$/, '.000Z');
25
- }
26
- export function applyReview(rows, review) {
27
- const expected = exportReview(rows);
28
- keys(review, ['schema_version', 'review_version', 'dataset_hash', 'items']);
29
- check(review.schema_version === 1 && review.review_version === REVIEW_VERSION, 'invalid_review_version');
30
- check(review.dataset_hash === expected.dataset_hash, 'stale_dataset');
31
- check(Array.isArray(review.items) && review.items.length === rows.length, 'incomplete_review');
32
- const byId = new Map();
33
- for (const item of review.items) { check(item && !byId.has(item.id), 'duplicate_review'); byId.set(item.id, item); }
34
- const result = rows.map((row, index) => {
35
- const item = byId.get(row.id), base = expected.items[index]; keys(item, Object.keys(base));
36
- for (const key of Object.keys(base).filter(k => !['decision', 'reviewed', 'reviewer', 'reviewed_at'].includes(k))) check(canonical(item[key]) === canonical(base[key]), 'review_identity_mismatch');
37
- check(item.reviewed === true, 'unreviewed_item');
38
- check(typeof item.reviewer === 'string' && item.reviewer.trim().length > 0 && item.reviewer.length <= 160, 'invalid_reviewer');
39
- check(validTime(item.reviewed_at), 'invalid_review_date');
40
- const out = structuredClone(row);
41
- if (row.purpose === 'correction') { keys(item.decision, ['correction']); check(typeof item.decision.correction === 'boolean', 'invalid_review_decision'); out.labels.correction = item.decision.correction; }
42
- else {
43
- keys(item.decision, ['grades']);
44
- check(Array.isArray(item.decision.grades) && item.decision.grades.length === row.candidates.length, 'incomplete_grades');
45
- const grades = new Map();
46
- for (const c of item.decision.grades) { keys(c, ['id', 'grade']); check(!grades.has(c.id) && row.candidates.some(x => x.id === c.id) && Number.isInteger(c.grade) && c.grade >= 0 && c.grade <= 3, 'invalid_review_grade'); grades.set(c.id, c.grade); }
47
- for (const c of out.candidates) c.grade = grades.get(c.id);
48
- }
49
- out.provenance = { ...out.provenance, annotation: 'human_verified', reviewer: item.reviewer, reviewed_at: item.reviewed_at };
50
- return out;
51
- });
52
- return validateDataset(result);
53
- }
54
- export async function main(args = process.argv.slice(2)) {
55
- const [command, ...rest] = args; check(['export', 'apply'].includes(command), 'invalid_command');
56
- const options = {};
57
- for (let i = 0; i < rest.length; i += 2) { check(['--dataset', '--out', ...(command === 'apply' ? ['--reviews'] : [])].includes(rest[i]) && typeof rest[i + 1] === 'string' && !rest[i + 1].startsWith('--') && !Object.hasOwn(options, rest[i]), 'invalid_arguments'); options[rest[i]] = rest[i + 1]; }
58
- check(options['--dataset'] && options['--out'] && (command !== 'apply' || options['--reviews']), 'missing_argument');
59
- check(resolve(options['--dataset']).toLowerCase() !== resolve(options['--out']).toLowerCase() && (!options['--reviews'] || resolve(options['--reviews']).toLowerCase() !== resolve(options['--out']).toLowerCase()), 'overwrite_forbidden');
60
- const rows = validateDataset(await readJsonl(options['--dataset']));
61
- let output;
62
- if (command === 'export') output = JSON.stringify(exportReview(rows), null, 2) + '\n';
63
- else {
64
- check((await stat(options['--reviews'])).size <= MAX_FILE_BYTES, 'file_budget_exceeded');
65
- const text = await readFile(options['--reviews'], 'utf8'); check(Buffer.byteLength(text) <= MAX_FILE_BYTES, 'file_budget_exceeded');
66
- let review; try { review = JSON.parse(text.replace(/^\uFEFF/, '')); } catch { throw new Error('invalid_review_json'); }
67
- output = applyReview(rows, review).map(r => JSON.stringify(r)).join('\n') + '\n';
68
- }
69
- check(Buffer.byteLength(output) <= MAX_FILE_BYTES, 'file_budget_exceeded');
70
- // A same-directory hard link publishes only the complete file, and fails if out exists.
71
- const temporary = `${options['--out']}.${randomUUID()}.tmp`;
72
- try { await writeFile(temporary, output, { flag: 'wx', encoding: 'utf8' }); await link(temporary, options['--out']); }
73
- finally { await unlink(temporary).catch(() => {}); }
74
- return { schema_version: 1, operation: command, count: rows.length, promotion_eligible: false, human_review_is_attestation_not_proof: true };
75
- }
76
- if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) main().then(r => console.log(JSON.stringify(r, null, 2))).catch(error => {
77
- console.error(JSON.stringify({ error: /^[a-z_]{1,80}$/.test(error.message) ? error.message : error.code === 'EEXIST' ? 'output_exists' : 'operation_failed' })); process.exitCode = 1;
78
- });
@@ -1,87 +0,0 @@
1
- import { readFile, stat } from 'node:fs/promises';
2
- import { createHash } from 'node:crypto';
3
-
4
- export const MAX_FILE_BYTES = 8 * 1024 * 1024;
5
- export const MAX_RECORD_BYTES = 64 * 1024;
6
- export const SPLITS = ['development', 'calibration', 'held_out'];
7
- export function check(condition, code = 'invalid_data') { if (!condition) throw new Error(code); }
8
- export const object = x => x !== null && typeof x === 'object' && !Array.isArray(x);
9
- export const number = (x, min, max) => typeof x === 'number' && Number.isFinite(x) && x >= min && x <= max;
10
- const string = x => typeof x === 'string' && x.trim().length > 0 && x.length <= 16384;
11
- const identifier = x => typeof x === 'string' && /^[\w.:/-]{1,160}$/.test(x);
12
- export function keys(x, names) {
13
- check(object(x) && Object.keys(x).length === names.length && names.every(k => Object.hasOwn(x, k)), 'invalid_fields');
14
- }
15
- export async function readJsonl(path) {
16
- check((await stat(path)).size <= MAX_FILE_BYTES, 'file_budget_exceeded');
17
- const text = await readFile(path, 'utf8');
18
- check(Buffer.byteLength(text) <= MAX_FILE_BYTES, 'file_budget_exceeded');
19
- try { return text.replace(/^\uFEFF/, '').split(/\r?\n/).filter(x => x.trim()).map(x => {
20
- check(Buffer.byteLength(x) <= MAX_RECORD_BYTES, 'record_budget_exceeded');
21
- return JSON.parse(x);
22
- }); } catch { throw new Error('invalid_jsonl'); }
23
- }
24
- export function inputState(row) {
25
- return { purpose: row.purpose, ...row.state, ...(row.purpose === 'relevance' ? { candidates: row.candidates.map(({ id, text }) => ({ id, text })) } : {}) };
26
- }
27
- export const stateHash = row => createHash('sha256').update(JSON.stringify(inputState(row))).digest('hex');
28
- export function identity(row) {
29
- return Object.fromEntries(['id', 'project_id', 'session_id', 'task_id', 'event_id', 'event_seq', 'task_revision'].map(k => [k, row[k]]));
30
- }
31
- export function validateDataset(rows) {
32
- check(Array.isArray(rows) && rows.length > 0 && rows.length <= 10000, 'invalid_dataset_size');
33
- const ids = new Set(), events = new Set(), splits = new Map(), texts = new Map();
34
- for (const row of rows) {
35
- check(Buffer.byteLength(JSON.stringify(row)) <= MAX_RECORD_BYTES, 'record_budget_exceeded');
36
- keys(row, ['schema_version', 'id', 'project_id', 'session_id', 'group_id', 'task_id', 'event_id', 'event_seq', 'task_revision', 'purpose', 'language', 'split', 'provenance', 'state', row.purpose === 'correction' ? 'labels' : 'candidates']);
37
- check(row.schema_version === 1, 'invalid_schema_version');
38
- for (const k of ['id', 'project_id', 'session_id', 'group_id', 'task_id', 'event_id']) check(identifier(row[k]), 'invalid_identifier');
39
- for (const k of ['event_seq', 'task_revision']) check(Number.isSafeInteger(row[k]) && row[k] >= 0, 'invalid_revision');
40
- check(['correction', 'relevance'].includes(row.purpose) && ['en', 'zh', 'mixed'].includes(row.language) && SPLITS.includes(row.split), 'invalid_enum');
41
- keys(row.provenance, ['source', 'annotation', 'reviewer', 'reviewed_at']);
42
- check(['synthetic', 'real'].includes(row.provenance.source) && ['agent_proposed', 'human_verified'].includes(row.provenance.annotation), 'invalid_provenance');
43
- check(row.provenance.annotation === 'human_verified' ? string(row.provenance.reviewer) : row.provenance.reviewer === null, 'invalid_reviewer');
44
- check(row.provenance.annotation === 'human_verified' ? typeof row.provenance.reviewed_at === 'string' && /^\d{4}-\d{2}-\d{2}T/.test(row.provenance.reviewed_at) && Number.isFinite(Date.parse(row.provenance.reviewed_at)) : row.provenance.reviewed_at === null, 'invalid_review_date');
45
- keys(row.state, ['goal', 'assumptions', 'message']);
46
- check(string(row.state.goal) && string(row.state.message) && Array.isArray(row.state.assumptions) && row.state.assumptions.length <= 20 && row.state.assumptions.every(string), 'invalid_state');
47
- if (row.purpose === 'correction') { keys(row.labels, ['correction']); check(typeof row.labels.correction === 'boolean', 'invalid_label'); }
48
- else {
49
- check(Array.isArray(row.candidates) && row.candidates.length >= 2 && row.candidates.length <= 12, 'invalid_candidates');
50
- const candidateIds = new Set();
51
- for (const c of row.candidates) { keys(c, ['id', 'text', 'grade']); check(identifier(c.id) && string(c.text) && Number.isInteger(c.grade) && number(c.grade, 0, 3) && !candidateIds.has(c.id), 'invalid_candidate'); candidateIds.add(c.id); }
52
- }
53
- check(!ids.has(row.id), 'duplicate_id'); ids.add(row.id);
54
- const event = JSON.stringify([row.project_id, row.session_id, row.event_id, row.purpose]);
55
- check(!events.has(event), 'duplicate_event'); events.add(event);
56
- for (const group of [`session:${row.project_id}:${row.session_id}`, `group:${row.group_id}`]) {
57
- check(!splits.has(group) || splits.get(group) === row.split, 'split_leakage'); splits.set(group, row.split);
58
- }
59
- const hash = stateHash(row);
60
- check(!texts.has(hash) || texts.get(hash) === row.split, 'content_split_leakage'); texts.set(hash, row.split);
61
- }
62
- return rows;
63
- }
64
- export function validatePrediction(row, prediction) {
65
- keys(prediction, [...Object.keys(identity(row)), 'state_hash', 'model', 'question_set_version', 'status', 'failure_reason', 'http_status', 'usage', 'latency_ms', row.purpose === 'correction' ? 'correction_probability' : 'scores']);
66
- for (const [k, v] of Object.entries(identity(row))) check(prediction[k] === v, 'prediction_identity_mismatch');
67
- check(prediction.state_hash === stateHash(row), 'stale_prediction');
68
- check(['jev-1.13.0', 'rules-v1'].includes(prediction.model) && prediction.question_set_version === 'jev-eval-v1', 'invalid_prediction_version');
69
- check(['ok', 'abstain', 'timeout', 'unavailable', 'invalid'].includes(prediction.status), 'invalid_status');
70
- check(number(prediction.latency_ms, 0, 3600000), 'invalid_latency');
71
- check(prediction.http_status === null || Number.isInteger(prediction.http_status) && number(prediction.http_status, 100, 599), 'invalid_http_status');
72
- check(prediction.status === 'ok' ? prediction.failure_reason === null : ['timeout', 'http_failure', 'transport_failure', 'invalid_response', 'abstain'].includes(prediction.failure_reason), 'invalid_failure_reason');
73
- if (prediction.usage !== null) { keys(prediction.usage, ['input_tokens', 'output_tokens']); for (const n of Object.values(prediction.usage)) check(Number.isSafeInteger(n) && n >= 0, 'invalid_usage'); }
74
- if (row.purpose === 'correction') {
75
- check(prediction.status === 'ok' ? number(prediction.correction_probability, 0, 1) : prediction.correction_probability === null, 'invalid_probability');
76
- } else {
77
- check(Array.isArray(prediction.scores) && prediction.scores.length === row.candidates.length, 'invalid_scores');
78
- const expected = new Set(row.candidates.map(c => c.id));
79
- for (const item of prediction.scores) {
80
- keys(item, ['id', 'score']); check(expected.delete(item.id), 'invalid_score_id');
81
- check(item.score === null || number(item.score, 0, 3), 'invalid_score');
82
- if (prediction.status !== 'ok') check(item.score === null, 'failure_with_score');
83
- }
84
- if (prediction.status === 'ok') check(prediction.scores.some(s => s.score !== null), 'empty_ok_prediction');
85
- }
86
- return prediction;
87
- }
@@ -1,95 +0,0 @@
1
- import test from 'node:test';
2
- import assert from 'node:assert/strict';
3
- import { mkdtemp, writeFile, symlink, readdir, unlink, rmdir, lstat } from 'node:fs/promises';
4
- import { createHash } from 'node:crypto';
5
- import { tmpdir } from 'node:os';
6
- import { join } from 'node:path';
7
- import { enrich, resolveSource, renderHtml } from '../context.mjs';
8
- import { normalizeMessage, redactHomePaths, credentialBearing } from '../corpus.mjs';
9
-
10
- const hash = text => createHash('sha256').update(text).digest('hex'), cwd = 'C:/Users/test/Documents/GitHub/KenazAI';
11
- const c = (uuid, parentUuid, role, text, extra = {}) => ({ uuid, parentUuid, sessionId: 's1', cwd, type: role, message: { role, content: [{ type: 'text', text }] }, ...extra });
12
- async function fixture(t, kind, records, targetLine, overrides = {}) {
13
- const dir = await mkdtemp(join(tmpdir(), 'jev-context-test-'));
14
- t.after(async () => { for (const name of await readdir(dir)) { const p = join(dir, name), s = await lstat(p); if (s.isSymbolicLink() && process.platform === 'win32') await rmdir(p); else await unlink(p); } await rmdir(dir); });
15
- const path = join(dir, 'source.jsonl'), bytes = records.map(r => JSON.stringify(r) + '\n').join(''); await writeFile(path, bytes);
16
- const source = { kind, relative_path: 'source.jsonl', source_id: hash(`${kind}:source.jsonl`) };
17
- const target = records[targetLine - 1], message = normalizeMessage(redactHomePaths(kind === 'claude' ? target.message.content[0].text : target.payload.message));
18
- const row = { kind: 'pending_historical_review', id: hash(`${source.source_id}:${targetLine}:${hash(message.toLowerCase())}`), source_id: source.source_id, session_id: hash(`${kind}:s1`), group_id: 'group', message, review_status: 'pending', provenance: { source: 'real', annotation: 'unreviewed' }, ...overrides };
19
- return { dir, path, bytes, row, source, manifest: { schema_version: 1, sources: [source], items: [{ id: row.id, source_id: source.source_id, line: targetLine }] }, options: { sourceRoots: { claude: dir, codex: dir }, cwdRoots: [cwd] } };
20
- }
21
- test('Claude ancestry follows parent UUID rather than neighboring branch, skips thinking/tools/future', async t => {
22
- const records = [c('u1', null, 'user', 'Start'), c('a1', 'u1', 'assistant', 'Correct branch'), c('wrong', 'u1', 'assistant', 'Other branch'), c('tool', 'a1', 'user', '', { message: { role: 'user', content: [{ type: 'tool_result', content: 'secret tool output' }] } }), c('thinking', 'tool', 'assistant', '', { message: { role: 'assistant', content: [{ type: 'thinking', thinking: 'hidden reasoning' }] } }), c('target', 'thinking', 'user', 'Please revise'), c('future', 'target', 'assistant', 'Future answer')];
23
- const f = await fixture(t, 'claude', records, 6), before = JSON.stringify(f.row), result = await enrich([f.row], f.manifest, f.options), row = result.rows[0];
24
- assert.equal(row.status, 'restored'); assert.deepEqual(row.observed_context.map(c => c.text), ['Start', 'Correct branch']);
25
- assert.ok(row.observed_context.every(c => c.source_line < row.target_line)); assert.equal(JSON.stringify(row).includes('hidden reasoning'), false); assert.equal(JSON.stringify(row).includes('Other branch'), false);
26
- assert.equal(row.source_prefix_sha256, hash(records.slice(0, 6).map(r => JSON.stringify(r) + '\n').join(''))); assert.equal(JSON.stringify(f.row), before); assert.equal(row.decision.correction, null);
27
- });
28
- test('stale targets and wrong session rejected without dropping IDs', async t => {
29
- const f = await fixture(t, 'claude', [c('a', null, 'assistant', 'Context'), c('u', 'a', 'user', 'Target')], 2);
30
- for (const change of [r => r.message = 'Changed', r => r.session_id = hash('other'), r => r.review_status = 'human_verified']) {
31
- const row = structuredClone(f.row); change(row); const result = await enrich([row], f.manifest, f.options); assert.equal(result.rows[0].id, row.id); assert.equal(result.rows[0].status, 'rejected'); assert.equal(result.rows[0].observed_context, undefined);
32
- }
33
- });
34
- test('source paths reject traversal absolute paths hash mismatch and symlink escape', async t => {
35
- const f = await fixture(t, 'claude', [c('u', null, 'user', 'Target')], 1);
36
- for (const relative_path of ['../outside', '/absolute', 'C:\\absolute', 'nested/../../outside']) await assert.rejects(resolveSource({ kind: 'claude', relative_path, source_id: hash(`claude:${relative_path}`) }, f.options.sourceRoots), /unsafe_source_path/);
37
- await assert.rejects(resolveSource({ ...f.source, source_id: 'wrong' }, f.options.sourceRoots), /source_id_mismatch/);
38
- const outside = await fixture(t, 'claude', [c('u', null, 'user', 'Other')], 1), link = join(f.dir, 'escape');
39
- await symlink(outside.dir, link, process.platform === 'win32' ? 'junction' : 'dir');
40
- await assert.rejects(resolveSource({ kind: 'claude', relative_path: 'escape/source.jsonl', source_id: hash('claude:escape/source.jsonl') }, f.options.sourceRoots), /source_path_escape/);
41
- });
42
- test('credential context dropped as whole message and gaps remain explicit', async t => {
43
- const f = await fixture(t, 'claude', [c('a1', null, 'assistant', 'Safe context'), c('a2', 'a1', 'assistant', 'Use apikey_abcdefgh12345 now'), c('u', 'a2', 'user', 'Continue')], 3);
44
- const row = (await enrich([f.row], f.manifest, f.options)).rows[0]; assert.equal(row.status, 'partial'); assert.deepEqual(row.observed_context.map(c => c.text), ['Safe context']); assert.ok(row.context_gaps.includes('credential_context')); assert.equal(JSON.stringify(row).includes('apikey_'), false);
45
- });
46
- test('normalization and JSON quote escaping cannot hide credential context', async t => {
47
- const escaped = 'API_KEY="abcd1234"'; assert.equal(credentialBearing(escaped), true); assert.equal(credentialBearing(JSON.stringify(escaped)), false);
48
- for (const text of [escaped, 'The config is {"API_KEY":"abc12345"}', 'Use API_KEY=abc12345 locally', 'APIKEY_abcdefgh12345']) {
49
- assert.equal(credentialBearing(normalizeMessage(text)), true);
50
- const f = await fixture(t, 'claude', [c('safe', null, 'assistant', 'Safe earlier text'), c('secret', 'safe', 'assistant', text), c('target', 'secret', 'user', 'Continue')], 3);
51
- const row = (await enrich([f.row], f.manifest, f.options)).rows[0];
52
- assert.deepEqual(row.observed_context.map(c => c.text), ['Safe earlier text']);
53
- assert.ok(row.context_gaps.includes('credential_context')); assert.ok(row.observed_context.every(c => !credentialBearing(c.text)));
54
- }
55
- const target = await fixture(t, 'claude', [c('user', null, 'user', 'API_KEY=abc12345')], 1);
56
- assert.equal((await enrich([target.row], target.manifest, target.options)).rows[0].status, 'rejected');
57
- });
58
- const meta = { type: 'session_meta', payload: { id: 's1', cwd, source: 'cli' } };
59
- const assistant = text => ({ type: 'response_item', payload: { type: 'message', role: 'assistant', phase: 'final_answer', content: [{ type: 'output_text', text }] } });
60
- const user = text => ({ type: 'event_msg', payload: { type: 'user_message', message: text } });
61
- test('Codex compaction/scope resets context and event assistant duplicates are ignored', async t => {
62
- const list = [meta, assistant('Before reset'), { type: 'compacted', payload: {} }, assistant('After reset'), { type: 'event_msg', payload: { type: 'agent_message', message: 'Event duplicate' } }, user('Target'), assistant('Future')];
63
- const f = await fixture(t, 'codex', list, 6), row = (await enrich([f.row], f.manifest, f.options)).rows[0];
64
- assert.deepEqual(row.observed_context.map(c => c.text), ['After reset']); assert.ok(row.context_gaps.includes('compaction_or_rollback'));
65
- const scoped = await fixture(t, 'codex', [meta, assistant('Original cwd'), { type: 'turn_context', payload: { cwd: 'C:/Other' } }, assistant('Foreign'), { type: 'turn_context', payload: { cwd } }, user('Return')], 6);
66
- assert.equal((await enrich([scoped.row], scoped.manifest, scoped.options)).rows[0].status, 'missing');
67
- });
68
- test('bounded context marks truncation, missing ancestry never uses nearest neighbor', async t => {
69
- const long = await fixture(t, 'claude', [c('a', null, 'assistant', 'Long visible text '.repeat(500)), c('u', 'a', 'user', 'Target')], 2);
70
- const row = (await enrich([long.row], long.manifest, long.options)).rows[0]; assert.equal(row.status, 'partial'); assert.equal(row.observed_context[0].text.length, 3000); assert.equal(row.observed_context[0].truncated, true);
71
- const missing = await fixture(t, 'claude', [c('a', null, 'assistant', 'Not ancestor'), c('u', 'unknown', 'user', 'Target')], 2);
72
- const m = (await enrich([missing.row], missing.manifest, missing.options)).rows[0]; assert.equal(m.status, 'missing'); assert.ok(m.context_gaps.includes('missing_ancestor'));
73
- });
74
- test('static HTML escapes raw content and has no scripts or external resources', () => {
75
- const html = renderHtml([{ id: 'case', status: 'restored', message: '<script>fetch("https://evil")</script>', observed_context: [{ role: 'assistant', source_line: 1, text: '<img src=x onerror=alert(1)>' }] }]);
76
- assert.equal(html.includes('<script>'), false); assert.equal(html.includes('<img'), false); assert.ok(html.includes('&lt;script&gt;')); assert.ok(html.includes("default-src 'none'"));
77
- });
78
- test('metadata-only duplicate UUID tolerated; conflicting text identity rejected', async t => {
79
- const first = c('a', null, 'assistant', 'Actual context');
80
- const attachment = { uuid: 'attachment', type: 'attachment', parentUuid: 'a', sessionId: 's1', cwd, arbitraryMetadata: 1 };
81
- const f = await fixture(t, 'claude', [first, attachment, { ...attachment, arbitraryMetadata: 2 }, c('u', 'a', 'user', 'Target')], 4);
82
- assert.equal((await enrich([f.row], f.manifest, f.options)).rows[0].status, 'restored');
83
- const bad = await fixture(t, 'claude', [first, c('a', null, 'assistant', 'Conflicting context'), c('u', 'a', 'user', 'Target')], 3);
84
- assert.equal((await enrich([bad.row], bad.manifest, bad.options)).rows[0].status, 'rejected');
85
- });
86
- test('ancestry walk and Codex history window are bounded with explicit gaps', async t => {
87
- const list = [c('a', null, 'assistant', 'Ancient context')];
88
- for (let i = 0; i < 6; i++) list.push({ uuid: `tool${i}`, parentUuid: i ? `tool${i - 1}` : 'a', sessionId: 's1', cwd, type: 'user', message: { role: 'user', content: [{ type: 'tool_result', content: 'omitted' }] } });
89
- list.push(c('u', 'tool5', 'user', 'Target'));
90
- const f = await fixture(t, 'claude', list, list.length); f.options.limits = { maxAncestorSteps: 3 };
91
- const row = (await enrich([f.row], f.manifest, f.options)).rows[0]; assert.ok(row.context_gaps.includes('ancestry_budget')); assert.equal(row.status, 'missing');
92
- const history = [meta, ...Array.from({ length: 25 }, (_, i) => assistant(`Turn ${i}`)), user('Target')];
93
- const g = await fixture(t, 'codex', history, history.length), restored = (await enrich([g.row], g.manifest, g.options)).rows[0];
94
- assert.equal(restored.observed_context.length, 6); assert.ok(restored.context_gaps.includes('history_window')); assert.ok(renderHtml([restored]).includes('history_window'));
95
- });
@@ -1,102 +0,0 @@
1
- import test from 'node:test';
2
- import assert from 'node:assert/strict';
3
- import { mkdtemp, mkdir, writeFile, readdir, unlink, rmdir } from 'node:fs/promises';
4
- import { tmpdir } from 'node:os';
5
- import { join } from 'node:path';
6
- import { credentialBearing, generatedMessage, automationSeed, redactHomePaths, userText, withinRoots, extractFile, sampleCandidates, records, discover, inventory, main } from '../corpus.mjs';
7
-
8
- async function temp(t) {
9
- const dir = await mkdtemp(join(tmpdir(), 'jev-corpus-test-'));
10
- async function cleanup(path) { for (const entry of await readdir(path, { withFileTypes: true })) { const child = join(path, entry.name); if (entry.isDirectory()) await cleanup(child); else await unlink(child); } await rmdir(path); }
11
- t.after(() => cleanup(dir)); return dir;
12
- }
13
- const roots = ['C:/Users/test/Documents/GitHub/KenazAI'];
14
- const claude = (text, extra = {}) => ({ type: 'user', sessionId: 's1', cwd: roots[0], message: { role: 'user', content: text }, ...extra });
15
- const meta = (extra = {}) => ({ type: 'session_meta', payload: { id: 's1', cwd: roots[0], source: 'cli', ...extra } });
16
- const event = text => ({ type: 'event_msg', payload: { type: 'user_message', message: text } });
17
- const response = text => ({ type: 'response_item', payload: { type: 'message', role: 'user', content: [{ type: 'input_text', text }] } });
18
- async function extract(t, items, kind = 'claude', limits = {}) {
19
- const dir = await temp(t), path = join(dir, 's.jsonl'); await writeFile(path, items.map(r => JSON.stringify(r)).join('\n'));
20
- const stats = {}, candidates = await extractFile({ path, kind, relative_path: 's.jsonl' }, roots, stats, limits); return { candidates, stats };
21
- }
22
- test('credential detection quarantines whole message and home paths are removed', () => {
23
- for (const text of ['apikey_abcdefgh123456', 'sk-abcdefgh-123456', 'Authorization: Bearer abcdefgh123', '$env:TYPESAFE_API_KEY="abc123456"', 'export API_KEY=abc12345', 'password: hunter22', 'https://user:secret@site.test', '-----BEGIN PRIVATE KEY-----', 'github_pat_abcde12345678']) assert.equal(credentialBearing(text), true);
24
- assert.equal(credentialBearing('Please configure the API key locally.'), false);
25
- const clean = redactHomePaths('C:\\Users\\someone\\repo /home/someone/repo /Users/someone/file'); assert.equal(clean.includes('someone'), false);
26
- });
27
- test('generated and non-user records are excluded without fabricated labels', async t => {
28
- for (const text of ['# AGENTS.md instructions for repo', '<environment_context>cwd</environment_context>', '[CANARY:v2]', '<system-reminder>generated</system-reminder>', '<subagent_notification>done</subagent_notification>']) assert.equal(generatedMessage(text), true);
29
- assert.equal(userText(claude([{ type: 'tool_result', content: 'not user' }]), 'claude'), null);
30
- const { candidates } = await extract(t, [claude('Real request'), claude('internal', { isMeta: true }), claude('render-only', { isVisibleInTranscriptOnly: true }), { type: 'assistant', message: { role: 'assistant', content: 'not user' } }, claude('<environment_context>private</environment_context>'), claude('Another request')]);
31
- assert.equal(candidates.length, 2);
32
- for (const { row } of candidates) { for (const field of ['labels', 'goal', 'assumptions', 'grade']) assert.equal(Object.hasOwn(row, field), false); assert.equal(row.review_status, 'pending'); assert.equal(row.incomplete_context_for_correction, true); }
33
- });
34
- test('secret message cannot survive as later preceding context', async t => {
35
- const { candidates, stats } = await extract(t, [claude('First'), claude('Use apikey_abcdefgh1234 now'), claude('Next request')]);
36
- assert.equal(candidates.length, 2); assert.equal(stats.credential_message, 1); assert.equal(candidates[1].row.context_missing, true);
37
- assert.equal(JSON.stringify(candidates).includes('apikey_'), false);
38
- });
39
- test('Codex exact cwd boundaries and subagent metadata fail closed', async t => {
40
- assert.equal(withinRoots(roots[0] + '/dashboard', roots), true); assert.equal(withinRoots(roots[0] + 'Else', roots), false); assert.equal(withinRoots(roots[0] + '/../Other', roots), false);
41
- for (const metadata of [meta({ cwd: 'C:/Other' }), meta({ source: { subagent: { parent_thread_id: 'parent' } } })]) assert.equal((await extract(t, [metadata, event('Request')], 'codex')).candidates.length, 0);
42
- assert.equal((await extract(t, [event('No metadata')], 'codex')).candidates.length, 0);
43
- const proper = await extract(t, [meta(), response('Replayed old text'), event('Actual text'), response('Actual text')], 'codex');
44
- assert.equal(proper.candidates.length, 1); assert.equal(proper.candidates[0].row.message, 'Actual text'); assert.equal(proper.candidates[0].row.context_missing, true);
45
- const fallback = await extract(t, [meta(), response('Fallback text')], 'codex'); assert.equal(fallback.candidates.length, 1); assert.equal(fallback.stats.response_fallback_candidates, 1);
46
- });
47
- test('whole Claude sidechain file rejected even after first candidate', async t => {
48
- const { candidates } = await extract(t, [claude('Earlier request'), claude('Subagent request', { isSidechain: true })]); assert.equal(candidates.length, 0);
49
- });
50
- test('automation seeds exclude entire session while genuine TASK references remain', async t => {
51
- const seeds = ['- ## Automated Dispatch Context\nThis prompt was machine-assembled by the Kenaz orchestration system.', 'This prompt was machine-assembled by the Kenaz orchestration system.', '- Extract key technical insights from this conversation chunk. Output in English only. Be concise, 1-3 sentences.', '[HEADLESS MODE] 你已被 Formation Lead 指派任務', 'You have access to MCP tools from kenaz-dashboard. Call the synapse_status tool now.'];
52
- for (const seed of seeds) {
53
- assert.equal(automationSeed(seed), true);
54
- const result = await extract(t, [claude('Prior automated followup'), claude(seed), claude('Continue automatically')]);
55
- assert.equal(result.candidates.length, 0); assert.equal(result.stats.automation_seed, 1);
56
- }
57
- assert.equal(automationSeed('Please investigate TASK_35 and explain the Automated Dispatch Context header.'), false);
58
- const genuine = await extract(t, [claude('Please investigate TASK_35'), claude('[Request interrupted by user for tool use]'), claude('<turn_aborted>The user interrupted the previous turn</turn_aborted>'), claude('Continue my investigation')]);
59
- assert.equal(genuine.candidates.length, 2);
60
- const smoke = await extract(t, [meta(), event(seeds.at(-1)), event('Continue')], 'codex'); assert.equal(smoke.candidates.length, 0);
61
- });
62
- test('automation discovered in one source excludes same session in another source', async t => {
63
- const dir = await temp(t), claudeRoot = join(dir, 'claude'), codexRoot = join(dir, 'codex'), project = join(claudeRoot, 'C-KenazAI');
64
- await mkdir(project, { recursive: true }); await mkdir(codexRoot);
65
- await writeFile(join(project, 'a.jsonl'), JSON.stringify(claude('Earlier inherited automated turn')));
66
- await writeFile(join(project, 'b.jsonl'), JSON.stringify(claude('[HEADLESS MODE] 你已被 Formation Lead 指派任務')));
67
- const result = await inventory({ claudeRoot, codexRoot, roots }); assert.equal(result.rows.length, 0); assert.equal(result.summary.exclusions.cross_file_automation_candidates, 1);
68
- });
69
- test('Claude foreign/missing cwd excluded; changing session identity rejects entire file', async t => {
70
- const foreign = await extract(t, [claude('Allowed first'), claude('Foreign', { cwd: 'C:/Other' }), claude('Allowed return'), claude('Missing', { cwd: undefined })]);
71
- assert.equal(foreign.candidates.length, 2); assert.equal(foreign.candidates[1].row.context_missing, true);
72
- const mixed = await extract(t, [claude('First'), claude('Other session', { sessionId: 's2' })]); assert.equal(mixed.candidates.length, 0); assert.equal(mixed.stats.session_identity_change, 1);
73
- const reentry = await extract(t, [meta(), event('First'), { type: 'turn_context', payload: { cwd: 'C:/Other' } }, { type: 'turn_context', payload: { cwd: roots[0] } }, event('Return')], 'codex');
74
- assert.equal(reentry.candidates[1].row.context_missing, true);
75
- });
76
- test('dedup and balanced sampling deterministic; generic duplicates do not merge families', async t => {
77
- const { candidates: a } = await extract(t, [claude('Continue'), claude('Unique A1'), claude('Unique A2')]);
78
- const { candidates: b } = await extract(t, [claude(' continue ', { sessionId: 's2' }), claude('Unique B1', { sessionId: 's2' }), claude('Unique B2', { sessionId: 's2' })]);
79
- const input = [...a, ...b], sample = sampleCandidates(input, 4);
80
- assert.equal(sample.unique_count, 5); assert.equal(sample.duplicate_count, 1); assert.equal(sample.group_count, 2);
81
- assert.deepEqual(sampleCandidates([...input].reverse(), 4), sample); assert.equal(new Set(sample.selected.map(c => c.row.session_id)).size, 2);
82
- const lengthy = 'Copied historical context '.repeat(10);
83
- const c = await extract(t, [claude(lengthy)]), d = await extract(t, [claude(lengthy, { sessionId: 's2' })]);
84
- assert.equal(sampleCandidates([...c.candidates, ...d.candidates]).group_count, 1);
85
- });
86
- test('stream bounds discard oversized lines then recover next JSON record', async t => {
87
- const dir = await temp(t), path = join(dir, 'big.jsonl'); await writeFile(path, 'x'.repeat(200000) + '\n' + JSON.stringify({ ok: true }) + '\n');
88
- const stats = {}, output = []; for await (const item of records(path, stats, { maxLineBytes: 100 })) output.push(item);
89
- assert.equal(stats.oversize_line, 1); assert.deepEqual(output, [{ value: { ok: true }, line: 2 }]);
90
- });
91
- test('discovery excludes non-Kenaz Claude and nested subagents; summary only dry output', async t => {
92
- const dir = await temp(t), claudeRoot = join(dir, 'claude'), codexRoot = join(dir, 'codex');
93
- for (const path of [join(claudeRoot, 'C-KenazAI'), join(claudeRoot, 'C-Other'), join(claudeRoot, 'C-KenazAI', 'subagents'), codexRoot]) await mkdir(path, { recursive: true });
94
- await writeFile(join(claudeRoot, 'C-KenazAI', 's.jsonl'), JSON.stringify(claude('Kept real user text')));
95
- await writeFile(join(claudeRoot, 'C-KenazAI', 'agent-1.jsonl'), JSON.stringify(claude('Agent')));
96
- await writeFile(join(claudeRoot, 'C-Other', 's.jsonl'), JSON.stringify(claude('Other')));
97
- await writeFile(join(claudeRoot, 'C-KenazAI', 'subagents', 'a.jsonl'), JSON.stringify(claude('Nested')));
98
- assert.equal((await discover({ claudeRoot, codexRoot })).length, 1);
99
- const result = await inventory({ claudeRoot, codexRoot, roots, target: 500 }); assert.equal(result.summary.shortfall, 499);
100
- const report = await main(['--claude-root', claudeRoot, '--codex-root', codexRoot]); assert.equal(report.written, false); assert.equal(JSON.stringify(report).includes('Kept real'), false);
101
- await assert.rejects(main(['--target', 'NaN']), /invalid_target/);
102
- });
@@ -1,146 +0,0 @@
1
- import test from 'node:test';
2
- import assert from 'node:assert/strict';
3
- import { createServer } from 'node:http';
4
- import { once } from 'node:events';
5
- import { spawnSync } from 'node:child_process';
6
- import { template, main } from '../cli.mjs';
7
- import { readJsonl, validateDataset, validatePrediction, stateHash, inputState } from '../schema.mjs';
8
- import { MODEL, RUBRIC, prediction, rules, replayProvider, liveProvider, buildRequest, parseAnswers } from '../providers.mjs';
9
- import { report } from '../metrics.mjs';
10
-
11
- const fixture = new URL('../fixtures/synthetic.jsonl', import.meta.url);
12
- const rows = validateDataset(await readJsonl(fixture));
13
- const clone = x => structuredClone(x);
14
- const row = () => template();
15
- function correctionResponse(noul = 0.9) { return { model: MODEL, answers: { correction: { type: 'noul', noul } }, usage: { input_tokens: 30, output_tokens: 2 } }; }
16
- async function server(t, handler) {
17
- const http = createServer(handler); http.listen(0, '127.0.0.1'); await once(http, 'listening');
18
- t.after(() => { http.closeAllConnections(); http.close(); });
19
- return `http://127.0.0.1:${http.address().port}/v1/systemone`;
20
- }
21
- const live = (endpoint, extra = {}) => liveProvider({ apiKey: 'test-only-secret', endpoint, allowLoopbackForTests: true, timeoutMs: 2000, ...extra });
22
-
23
- test('varied synthetic fixtures are strict, immutable and never promotion eligible', async () => {
24
- const before = JSON.stringify(rows);
25
- assert.equal(rows.length, 11);
26
- const result = report(rows, rows.map(rules), { provider: 'rules' });
27
- assert.equal(result.promotion_eligible, false);
28
- assert.equal(result.provenance.annotation.agent_proposed, rows.length);
29
- assert.equal(result.metrics.relevance.zero_relevance_queries_excluded, 1);
30
- assert.equal(JSON.stringify(rows), before);
31
- assert.equal(JSON.stringify(result).includes(rows[0].state.message), false);
32
- assert.equal((await main(['validate', '--dataset', fixture.pathname.replace(/^\/([A-Z]:)/i, '$1')])).valid, true);
33
- });
34
- test('schema rejects unknown fields, invalid labels, duplicates and dishonest review metadata', () => {
35
- for (const mutate of [r => r.extra = true, r => r.labels.correction = 1, r => r.provenance.annotation = 'human_verified', r => r.state.message = '', r => r.event_seq = -1]) {
36
- const r = row(); mutate(r); assert.throws(() => validateDataset([r]));
37
- }
38
- const valid = row(); valid.provenance = { source: 'real', annotation: 'human_verified', reviewer: 'reviewer-a', reviewed_at: '2026-09-20T00:00:00Z' };
39
- assert.doesNotThrow(() => validateDataset([valid]));
40
- assert.throws(() => validateDataset([row(), row()]));
41
- });
42
- test('group, session and exact-content split leakage rejected', () => {
43
- for (const kind of ['group', 'session', 'content']) {
44
- const a = row(), b = row(); b.id = 'other'; b.event_id = 'other'; b.split = 'held_out';
45
- if (kind !== 'session') b.session_id = 'other';
46
- if (kind !== 'group') b.group_id = 'other';
47
- if (kind !== 'content') b.state.message = 'Different message';
48
- assert.throws(() => validateDataset([a, b]), /leakage/);
49
- }
50
- });
51
- test('model input and hash exclude ground truth and provenance', () => {
52
- const r = clone(rows.find(r => r.purpose === 'relevance')), hash = stateHash(r);
53
- r.candidates[0].grade = 0; r.provenance.reviewer = 'changed'; r.split = 'held_out';
54
- assert.equal(stateHash(r), hash);
55
- const input = JSON.stringify(inputState(r));
56
- for (const forbidden of ['grade', 'provenance', 'reviewer', 'split', 'labels']) assert.equal(input.includes(`"${forbidden}"`), false);
57
- r.state.message += ' revised'; assert.notEqual(stateHash(r), hash);
58
- });
59
- test('replay rejects wrong project/session/task, stale revision/hash, unknown IDs and aliases', () => {
60
- const r = row(), p = prediction(r, 'ok', 0.8);
61
- for (const field of ['project_id', 'session_id', 'task_id', 'event_id', 'task_revision', 'state_hash', 'model', 'question_set_version']) {
62
- const bad = clone(p); bad[field] = 'wrong'; assert.throws(() => replayProvider([r], [bad]));
63
- }
64
- assert.throws(() => replayProvider([r], []));
65
- assert.throws(() => replayProvider([r], [p, p]));
66
- assert.equal(replayProvider([r], [p])(r), p);
67
- });
68
- test('correction metrics include failed positives, preserve unanswered Brier denominator', () => {
69
- const data = [true, true, false, false].map((label, i) => ({ ...row(), id: `m${i}`, labels: { correction: label } }));
70
- const preds = [prediction(data[0], 'ok', 0.8), prediction(data[1], 'timeout'), prediction(data[2], 'ok', 0.6), prediction(data[3], 'ok', 0.1)];
71
- const result = report(data, preds, { provider: 'replay' }), m = result.metrics.correction;
72
- assert.deepEqual(m.confusion, { tp: 1, fp: 1, tn: 1, fn: 0 });
73
- assert.equal(m.coverage, 0.75); assert.equal(m.recall_including_abstentions, 0.5); assert.equal(m.recall_answered_only, 1);
74
- assert.equal(m.precision, 0.5); assert.equal(m.accuracy_including_abstentions, 0.5);
75
- assert.ok(Math.abs(m.brier_answered_only - 0.41 / 3) < 1e-12); assert.equal(m.brier_count, 3);
76
- const empty = report([data[1]], [prediction(data[1], 'abstain')], { provider: 'replay' }).metrics.correction;
77
- assert.equal(empty.precision, null); assert.equal(empty.brier_answered_only, null); assert.equal(empty.recall_including_abstentions, 0);
78
- });
79
- test('ranking uses full ideal, tracks partial scores and handles zero relevance', () => {
80
- const r = clone(rows.find(r => r.purpose === 'relevance'));
81
- const partial = prediction(r, 'ok', { [r.candidates[1].id]: 3 });
82
- const m = report([r], [partial], { provider: 'replay', k: 1 }).metrics.relevance;
83
- assert.equal(m.ndcg_at_k, 1 / 7); assert.equal(m.recall_at_k, 0.5); assert.equal(m.query_coverage, 0); assert.equal(m.candidate_coverage, 0.25); assert.equal(m.ndcg_complete_queries_only, null);
84
- const failed = report([r], [prediction(r, 'timeout')], { provider: 'replay' }).metrics.relevance;
85
- assert.equal(failed.ndcg_at_k, 0); assert.equal(failed.recall_at_k, 0);
86
- const zero = rows.at(-1), z = report([zero], [rules(zero)], { provider: 'rules' }).metrics.relevance;
87
- assert.equal(z.ndcg_at_k, null); assert.equal(z.zero_relevance_queries_excluded, 1);
88
- partial.scores[0].id = 'wrong'; assert.throws(() => validatePrediction(r, partial));
89
- });
90
- test('missing/blank key and unsafe URL rejected before any network', () => {
91
- let calls = 0; const fetchImpl = () => { calls++; throw new Error('unexpected'); };
92
- for (const apiKey of ['', ' ', '\r\n']) assert.throws(() => liveProvider({ apiKey, fetchImpl }), /api_key/);
93
- for (const endpoint of ['http://evil.example', 'https://api.typesafe.ai.evil.example/v1/systemone', 'https://api.typesafe.ai/v1/systemone?key=x', 'http://localhost:1234']) assert.throws(() => liveProvider({ apiKey: 'fake', endpoint, fetchImpl }), /unsafe_endpoint/);
94
- assert.equal(calls, 0);
95
- const child = spawnSync(process.execPath, ['dev/jev-eval/cli.mjs', 'evaluate', '--dataset', 'dev/jev-eval/fixtures/synthetic.jsonl', '--provider', 'live'], { env: { ...process.env, TYPESAFE_API_KEY: '' }, encoding: 'utf8' });
96
- assert.equal(child.status, 1); assert.deepEqual(JSON.parse(child.stderr), { error: 'missing_or_invalid_api_key' });
97
- });
98
- test('successful HTTP batches by row and tracks usage without gold leakage', async t => {
99
- const endpoint = await server(t, async (req, res) => {
100
- const parts = []; for await (const chunk of req) parts.push(chunk);
101
- const request = JSON.parse(Buffer.concat(parts));
102
- assert.equal(request.model, MODEL); assert.equal(request.state.labels, undefined); assert.equal(req.headers.authorization, 'Bearer test-only-secret');
103
- res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify(correctionResponse()));
104
- });
105
- const p = await live(endpoint)(row()); assert.equal(p.status, 'ok'); assert.equal(p.correction_probability, 0.9); assert.equal(p.usage.input_tokens, 30); validatePrediction(row(), p);
106
- });
107
- test('HTTP error statuses abstain without leaking raw provider errors', async t => {
108
- for (const status of [401, 422, 429, 529]) {
109
- const endpoint = await server(t, (req, res) => { res.writeHead(status); res.end('secret-body test-only-secret'); });
110
- const p = await live(endpoint)(row()); assert.equal(p.status, 'unavailable'); assert.equal(p.http_status, status); assert.equal(p.correction_probability, null); assert.equal(JSON.stringify(p).includes('secret'), false);
111
- }
112
- });
113
- test('redirect rejected without contacting target', async t => {
114
- let targetCalls = 0;
115
- const target = await server(t, (req, res) => { targetCalls++; res.end('{}'); });
116
- const endpoint = await server(t, (req, res) => { res.writeHead(302, { Location: target }); res.end(); });
117
- const p = await live(endpoint)(row()); assert.equal(p.status, 'unavailable'); assert.equal(targetCalls, 0);
118
- });
119
- test('timeout remains active across response body and also covers stalled transport', async t => {
120
- const endpoint = await server(t, (req, res) => { res.writeHead(200, { 'Content-Type': 'application/json' }); res.flushHeaders(); res.write('{'); });
121
- const start = Date.now(), p = await live(endpoint, { timeoutMs: 80 })(row());
122
- assert.equal(p.status, 'timeout'); assert.ok(Date.now() - start < 3000);
123
- const stalled = await liveProvider({ apiKey: 'fake', timeoutMs: 20, fetchImpl: () => new Promise(() => {}) })(row());
124
- assert.equal(stalled.status, 'timeout');
125
- });
126
- test('invalid JSON, oversized response and malformed answers fail closed', async t => {
127
- const invalids = ['{', 'x'.repeat(65537), JSON.stringify(correctionResponse(1.1)), JSON.stringify({ ...correctionResponse(), answers: { wrong: { type: 'noul', noul: 0.9 } } }), JSON.stringify({ ...correctionResponse(), usage: null })];
128
- for (const body of invalids) {
129
- const endpoint = await server(t, (req, res) => res.end(body));
130
- const p = await live(endpoint)(row()); assert.equal(p.status, 'invalid'); assert.equal(p.correction_probability, null);
131
- }
132
- });
133
- test('score answers enforce distributions, legends, bounds, confidence and exact IDs', () => {
134
- const r = rows.find(r => r.purpose === 'relevance'), request = buildRequest(r);
135
- const answer = { type: 'score', score: 2, legend: Object.fromEntries(RUBRIC.map((v, i) => [i, v])), probabilities: { 0: 0, 1: 0, 2: 1, 3: 0 }, confidence: 1 };
136
- const body = { model: MODEL, answers: Object.fromEntries(Object.keys(request.questions).map(k => [k, clone(answer)])), usage: { input_tokens: 100, output_tokens: 8 } };
137
- assert.equal(Object.keys(parseAnswers(r, body, request)).length, r.candidates.length);
138
- for (const mutate of [a => a.score = NaN, a => a.probabilities[2] = 0.3, a => a.legend[0] = 'wrong', a => a.confidence = 2, a => a.probabilities[4] = 0, a => a.type = 'noul']) {
139
- const bad = clone(body); mutate(bad.answers.candidate_0); assert.throws(() => parseAnswers(r, bad, request));
140
- }
141
- });
142
- test('CLI defaults offline, rejects ambiguous options, and preflight prints no key', async () => {
143
- assert.equal((await main(['preflight'])).network_attempted, false);
144
- assert.equal((await main(['template'])).schema_version, 1);
145
- for (const args of [['evaluate', '--endpoint', 'http://evil'], ['evaluate', '--dataset', 'a', '--dataset', 'b'], ['preflight', '--provider', 'live']]) await assert.rejects(main(args));
146
- });
@@ -1,71 +0,0 @@
1
- import test from 'node:test';
2
- import assert from 'node:assert/strict';
3
- import { readFile } from 'node:fs/promises';
4
- import { createHash } from 'node:crypto';
5
- import { resolve } from 'node:path';
6
- import { readJsonl } from '../schema.mjs';
7
- import { runBaseline, strictAnswers, safeInvocation, nativeTransport, main } from '../muninn-baseline.mjs';
8
-
9
- const source = await readFile(new URL('../../../.formation/tools/muninn.js', import.meta.url), 'utf8');
10
- const rows = await readJsonl(new URL('../fixtures/synthetic.jsonl', import.meta.url));
11
- const corrections = rows.filter(r => r.purpose === 'correction');
12
- const answers = () => corrections.map((r, idx) => ({ idx, translated: `Synthetic translation ${idx}`, labels: r.labels.correction ? ['correction'] : [] }));
13
- const response = items => ({ status: 0, stdout: JSON.stringify({ result: JSON.stringify(items), modelUsage: { 'claude-haiku-test': { inputTokens: 20 } } }) });
14
-
15
- test('offline default captures actual source prompt/parser without model quality claim', async () => {
16
- const result = await main([]);
17
- assert.equal(result.live, false); assert.equal(result.promotion_eligible, false); assert.equal(result.status, 'ok');
18
- assert.equal(result.batch_count, 8); assert.equal(result.translation_present, 8); assert.equal(result.correction_confusion, null);
19
- assert.equal(result.source_sha256, createHash('sha256').update(source).digest('hex'));
20
- assert.equal(result.source_requested_permission_bypass, true); assert.equal(result.actual_permission_bypass, false);
21
- });
22
- test('isolated source passes exact indexed messages, single transport and stable confusion', () => {
23
- let calls = 0; const before = JSON.stringify(rows);
24
- const result = runBaseline(rows, { source, live: true, transport: input => {
25
- calls++; assert.ok(input.startsWith('For each numbered message, output a JSON array'));
26
- assert.ok(input.includes('length_too_short')); assert.ok(!input.includes('Development startup also fails'));
27
- corrections.forEach((r, idx) => assert.ok(input.includes(`[${idx}] ${r.state.message.replace(/\r?\n/g, ' ')}`)));
28
- return response(answers());
29
- } });
30
- assert.equal(calls, 1); assert.equal(result.status, 'ok'); assert.equal(JSON.stringify(rows), before);
31
- assert.deepEqual(result.correction_confusion, { tp: 4, fp: 0, tn: 4, fn: 0, precision: 1, recall: 1 });
32
- assert.deepEqual(result.observed_model_metadata, ['claude-haiku-test']);
33
- assert.equal(JSON.stringify(result).includes(corrections[0].state.message), false);
34
- });
35
- test('strict raw checking rejects identities and labels before permissive source filters them', () => {
36
- const changes = [a => a.pop(), a => a[1].idx = a[0].idx, a => a.reverse(), a => a[0].idx = 0.5, a => a[0].translated = ' ', a => a[0].labels = ['invented'], a => a[0].labels = ['correction', 'correction'], a => a[0].extra = true];
37
- for (const change of changes) {
38
- const items = answers(); change(items); assert.throws(() => strictAnswers(JSON.stringify(items), corrections.length));
39
- const result = runBaseline(rows, { source, live: true, transport: () => response(items) });
40
- assert.notEqual(result.status, 'ok'); assert.equal(result.correction_confusion, null); assert.equal(result.translation_present, 0);
41
- }
42
- });
43
- test('failures timeouts malformed envelopes and oversize output remain sanitized failures', () => {
44
- for (const transport of [() => ({ status: 1, stdout: 'private-error' }), () => ({ status: null, error: { code: 'ETIMEDOUT' } }), () => ({ status: 0, stdout: '{' }), () => ({ status: 0, stdout: 'x'.repeat(1048577) }), () => { throw 'private-error'; }, () => ({ status: 0, stdout: JSON.stringify({ is_error: true, result: 'private-error' }) })]) {
45
- const result = runBaseline(rows, { source, live: true, transport });
46
- assert.notEqual(result.status, 'ok'); assert.equal(result.correction_confusion, null); assert.equal(JSON.stringify(result).includes('private-error'), false);
47
- }
48
- });
49
- test('real data rejected before transport including irrelevant purpose rows', () => {
50
- let calls = 0; const real = structuredClone(rows); real.at(-1).provenance.source = 'real';
51
- assert.throws(() => runBaseline(real, { source, live: true, transport: () => { calls++; } }), /synthetic_only/); assert.equal(calls, 0);
52
- });
53
- test('VM denies filesystem/network and unrelated module calls; empty environment', () => {
54
- for (const expression of ["require('fs').readFileSync('x')", "require('http').request('x')", "require('os').homedir()", "require('net')", "require('./log-reader').findTaskLog()"])
55
- assert.throws(() => runBaseline(rows, { source: source + '\n' + expression }), /blocked_vm/);
56
- const checked = source + '\nif (Object.keys(process.env).length || require.main === module) throw new Error("unexpected_environment");';
57
- assert.equal(runBaseline(rows, { source: checked }).status, 'ok');
58
- });
59
- test('safe subprocess uses explicit executable argv no shell and bounded output/time', () => {
60
- const exe = resolve('test-claude.exe'), invocation = safeInvocation(exe);
61
- for (const flag of ['--safe-mode', '--tools', '--disable-slash-commands', '--no-session-persistence']) assert.ok(invocation.args.includes(flag));
62
- assert.equal(invocation.args[invocation.args.indexOf('--tools') + 1], '');
63
- assert.equal(invocation.args.includes('--dangerously-skip-permissions'), false);
64
- let calls = 0;
65
- nativeTransport(exe, '/isolated', (command, args, options) => {
66
- calls++; assert.equal(command, exe); assert.deepEqual(args, invocation.args); assert.equal(options.shell, false);
67
- assert.equal(options.timeout, 30000); assert.equal(options.maxBuffer, 1048576); assert.equal(options.windowsHide, true);
68
- assert.equal(Object.hasOwn(options.env, 'TYPESAFE_API_KEY'), false); return { status: 0, stdout: '{}' };
69
- })('synthetic prompt'); assert.equal(calls, 1);
70
- for (const bad of ['claude', resolve('claude.cmd'), resolve('claude.bat')]) assert.throws(() => safeInvocation(bad), /invalid_claude_cli/);
71
- });