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.
- package/core/.claude/hooks/_user-scope.js +1 -1
- package/core/.claude/hooks/core-resolve.js +1 -1
- package/core/.claude/hooks/worktree-create.js +11 -29
- package/core/.claude/hooks/worktree-remove.js +12 -38
- package/core/.collaboration/core/reconcile.js +16 -1
- package/core/.collaboration/core/task-2467-lifecycle.test.js +63 -0
- package/core/.collaboration/core/task-api.js +37 -7
- package/core/.formation/bifrost/launch.js +1 -1
- package/core/.formation/tools/dispatch-detail/worktree-subagent-mode.md +6 -1
- package/core/.formation/tools/kenaz-stats.js +1 -1
- package/core/.formation/tools/post-complete/git-merge.js +1 -1
- package/core/.formation/tools/prompt.js +1 -1
- package/core/.formation/tools/utils.js +5 -5
- package/core/.formation/tools/worktree-reclaim.js +73 -2
- package/core/.formation/tools/worktree-reclaim.test.js +113 -0
- package/core/.kenaz/specialist/ansuz_rules.yaml +7 -51
- package/core/.kenaz/specialist/ansuz_session_handoff.schema.json +2 -6
- package/core/.rule/general/project-self-containment.yaml +2 -2
- package/core/.specialist/Amelia/README.md +1 -1
- package/core/.specialist/Amelia/rule.yaml +1 -1
- package/core/.specialist/Ansuz/RULES.md +6 -2
- package/core/.specialist/Ansuz/concepts/commitment_layer.yaml +1 -1
- package/core/.specialist/Ansuz/concepts/evolvable_guardrails.yaml +1 -1
- package/core/.specialist/Ansuz/knowledge.yaml +1 -3
- package/core/.specialist/tools/__tests__/task-2409-lessons.test.js +10 -0
- package/core/.specialist/tools/__tests__/task-2427-harvest.test.js +25 -0
- package/core/.specialist/tools/ansuz-boot-fast.js +1 -1
- package/core/.specialist/tools/failure-detector.js +4 -4
- package/core/.specialist/tools/handoff-doc.js +1 -1
- package/core/.specialist/tools/lessons.js +2 -2
- package/core/CLAUDE.md +5 -5
- package/core/KENAZ_CORE_VERSION +1 -1
- package/core/dashboard/scripts/install-kenaz-cli.js +56 -30
- package/core/dev/scripts/check-file-size.js +1 -1
- package/core/dev/scripts/ci-feedback.js +1 -1
- package/core/dev/scripts/gc-agent-worktrees.js +13 -12
- package/core/dev/scripts/kenaz-session.js +3 -3
- package/core/dev/scripts/peer-identity-e2e.js +6 -4
- package/core/dev/scripts/run-rust-tests.js +2 -2
- package/core/dev/scripts/skill-routing-replay.js +3 -3
- package/core/dev/scripts/task1961/selftest.js +2 -2
- package/core/dev/scripts/windows-hide-guard.test.js +112 -0
- package/core/plugins/kenaz/guidance.md +1 -0
- package/core/plugins/kenaz/hooks/core-resolve.js +1 -1
- package/core/plugins/kenaz/hooks/hooks.json +9 -0
- package/core/plugins/kenaz/hooks/kenaz-hook.js +58 -4
- package/core/plugins/kenaz/hooks/worktree-guard.js +121 -0
- package/core/plugins/kenaz/hooks/worktree-guard.test.js +75 -0
- package/core/plugins/kenaz/scripts/kenaz.test.js +72 -5
- package/core/plugins/kenaz-peer/hooks/register.test.ts +14 -2
- package/core/plugins/kenaz-peer/hooks/register.ts +6 -1
- package/lib/cli.js +9 -5
- package/package.json +6 -6
- package/vendor/install-kenaz-cli.js +56 -30
- package/core/.kenaz/designs/METAPLASTICITY_CONFIDENCE_DESIGN.md +0 -537
- package/core/.kenaz/designs/REFLEX_INITIATOR_DESIGN.md +0 -501
- package/core/.kenaz/designs/TASK_1385_handoff_mcp_design.md +0 -426
- package/core/.kenaz/designs/TASK_932_hippocampus_consolidation.md +0 -103
- package/core/.kenaz/designs/TASK_934_efe_signal_engine.md +0 -97
- package/core/.kenaz/designs/TASK_935_self_evolution_framework.md +0 -154
- package/core/.kenaz/designs/VISION_cognitive_architecture_roadmap.md +0 -159
- package/core/.kenaz/designs/metaplasticity_simulation_results.json +0 -696
- package/core/.kenaz/main-memory/README.md +0 -230
- package/core/.kenaz/main-memory/kenaz/cortex/001_cortex_overview.md +0 -168
- package/core/.kenaz/main-memory/kenaz/cortex/001_rag_engine_overview.md +0 -30
- package/core/.kenaz/main-memory/kenaz/memory-system/001_three_tier_architecture.md +0 -361
- package/core/.kenaz/main-memory/kenaz/pipeline/001_task_execution_flow.md +0 -117
- package/core/.kenaz/main-memory/kenaz/pipeline/001_task_granularity.md +0 -154
- package/core/.kenaz/main-memory/kenaz/pipeline/002_team_priority.md +0 -51
- package/core/.kenaz/main-memory/kenaz/pipeline/003_feature_id_system.md +0 -46
- package/core/.kenaz/main-memory/kenaz/rules/001_gen_007_self_containment.md +0 -108
- package/core/.kenaz/main-memory/kenaz/rules/001_rule_priority_system.md +0 -121
- package/core/.kenaz/main-memory/kenaz/rules/002_agt_006_pre_check.md +0 -0
- package/core/.kenaz/main-memory/kenaz/rules/003_ppl_002_task_archival.md +0 -48
- package/core/.kenaz/main-memory/kenaz/system/001_dual_track_task_system.md +0 -197
- package/core/.kenaz/main-memory/knowledge/patterns/001_json_bom_issue.md +0 -78
- package/core/.kenaz/main-memory/knowledge/patterns/001_leader_worker_pattern.md +0 -0
- package/core/.kenaz/main-memory/knowledge/patterns/002_scope_path_conflict.md +0 -115
- package/core/.kenaz/main-memory/knowledge/patterns/002_task_dependency_resolution.md +0 -223
- package/core/.kenaz/main-memory/knowledge/patterns/003_question_protocol.md +0 -242
- package/core/.kenaz/main-memory/knowledge/patterns/004_user_insight_value.md +0 -111
- package/core/.kenaz/main-memory/knowledge/patterns/005_file_lock_pattern.md +0 -274
- package/core/.kenaz/main-memory/knowledge/references/001_ppl_rules.md +0 -28
- package/core/.kenaz/main-memory/knowledge/solutions/001_json_bom_issue.md +0 -137
- package/core/.kenaz/main-memory/knowledge/solutions/001_team_invocation.md +0 -0
- package/core/.kenaz/main-memory/knowledge/solutions/002_passive_monitoring.md +0 -0
- package/core/.kenaz/main-memory/knowledge/solutions/003_windows_file_race_condition.md +0 -239
- package/core/.kenaz/main-memory/registry.json +0 -326
- package/core/.kenaz/main-memory/version.yaml +0 -58
- package/core/.kenaz/specialist/memory_guard_fired.json +0 -1
- package/core/.kenaz/specialist/memory_guard_trigger_cache.json +0 -1
- package/core/.kenaz/specialist/memory_source_priority.yaml +0 -260
- package/core/.kenaz/specialist/prompt_1775.txt +0 -317
- package/core/.kenaz/specialist/prompt_1776.txt +0 -326
- package/core/.kenaz/specialist/prompt_1791.txt +0 -320
- package/core/.kenaz/specialist/prompt_1792.txt +0 -320
- package/core/.kenaz/specialist/prompt_1795.txt +0 -281
- package/core/.kenaz/specialist/prompt_1813.txt +0 -332
- package/core/.kenaz/specialist/prompt_1814.txt +0 -401
- package/core/.kenaz/specialist/prompt_1815.txt +0 -394
- package/core/.kenaz/specialist/prompt_1816.txt +0 -437
- package/core/.kenaz/specialist/prompt_1818.txt +0 -361
- package/core/.kenaz/specialist/prompt_1819.txt +0 -421
- package/core/.kenaz/specialist/prompt_1821.txt +0 -345
- package/core/.kenaz/specialist/prompt_1822.txt +0 -313
- package/core/.kenaz/specialist/prompt_1824.txt +0 -348
- package/core/.kenaz/specialist/prompt_1826.txt +0 -388
- package/core/.kenaz/specialist/rune_efe_salience_gap.md +0 -21
- package/core/.kenaz/specialist/task1825_update.json +0 -43
- package/core/.kenaz/specialist/taskgen/consolidation_i.json +0 -38
- package/core/.kenaz/specialist/taskgen/csharp_a.json +0 -44
- package/core/.kenaz/specialist/taskgen/csharp_b.json +0 -40
- package/core/.kenaz/specialist/taskgen/embedding_e.json +0 -34
- package/core/.kenaz/specialist/taskgen/hygiene_fg.json +0 -39
- package/core/.kenaz/specialist/taskgen/pathology_h.json +0 -36
- package/core/.kenaz/specialist/taskgen/unity_noise_d.json +0 -38
- package/core/.kenaz/specialist/taskgen/visibility_c.json +0 -38
- package/core/.specialist/Ansuz/decisions/ADR-requirement-graph-layer.md +0 -390
- package/core/.specialist/Ansuz/self_model_seed.backup.json +0 -100
- package/core/.specialist/ansuz_session_handoff.json +0 -96
- package/core/dev/ALAYA_FIELD_FEEDBACK_DESIGN.md +0 -126
- package/core/dev/ANSUZ_SCAFFOLD_DIET_2026-09-20.md +0 -231
- package/core/dev/ANSUZ_STARTUP_INJECTION_REVIEW.md +0 -355
- package/core/dev/ANSUZ_WORKFLOW_MODERNIZATION.md +0 -143
- package/core/dev/CORTEX_META_GRAPH_ASSESSMENT.md +0 -99
- package/core/dev/FREYA_DOWNSTREAM_BUGS_2026-09-19.md +0 -44
- package/core/dev/GLOBAL_MEMORY_IDENTITY_CONSOLIDATION.md +0 -263
- package/core/dev/GUARD_EFFECTIVENESS_DESIGN.md +0 -180
- package/core/dev/HEALTH_GATE_VARIANCE_ASSESSMENT.md +0 -271
- package/core/dev/HOOK_DIET_2026-09-21.md +0 -126
- package/core/dev/JEV_INTEGRATION_PLAN.md +0 -189
- package/core/dev/KENAZ_AGENT_CONNECT_v1_SPEC.md +0 -139
- package/core/dev/MOBILE_DESIGN_SPEC.md +0 -569
- package/core/dev/MULTI_ANSUZ_SPEC.md +0 -136
- package/core/dev/MUNINN_RETIREMENT.md +0 -115
- package/core/dev/PHASE3_ATTRIBUTION_POPULATION_DIAGNOSIS.md +0 -211
- package/core/dev/PHASE3_P3-2B_TASKLEVEL_PROBE.md +0 -83
- package/core/dev/PHASE3_P3-2_POPULATION_DISJOINTNESS.md +0 -83
- package/core/dev/PHASE3_P3-2_REMEASURE_REPORT.md +0 -231
- package/core/dev/PREDICTION_GROUNDING_DESIGN.md +0 -376
- package/core/dev/PRODUCT_SPEC.md +0 -317
- package/core/dev/PROJECT_REGISTRY_DUPLICATE_ASSESSMENT.md +0 -86
- package/core/dev/STARTUP_TIMELINE_TASK_1995.md +0 -181
- package/core/dev/SYNAPSE_WORKER_PER_PROJECT.md +0 -881
- package/core/dev/TASK_1680_P3-3_DISPATCH_SPEC.md +0 -96
- package/core/dev/TASK_1684_CALIBRATION_IMPACT_ANALYSIS.md +0 -170
- package/core/dev/TASK_1684_FORK_A_GOODHART_DESIGN.md +0 -171
- package/core/dev/TASK_1684_P3_2_REMEASURE_VALIDATION.md +0 -262
- package/core/dev/TASK_1903_SIGNAL_AUC_MEASUREMENT.md +0 -207
- package/core/dev/TASK_1904_BRANCH_INTEGRITY_AUDIT.md +0 -146
- package/core/dev/ansuz-eval/README.md +0 -38
- package/core/dev/ansuz-eval/build-fixtures.js +0 -87
- package/core/dev/ansuz-eval/grade.js +0 -96
- package/core/dev/ansuz-eval/grader.test.js +0 -117
- package/core/dev/ansuz-eval/tasks.md +0 -32
- package/core/dev/archive/ansuz/BOOT_FULL.md +0 -141
- package/core/dev/archive/ansuz/agents/ansuz-boot.md +0 -176
- package/core/dev/archive/ansuz/designs/alaya-passive-surfacing.md +0 -84
- package/core/dev/archive/ansuz/designs/cc_memory_indexing.md +0 -307
- package/core/dev/archive/ansuz/designs/check_guard.md +0 -322
- package/core/dev/archive/ansuz/designs/consequence_loop.md +0 -227
- package/core/dev/archive/ansuz/designs/mcp_kuzudb_lock_architecture.md +0 -312
- package/core/dev/archive/ansuz/designs/phase0_git_enrichment.md +0 -278
- package/core/dev/archive/ansuz/designs/refactor_mcp_tools_synapse.md +0 -490
- package/core/dev/archive/ansuz/designs/semantic_markdown_extraction.md +0 -167
- package/core/dev/archive/ansuz/designs/task_1372_prompt_injects_into.md +0 -193
- package/core/dev/archive/ansuz/designs/thought_stack.md +0 -286
- package/core/dev/archive/ansuz/investigations/reachability_unified_api_2026-04-11.md +0 -330
- package/core/dev/archive/ansuz/investigations/synapse_orphans_indexing_bug_2026-04-11.md +0 -352
- package/core/dev/archive/ansuz/investigations/synapse_orphans_reindex_verification_2026-04-11.md +0 -48
- package/core/dev/archive/ansuz/investigations/synapse_orphans_verification_2026-04-11.md +0 -170
- package/core/dev/archive/ansuz/legacy/kernel.yaml +0 -399
- package/core/dev/archive/ansuz/legacy/phases/phase_0.yaml +0 -418
- package/core/dev/archive/ansuz/legacy/phases/phase_1.yaml +0 -376
- package/core/dev/archive/ansuz/legacy/phases/phase_10.yaml +0 -35
- package/core/dev/archive/ansuz/legacy/phases/phase_11.yaml +0 -582
- package/core/dev/archive/ansuz/legacy/phases/phase_2.yaml +0 -94
- package/core/dev/archive/ansuz/legacy/phases/phase_3.yaml +0 -274
- package/core/dev/archive/ansuz/legacy/phases/phase_4.yaml +0 -67
- package/core/dev/archive/ansuz/legacy/phases/phase_5.yaml +0 -32
- package/core/dev/archive/ansuz/legacy/phases/phase_6.yaml +0 -91
- package/core/dev/archive/ansuz/legacy/phases/phase_7.yaml +0 -58
- package/core/dev/archive/ansuz/legacy/phases/phase_8.yaml +0 -146
- package/core/dev/archive/ansuz/legacy/phases/phase_9.yaml +0 -424
- package/core/dev/archive/ansuz/specs/INDEX_bifrost_hook_parity.yaml +0 -92
- package/core/dev/archive/ansuz/specs/active-inference-formation.yaml +0 -453
- package/core/dev/archive/ansuz/specs/brief_TASK_1228_userpromptsubmit.yaml +0 -191
- package/core/dev/archive/ansuz/specs/brief_TASK_1229_pretooluse_posttooluse.yaml +0 -250
- package/core/dev/archive/ansuz/specs/brief_TASK_1230_sessionstart_stop.yaml +0 -301
- package/core/dev/archive/ansuz/specs/brief_TASK_1231_verification.yaml +0 -272
- package/core/dev/archive/skills/feature_agent/SKILL.md +0 -289
- package/core/dev/design/PHASE4_DESIGN.md +0 -559
- package/core/dev/design/dashboard_docs_integration_PLAN.md +0 -388
- package/core/dev/design/matrix_format_ABBREVIATIONS.md +0 -655
- package/core/dev/design/matrix_format_DESIGN_SPEC.md +0 -601
- package/core/dev/design/matrix_format_DISCUSSION_SUMMARY.md +0 -484
- package/core/dev/design/matrix_format_EXAMPLE_memory.matrix +0 -13
- package/core/dev/design/matrix_format_EXAMPLE_project_status.matrix +0 -9
- package/core/dev/design/matrix_format_EXAMPLE_tasks.matrix +0 -14
- package/core/dev/design/matrix_format_SYNTAX_BNF.md +0 -754
- package/core/dev/design/matrix_format_TOKEN_COMPARISON.md +0 -484
- package/core/dev/design/matrix_v2_COGNITIVE_DESIGN.md +0 -503
- package/core/dev/design/matrix_v2_DISCUSSION_SUMMARY.md +0 -414
- package/core/dev/design/matrix_v2_EXAMPLE.matrix +0 -67
- package/core/dev/designs/EXPANDABLE_CARD_DESIGN_SPEC.md +0 -509
- package/core/dev/jev-eval/ACTIVE_CORRECTION.md +0 -52
- package/core/dev/jev-eval/ANNOTATION_GUIDE.md +0 -68
- package/core/dev/jev-eval/BASELINE_COMPARISON.md +0 -45
- package/core/dev/jev-eval/CONTEXT_REVIEW.md +0 -31
- package/core/dev/jev-eval/EVALUATION_STATUS.md +0 -39
- package/core/dev/jev-eval/HISTORICAL_CORPUS.md +0 -33
- package/core/dev/jev-eval/PACKAGING_VERIFICATION.md +0 -42
- package/core/dev/jev-eval/README.md +0 -101
- package/core/dev/jev-eval/THALAMUS_RANKING.md +0 -58
- package/core/dev/jev-eval/VALIDATION_PROGRESS.md +0 -54
- package/core/dev/jev-eval/cli.mjs +0 -50
- package/core/dev/jev-eval/context.mjs +0 -183
- package/core/dev/jev-eval/corpus.mjs +0 -186
- package/core/dev/jev-eval/fixtures/conversation-review.seed.jsonl +0 -6
- package/core/dev/jev-eval/fixtures/synthetic.jsonl +0 -11
- package/core/dev/jev-eval/metrics.mjs +0 -67
- package/core/dev/jev-eval/muninn-baseline.mjs +0 -119
- package/core/dev/jev-eval/providers.mjs +0 -95
- package/core/dev/jev-eval/reports/annotation-pilot-2026-09-20.json +0 -32
- package/core/dev/jev-eval/reports/context-review-2026-09-20.json +0 -48
- package/core/dev/jev-eval/reports/conversation-review.pending.json +0 -151
- package/core/dev/jev-eval/reports/history-corpus-2026-09-20.json +0 -52
- package/core/dev/jev-eval/reports/length-probe-2026-09-20.json +0 -133
- package/core/dev/jev-eval/reports/live-smoke-2026-09-20.json +0 -616
- package/core/dev/jev-eval/reports/muninn-baseline-2026-09-20.json +0 -52
- package/core/dev/jev-eval/reports/resilience-2026-09-20.json +0 -520
- package/core/dev/jev-eval/reports/rules-baseline.json +0 -197
- package/core/dev/jev-eval/reports/synthetic-review.pending.json +0 -357
- package/core/dev/jev-eval/resilience.mjs +0 -71
- package/core/dev/jev-eval/review.mjs +0 -78
- package/core/dev/jev-eval/schema.mjs +0 -87
- package/core/dev/jev-eval/test/context.test.mjs +0 -95
- package/core/dev/jev-eval/test/corpus.test.mjs +0 -102
- package/core/dev/jev-eval/test/eval.test.mjs +0 -146
- package/core/dev/jev-eval/test/muninn-baseline.test.mjs +0 -71
- package/core/dev/jev-eval/test/resilience.test.mjs +0 -72
- package/core/dev/jev-eval/test/review.test.mjs +0 -61
- package/core/dev/pipeline/PHASE3_PLANNING_SUMMARY.md +0 -338
- package/core/dev/pipeline/PROGRESS.md +0 -113
- package/core/dev/pipeline/PROGRESS_template.md +0 -860
- package/core/dev/pipeline/QA_REPORT_F008.md +0 -431
- package/core/dev/pipeline/QA_REPORT_LOCAL_CLAUDE_DIAGNOSIS.md +0 -583
- package/core/dev/pipeline/README.md +0 -210
- package/core/dev/pipeline/WORKFLOW_GUIDE.md +0 -824
- package/core/dev/pipeline/archived/TASK_015_tauri_init.yaml +0 -53
- package/core/dev/pipeline/archived/TASK_016_tauri_commands.yaml +0 -54
- package/core/dev/pipeline/archived/TASK_017_rust_pty.yaml +0 -54
- package/core/dev/pipeline/archived/TASK_018_tauri_bundle.yaml +0 -53
- package/core/dev/pipeline/archived/TASK_019_release_workflow.yaml +0 -56
- package/core/dev/pipeline/archived/TASK_020_update_ui.yaml +0 -54
- package/core/dev/pipeline/archived/TASK_021_update_notification_ui.yaml +0 -55
- package/core/dev/pipeline/archived/TASK_022_remove_node_pty.yaml +0 -65
- package/core/dev/pipeline/archived/TASK_023_api_routes_migration.yaml +0 -86
- package/core/dev/pipeline/archived/TASK_024_feature_id_system.yaml +0 -51
- package/core/dev/pipeline/archived/TASK_025_executable_acceptance.yaml +0 -66
- package/core/dev/pipeline/archived/TASK_026_spec_versioning.yaml +0 -56
- package/core/dev/pipeline/archived/TASK_027_drift_detection.yaml +0 -60
- package/core/dev/pipeline/archived/TASK_028_tauri_pty_manager.yaml +0 -60
- package/core/dev/pipeline/archived/TASK_029_tauri_pty_commands.yaml +0 -62
- package/core/dev/pipeline/archived/TASK_030_frontend_session_adapter.yaml +0 -54
- package/core/dev/pipeline/archived/TASK_031_terminal_tauri_events.yaml +0 -56
- package/core/dev/pipeline/archived/TASK_041_scheduler_data_models.yaml +0 -54
- package/core/dev/pipeline/archived/TASK_042_path_lock_manager.yaml +0 -53
- package/core/dev/pipeline/archived/TASK_043_process_manager.yaml +0 -57
- package/core/dev/pipeline/archived/TASK_044_git_integration.yaml +0 -85
- package/core/dev/pipeline/archived/TASK_045_task_queue_manager.yaml +0 -54
- package/core/dev/pipeline/archived/TASK_046_scheduler_dispatcher.yaml +0 -60
- package/core/dev/pipeline/archived/TASK_047_tauri_scheduler_commands.yaml +0 -55
- package/core/dev/pipeline/archived/TASK_048_realtime_status_push.yaml +0 -92
- package/core/dev/pipeline/archived/TASK_049_frontend_scheduler_integration.yaml +0 -58
- package/core/dev/pipeline/archived/TASK_050_error_recovery.yaml +0 -56
- package/core/dev/pipeline/archived/TASK_051_optimization_proposals_backend.yaml +0 -53
- package/core/dev/pipeline/archived/TASK_052_optimization_proposals_ui.yaml +0 -58
- package/core/dev/pipeline/archived/TASK_053_optimization_proposals_diff_view.yaml +0 -54
- package/core/dev/pipeline/archived/TASK_054_multi_project_scheduler_state.yaml +0 -76
- package/core/dev/pipeline/archived/TASK_055_scheduler_api_project_scope.yaml +0 -64
- package/core/dev/pipeline/archived/TASK_056_frontend_scheduler_project_scope.yaml +0 -62
- package/core/dev/pipeline/archived/TASK_057_scheduler_module_structure.yaml +0 -54
- package/core/dev/pipeline/archived/TASK_058_scheduler_models_extract.yaml +0 -51
- package/core/dev/pipeline/archived/TASK_059_scheduler_core_extract.yaml +0 -51
- package/core/dev/pipeline/archived/TASK_060_scheduler_commands_extract.yaml +0 -51
- package/core/dev/pipeline/archived/TASK_061_scheduler_specialized_commands.yaml +0 -53
- package/core/dev/pipeline/archived/TASK_062_process_manager_module_structure.yaml +0 -56
- package/core/dev/pipeline/archived/TASK_063_process_manager_core_extract.yaml +0 -56
- package/core/dev/pipeline/archived/TASK_064_recovery_module_structure.yaml +0 -57
- package/core/dev/pipeline/archived/TASK_065_recovery_core_extract.yaml +0 -56
- package/core/dev/pipeline/archived/TASK_066_self_enhancement_scheduler_models.yaml +0 -60
- package/core/dev/pipeline/archived/TASK_067_agents_section_quick_actions.yaml +0 -53
- package/core/dev/pipeline/archived/TASK_067_self_enhancement_scheduler_core.yaml +0 -65
- package/core/dev/pipeline/archived/TASK_068_agent_workflow_rule_enhancement.yaml +0 -46
- package/core/dev/pipeline/archived/TASK_068_self_enhancement_tauri_commands.yaml +0 -61
- package/core/dev/pipeline/archived/TASK_069_agent_wizard_responsive.yaml +0 -46
- package/core/dev/pipeline/archived/TASK_069_self_enhancement_ui.yaml +0 -62
- package/core/dev/pipeline/archived/TASK_070_preview_panel_redesign.yaml +0 -62
- package/core/dev/pipeline/archived/TASK_070_self_enhancement_integration.yaml +0 -57
- package/core/dev/pipeline/archived/TASK_071_preview_panel_qa.yaml +0 -98
- package/core/dev/pipeline/archived/TASK_071_single_agent_config.yaml +0 -57
- package/core/dev/pipeline/archived/TASK_072_preview_modal_esc_fix.yaml +0 -71
- package/core/dev/pipeline/archived/TASK_072_product_review_module.yaml +0 -57
- package/core/dev/pipeline/archived/TASK_073_agents_page_component_refactor.yaml +0 -68
- package/core/dev/pipeline/archived/TASK_073_rename_single_agent.yaml +0 -64
- package/core/dev/pipeline/archived/TASK_074_preview_mode_ui_diagnosis.yaml +0 -71
- package/core/dev/pipeline/archived/TASK_074_single_agent_ui_toggle.yaml +0 -56
- package/core/dev/pipeline/archived/TASK_075_agents_page_component_refactor.yaml +0 -69
- package/core/dev/pipeline/archived/TASK_075_single_agent_integration_test.yaml +0 -75
- package/core/dev/pipeline/archived/TASK_076_preview_mode_ui_diagnosis.yaml +0 -70
- package/core/dev/pipeline/archived/TASK_076_single_agent_continuous_mode.yaml +0 -65
- package/core/dev/pipeline/archived/TASK_077_failure_directory_structure.yaml +0 -51
- package/core/dev/pipeline/archived/TASK_077_single_agent_typescript_types.yaml +0 -59
- package/core/dev/pipeline/archived/TASK_078_fail_001_agent_no_output.yaml +0 -53
- package/core/dev/pipeline/archived/TASK_078_single_agent_ui_simplify.yaml +0 -74
- package/core/dev/pipeline/archived/TASK_079_dashboard_rwd_responsive.yaml +0 -63
- package/core/dev/pipeline/archived/TASK_079_fail_002_json_bom.yaml +0 -56
- package/core/dev/pipeline/archived/TASK_080_fail_003_queue_pollution.yaml +0 -56
- package/core/dev/pipeline/archived/TASK_080_http_server_module.yaml +0 -55
- package/core/dev/pipeline/archived/TASK_081_failure_logging_tools.yaml +0 -57
- package/core/dev/pipeline/archived/TASK_081_http_api_routes.yaml +0 -62
- package/core/dev/pipeline/archived/TASK_082_frontend_api_adapter.yaml +0 -51
- package/core/dev/pipeline/archived/TASK_082_integrate_failure_to_workflow.yaml +0 -60
- package/core/dev/pipeline/archived/TASK_083_cleanup_nextjs_api.yaml +0 -48
- package/core/dev/pipeline/archived/TASK_083_task_queue_cleanup.yaml +0 -67
- package/core/dev/pipeline/archived/TASK_084_rust_dead_code_cleanup.yaml +0 -66
- package/core/dev/pipeline/archived/TASK_084_scheduler_sync_logic_fix.yaml +0 -68
- package/core/dev/pipeline/archived/TASK_085_http_api_web_mode_fixes.yaml +0 -46
- package/core/dev/pipeline/archived/TASK_085_memory_consolidation_0204_0205.yaml +0 -98
- package/core/dev/pipeline/archived/TASK_086_collapsible_preview_panel.yaml +0 -161
- package/core/dev/pipeline/archived/TASK_086_web_mode_feature_parity.yaml +0 -62
- package/core/dev/pipeline/archived/TASK_087_manual_memory_archival.yaml +0 -163
- package/core/dev/pipeline/archived/TASK_087_mobile_http_control.yaml +0 -68
- package/core/dev/pipeline/archived/TASK_088_fail_003_to_ppl_002_rule.yaml +0 -63
- package/core/dev/pipeline/archived/TASK_088_mobile_http_qa.yaml +0 -121
- package/core/dev/pipeline/archived/TASK_089_agent_collaboration_topic.yaml +0 -60
- package/core/dev/pipeline/archived/TASK_089_web_mode_monitor_fix.yaml +0 -58
- package/core/dev/pipeline/archived/TASK_090_cli_detection_fix.yaml +0 -61
- package/core/dev/pipeline/archived/TASK_090_ui_ux_lessons_topic.yaml +0 -63
- package/core/dev/pipeline/archived/TASK_091_expandable_card_design.yaml +0 -56
- package/core/dev/pipeline/archived/TASK_091_move_agent_section_components.yaml +0 -65
- package/core/dev/pipeline/archived/TASK_092_expandable_card_component.yaml +0 -60
- package/core/dev/pipeline/archived/TASK_092_refactor_agent_create_wizard.yaml +0 -84
- package/core/dev/pipeline/archived/TASK_093_taskcard_detail_integration.yaml +0 -57
- package/core/dev/pipeline/archived/TASK_093_update_barrel_exports_test.yaml +0 -84
- package/core/dev/pipeline/archived/TASK_094_ai_agent_generation_enhancement.yaml +0 -115
- package/core/dev/pipeline/archived/TASK_094_proposalcard_detail_integration.yaml +0 -55
- package/core/dev/pipeline/archived/TASK_095_preview_fixes.yaml +0 -129
- package/core/dev/pipeline/archived/TASK_095_single_agent_task_selector.yaml +0 -60
- package/core/dev/pipeline/archived/TASK_096_agents_page_ux_improvements.yaml +0 -163
- package/core/dev/pipeline/archived/TASK_096_single_agent_status_sync.yaml +0 -60
- package/core/dev/pipeline/archived/TASK_097_local_claude_error_logging.yaml +0 -59
- package/core/dev/pipeline/archived/TASK_097_single_agent_monitor_events.yaml +0 -59
- package/core/dev/pipeline/archived/TASK_098_product_manager_team_phase2.yaml +0 -60
- package/core/dev/pipeline/archived/TASK_098_single_agent_refactor_test.yaml +0 -58
- package/core/dev/pipeline/archived/TASK_099_backend_team_creation.yaml +0 -258
- package/core/dev/pipeline/archived/TASK_100_frontend_team_creation.yaml +0 -61
- package/core/dev/pipeline/archived/TASK_101_orchestrator_system.yaml +0 -403
- package/core/dev/pipeline/archived/TASK_102_designer_sre_teams.yaml +0 -90
- package/core/dev/pipeline/archived/TASK_103_integration_testing.yaml +0 -86
- package/core/dev/pipeline/archived/TASK_128_integration_testing.yaml +0 -83
- package/core/dev/pipeline/archived/TASK_134_cortex_v2_phase3_file_watcher.yaml +0 -65
- package/core/dev/pipeline/archived/TASK_134_team_http_api.yaml +0 -96
- package/core/dev/pipeline/archived/TASK_135_cortex_v2_phase3_git_monitor.yaml +0 -63
- package/core/dev/pipeline/archived/TASK_136_cortex_v2_phase3_change_analyzer.yaml +0 -69
- package/core/dev/pipeline/archived/TASK_137_cortex_v2_phase3_cache_invalidator.yaml +0 -67
- package/core/dev/pipeline/archived/TASK_137_team_orchestrator_integration.yaml +0 -93
- package/core/dev/pipeline/archived/TASK_138_cortex_v2_phase3_distributed_cache.yaml +0 -68
- package/core/dev/pipeline/archived/TASK_138_matrix_folder_structure.yaml +0 -61
- package/core/dev/pipeline/archived/TASK_139_cortex_v2_phase3_cache_prewarming.yaml +0 -65
- package/core/dev/pipeline/archived/TASK_146_unified_documentation.yaml +0 -141
- package/core/dev/pipeline/archived/TASK_147_pipeline_execution_rules.yaml +0 -76
- package/core/dev/pipeline/archived/TASK_148_update_claude_md.yaml +0 -77
- package/core/dev/pipeline/archived/TASK_149_fix_nextjs_mdx_serialization.yaml +0 -63
- package/core/dev/pipeline/archived/TASK_149_update_team_docs.yaml +0 -77
- package/core/dev/pipeline/archived/TASK_150_pipeline_workflow_guide.yaml +0 -82
- package/core/dev/pipeline/archived/TASK_164_fix_smart_context_switch.yaml +0 -49
- package/core/dev/pipeline/archived/TASK_165_ctags_symbol_index.yaml +0 -53
- package/core/dev/pipeline/archived/TASK_166_symbol_search_mcp_tool.yaml +0 -48
- package/core/dev/pipeline/archived/TASK_167_llm_module_summary.yaml +0 -55
- package/core/dev/pipeline/archived/TASK_168_map_reduce_context.yaml +0 -51
- package/core/dev/pipeline/archived/TASK_169_v2_integration_testing.yaml +0 -52
- package/core/dev/pipeline/backups/archive_2026-02-04T22-07-22/TASK_QUEUE_backup.json +0 -95
- package/core/dev/pipeline/docs/multi-agent-coordination.md +0 -446
- package/core/dev/pipeline/docs/overview.md +0 -406
- package/core/dev/pipeline/docs/task-management.md +0 -412
- package/core/dev/pipeline/docs/workflows.md +0 -32
- package/core/dev/pipeline/orchestrator/schemas/task_queue_schema.json +0 -58
- package/core/dev/pipeline/orchestrator/schemas/task_schema.json +0 -139
- package/core/dev/pipeline/plans/PLAN_task_cli_refactor.md +0 -281
- package/core/dev/pipeline/test_results/TASK_TEST_PARALLEL_002_result.txt +0 -27
- package/core/dev/plans/ANSUZ_SLIM_PLAN.md +0 -68
- package/core/dev/plans/CLI_FIRST_INSTALL_FLOW.md +0 -120
- package/core/dev/plans/FORMATION_RETIREMENT_PLAN.md +0 -313
- package/core/dev/plans/KUZU_REPLACEMENT_PLAN.md +0 -126
- package/core/dev/scripts/CRASH_DIAGNOSIS.md +0 -47
- package/core/dev/scripts/README.md +0 -142
- package/core/dev/scripts/RUN_ONCE.bat +0 -40
- package/core/dev/scripts/START_DEV_AGENT.bat +0 -63
- package/core/dev/scripts/START_MULTI_AGENT.bat +0 -80
- package/core/dev/scripts/dev_agent_scheduler.ps1 +0 -536
- package/core/dev/scripts/init_git.ps1 +0 -396
- package/core/dev/scripts/init_git.sh +0 -337
- package/core/dev/scripts/init_project.ps1 +0 -851
- package/core/dev/scripts/init_project.sh +0 -477
- package/core/dev/scripts/multi_agent_scheduler.ps1 +0 -2021
- package/core/dev/scripts/multi_agent_scheduler.sh +0 -1344
- package/core/dev/scripts/run_once.sh +0 -47
- package/core/dev/scripts/setup_rag.ps1 +0 -304
- package/core/dev/scripts/setup_rag.sh +0 -230
- package/core/dev/scripts/start_dev_agent.sh +0 -137
- package/core/dev/scripts/start_multi_agent.sh +0 -41
- package/core/dev/scripts/sync_task_queue.ps1 +0 -505
- package/core/dev/scripts/sync_task_queue.sh +0 -392
- package/core/dev/specs/agent-connect/PROTOCOL.md +0 -177
- package/core/dev/specs/agent-connect/SDK_GUIDE.md +0 -915
- package/core/dev/specs/agent-connect/examples/minimal-site/README.md +0 -137
- package/core/dev/specs/agent-connect/examples/minimal-site/package.json +0 -12
- package/core/dev/specs/agent-connect/examples/minimal-site/public/index.html +0 -116
- package/core/dev/specs/agent-connect/examples/minimal-site/public/install-redirect.js +0 -73
- package/core/dev/specs/agent-connect/examples/minimal-site/server.js +0 -516
- package/core/dev/specs/agent-connect/examples/minimal-site/test/smoke.test.mjs +0 -263
- 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
- package/core/dev/specs/agent-connect/history/DEFECT_REPORT_kenaz-agent-hub_2026-09-09_v0.4-prompt-mojibake.md +0 -90
- package/core/dev/specs/agent-connect/history/FEATURE_REQUEST_kenaz-agent-hub_2026-09-07.md +0 -61
- package/core/dev/specs/agent-connect/history/FEATURE_REQUEST_kenaz-agent-hub_2026-09-08_relay-v1-conformance.md +0 -76
- package/core/dev/specs/agent-connect/history/FEATURE_REQUEST_kenaz-agent-hub_2026-09-09_v0.4-session-channel.md +0 -87
- package/core/dev/specs/agent-connect/history/FLOWPIX_REPLY_agent-hub_2026-09-08_relay-v1-answers.md +0 -68
- package/core/dev/specs/agent-connect/history/FLOWPIX_bridge_CONTRACT.md +0 -642
- package/core/dev/specs/agent-connect/history/FLOWPIX_spikes_relay_spike_relay.mjs +0 -244
- package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-07.md +0 -77
- package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-08_direction-change-v0.3.md +0 -44
- package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-08_relay-v1-answers-ack.md +0 -37
- package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-08_relay-v1-conformance.md +0 -56
- package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-09_annotations-install-coldstart.md +0 -44
- package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-09_empty-prompt-first-turn.md +0 -56
- package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-09_prompt-mojibake-fixed.md +0 -48
- package/core/dev/specs/agent-connect/history/KENAZ_RESPONSE_agent-hub_2026-09-09_session-channel.md +0 -57
- package/core/dev/specs/agent-connect/history/PROTOCOL_v0.3_snapshot.md +0 -379
- package/core/dev/specs/agent-connect/history/README.md +0 -47
- package/core/dev/specs/peer/CODEX_INTERACTIVE_PUSH.md +0 -65
- package/core/dev/specs/peer/CODEX_MANAGED_DAEMON.md +0 -54
- package/core/dev/specs/peer/CODEX_PEER_PULL_SPIKE.md +0 -54
- package/core/dev/specs/peer/MODS_SPIKE.md +0 -133
- package/core/dev/specs/peer/PER_PROJECT_ADDRESSING.md +0 -143
- package/core/dev/specs/peer/SWARM_PROTOCOLS.md +0 -256
- package/core/dev/specs/peer/codex-hook-shim-peer.test.js +0 -113
- package/core/dev/specs/peer/codex-push-launcher.test.js +0 -142
- package/core/dev/specs/peer/setup-codex-hooks.test.js +0 -60
- package/core/dev/specs/peer-ansuz/DELIVERY_SPIKE.md +0 -397
- package/core/dev/specs/peer-ansuz/DESIGN.md +0 -109
- package/core/dev/specs/peer-ansuz/spike/claude_poke.js +0 -129
- package/core/dev/specs/peer-ansuz/spike/claude_session_start_hook.js +0 -37
- package/core/dev/specs/peer-ansuz/spike/claude_settings_hook.json +0 -14
- package/core/dev/specs/peer-ansuz/spike/codex_appserver_client.js +0 -105
- package/core/dev/specs/peer-ansuz/spike/codex_appserver_query.js +0 -29
- package/core/dev/specs/peer-ansuz/spike/extract_timeline.js +0 -26
- package/core/dev/specs/synapse/SYMBOL_IDENTITY.md +0 -305
- package/core/dev/spikes/A4-cypher-varlen.md +0 -176
- package/core/dev/spikes/bloat-rounds.sh +0 -25
- package/core/dev/spikes/mods/clean-claude.js +0 -9
- package/core/dev/spikes/mods/drive-probe.js +0 -29
- package/core/dev/spikes/mods/e2e-peer.js +0 -71
- package/core/dev/spikes/mods/evidence/e2e-peer-control.json +0 -17
- package/core/dev/spikes/mods/evidence/e2e-peer-mod.json +0 -17
- package/core/dev/spikes/mods/evidence/probe-006a6e65-d807-4bc1-b648-fd7d1edfe0b4.jsonl +0 -4
- package/core/dev/spikes/mods/evidence/probe-cebdf1f7-f9c4-47a8-83cd-7c0786177404.jsonl +0 -12
- package/core/dev/spikes/mods/evidence/probe-eb21147d-10ce-4c32-93ed-37ca37d88d5a.jsonl +0 -11
- package/core/dev/spikes/mods/evidence/stream-cebdf1f7.jsonl +0 -18
- package/core/dev/spikes/mods/kenaz-mod-probe/.claude-plugin/plugin.json +0 -1
- package/core/dev/spikes/mods/kenaz-mod-probe/hooks/hooks.json +0 -1
- package/core/dev/spikes/mods/kenaz-mod-probe/hooks/register.ts +0 -65
- package/core/dev/spikes/mods/kenaz-mod-probe/tsconfig.json +0 -3
|
@@ -14,7 +14,7 @@ const fs = require('fs');
|
|
|
14
14
|
const os = require('os');
|
|
15
15
|
const path = require('path');
|
|
16
16
|
const http = require('http');
|
|
17
|
-
const { spawnSync } = require('child_process');
|
|
17
|
+
const { spawnSync, spawn } = require('child_process');
|
|
18
18
|
|
|
19
19
|
const ENV_KEY = 'CLAUDE_CODE_PLUGIN_DIRS';
|
|
20
20
|
const BACKUP = 'settings.json.bak-kenaz-peer'; // shared with the Rust path on purpose: one backup of the pristine file
|
|
@@ -22,6 +22,9 @@ const MIN_CLI = [2, 1, 287];
|
|
|
22
22
|
const SEP = process.platform === 'win32' ? ';' : ':';
|
|
23
23
|
const TASK_NAME = 'KenazServer';
|
|
24
24
|
const LABEL = 'ai.kenaz.server';
|
|
25
|
+
const RUN_KEY = 'HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run';
|
|
26
|
+
const BATTERY_PS = '$s = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -ExecutionTimeLimit ([TimeSpan]::Zero); Set-ScheduledTask -TaskName ' + TASK_NAME + ' -Settings $s';
|
|
27
|
+
const linuxUser = () => { try { return os.userInfo().username; } catch (_) { return process.env.USER || ''; } };
|
|
25
28
|
|
|
26
29
|
const norm = (e) => {
|
|
27
30
|
const s = String(e).trim().replace(/\\/g, '/').replace(/\/+$/, '');
|
|
@@ -113,9 +116,14 @@ function unregisterStatusline(file, dry) {
|
|
|
113
116
|
// agent-flow curl/node posts) duplicate what plugins/kenaz/hooks/hooks.json now runs. Single owner = the plugin, so
|
|
114
117
|
// once it is registered these are removed (first write backs up the pristine file to settings.json.bak-kenaz-peer).
|
|
115
118
|
const DASH_HOOK = /_user-scope\.js|[\\/]\.claude[\\/]hooks[\\/][\w.-]+\.js|\/api\/rust\/agent-flow\/hook/;
|
|
119
|
+
// Field report 2026-10-19: Kenaz never wrote hooks into the user's own ~/.claude/hooks, so a hook there is the user's.
|
|
120
|
+
const HOME_HOOKS = /(^|["'\s])(~|\$\{?HOME\}?|%USERPROFILE%)[\\/]\.claude[\\/]hooks[\\/]/i;
|
|
121
|
+
const slashLower = (s) => s.replace(/\\/g, '/').toLowerCase();
|
|
116
122
|
/** @returns number of hook commands retired */
|
|
117
123
|
function retireDashboardHooks(file, dry) {
|
|
118
124
|
if (!fs.existsSync(file)) return 0;
|
|
125
|
+
const homeHooks = slashLower(path.join(path.dirname(file), 'hooks')) + '/';
|
|
126
|
+
const isDash = (c) => DASH_HOOK.test(c) && !HOME_HOOKS.test(c) && !slashLower(c).includes(homeHooks);
|
|
119
127
|
const v = loadSettings(file);
|
|
120
128
|
if (!v.hooks || typeof v.hooks !== 'object' || Array.isArray(v.hooks)) return 0;
|
|
121
129
|
let n = 0;
|
|
@@ -124,7 +132,7 @@ function retireDashboardHooks(file, dry) {
|
|
|
124
132
|
const groups = [];
|
|
125
133
|
for (const g of v.hooks[ev]) {
|
|
126
134
|
if (!g || !Array.isArray(g.hooks)) { groups.push(g); continue; }
|
|
127
|
-
const kept = g.hooks.filter((h) => !(h && typeof h.command === 'string' &&
|
|
135
|
+
const kept = g.hooks.filter((h) => !(h && typeof h.command === 'string' && isDash(h.command)));
|
|
128
136
|
n += g.hooks.length - kept.length;
|
|
129
137
|
if (kept.length) groups.push(kept.length === g.hooks.length ? g : { ...g, hooks: kept });
|
|
130
138
|
}
|
|
@@ -136,20 +144,22 @@ function retireDashboardHooks(file, dry) {
|
|
|
136
144
|
|
|
137
145
|
function claudeVersion() {
|
|
138
146
|
const r = process.platform === 'win32' // one string with shell (.cmd shim): args + shell:true is deprecated (DEP0190)
|
|
139
|
-
? spawnSync('claude --version', { encoding: 'utf8', shell: true, timeout: 15000 })
|
|
140
|
-
: spawnSync('claude', ['--version'], { encoding: 'utf8', timeout: 15000 });
|
|
147
|
+
? spawnSync('claude --version', { windowsHide: true, encoding: 'utf8', shell: true, timeout: 15000 })
|
|
148
|
+
: spawnSync('claude', ['--version'], { windowsHide: true, encoding: 'utf8', timeout: 15000 });
|
|
141
149
|
return r.status === 0 ? parseVersion(r.stdout) : null;
|
|
142
150
|
}
|
|
143
151
|
|
|
144
152
|
// ---- service definitions (pure; the OS calls are in service* below) ----
|
|
145
153
|
function launcherPaths(home) {
|
|
146
154
|
const d = path.join(home, '.kenaz');
|
|
147
|
-
return { dir: d,
|
|
155
|
+
return { dir: d, log: path.join(d, 'kenaz-server.log') };
|
|
148
156
|
}
|
|
149
157
|
const q = (s) => '"' + s + '"';
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
158
|
+
// TASK_2478: kenaz-server is a no-console binary on Windows and takes the core dir as an argument (no launcher script).
|
|
159
|
+
function winRunCmd(bin, core) { return q(bin) + ' --source-dir ' + q(core); }
|
|
160
|
+
// TASK_2478 migration: the old script-host launchers (antivirus flagged them); removed on install and uninstall.
|
|
161
|
+
function legacyLaunchers(home, roaming) {
|
|
162
|
+
return [path.join(home, '.kenaz', 'kenaz-server.vbs'), path.join(roaming, 'Microsoft', 'Windows', 'Start Menu', 'Programs', 'Startup', 'KenazServer.vbs')]; // legacy-vbs-cleanup
|
|
153
163
|
}
|
|
154
164
|
// launchd and systemd start the server with a bare PATH (/usr/bin:/bin...), so `node` from Homebrew,
|
|
155
165
|
// nvm or /usr/local was not found and every MCP tool that runs a node script failed with
|
|
@@ -195,8 +205,7 @@ function servicePlan(home, bin, core, platform = process.platform, caps = { syst
|
|
|
195
205
|
const L = launcherPaths(home);
|
|
196
206
|
if (platform === 'win32') {
|
|
197
207
|
const roaming = home === os.homedir() && process.env.APPDATA ? process.env.APPDATA : path.join(home, 'AppData', 'Roaming');
|
|
198
|
-
|
|
199
|
-
return { kind: 'windows', files: [[L.vbs, winVbs(bin, core)]], fallbackFile: startup };
|
|
208
|
+
return { kind: 'windows', files: [], bin, core, runCmd: winRunCmd(bin, core), legacy: legacyLaunchers(home, roaming) };
|
|
200
209
|
}
|
|
201
210
|
if (platform === 'darwin') {
|
|
202
211
|
const p = path.join(home, 'Library', 'LaunchAgents', LABEL + '.plist');
|
|
@@ -208,7 +217,7 @@ function servicePlan(home, bin, core, platform = process.platform, caps = { syst
|
|
|
208
217
|
const p = path.join(home, '.config', 'systemd', 'user', 'kenaz-server.service');
|
|
209
218
|
return { kind: 'systemd', files: [[p, systemdUnit(bin, core)]], unit: p };
|
|
210
219
|
}
|
|
211
|
-
const sh = (cmd, args, opts) => spawnSync(cmd, args, { encoding: 'utf8', ...(opts || {}) });
|
|
220
|
+
const sh = (cmd, args, opts) => spawnSync(cmd, args, { windowsHide: true, encoding: 'utf8', ...(opts || {}) });
|
|
212
221
|
|
|
213
222
|
// crontab -l: null = no crontab binary; '' = binary present, no crontab yet. All through the injected `run`.
|
|
214
223
|
function readCron(run) {
|
|
@@ -239,8 +248,7 @@ function restartHint(plan, uid = defaultUid()) {
|
|
|
239
248
|
if (plan.kind === 'launchd') return 'launchctl kickstart -k gui/' + uid + '/' + LABEL;
|
|
240
249
|
if (plan.kind === 'systemd') return 'systemctl --user restart kenaz-server';
|
|
241
250
|
if (plan.kind === 'cron' || plan.kind === 'manual') return stopCmd(plan) + '; ' + detachedStartCmd(plan);
|
|
242
|
-
|
|
243
|
-
return 'end kenaz-server.exe in Task Manager, then run: wscript.exe ' + q(plan.files && plan.files[0] ? plan.files[0][0] : 'kenaz-server.vbs');
|
|
251
|
+
return 'end kenaz-server.exe in Task Manager, then run: ' + plan.runCmd;
|
|
244
252
|
}
|
|
245
253
|
function serviceRestart(plan, dry, log, run = sh, uid = defaultUid()) {
|
|
246
254
|
if (plan.kind === 'cron' || plan.kind === 'manual') { // no supervisor: start it (stopOwnServer freed the old one)
|
|
@@ -295,22 +303,28 @@ async function verifyRuntime(plan, expected, log, opts = {}) {
|
|
|
295
303
|
return 'unreachable';
|
|
296
304
|
}
|
|
297
305
|
|
|
298
|
-
function serviceInstall(plan, dry, log, run = sh, uid) {
|
|
306
|
+
function serviceInstall(plan, dry, log, run = sh, uid, spawnFn = spawn) {
|
|
299
307
|
const sh = run; // injectable for tests; shadows the module-level spawnSync wrapper inside this function
|
|
300
308
|
for (const [f, body] of plan.files) { log('write ' + f); if (!dry) { fs.mkdirSync(path.dirname(f), { recursive: true }); fs.writeFileSync(f, body); } }
|
|
301
309
|
if (plan.kind === 'windows') {
|
|
302
|
-
const tr =
|
|
303
|
-
log('schtasks /Create /TN ' + TASK_NAME + ' /SC ONLOGON /TR ' + tr + ' /F (fallback: ' +
|
|
310
|
+
const tr = plan.runCmd;
|
|
311
|
+
log('schtasks /Create /TN ' + TASK_NAME + ' /SC ONLOGON /TR ' + tr + ' /F (fallback: ' + RUN_KEY + '\\' + TASK_NAME + ')');
|
|
312
|
+
removeLegacy(plan, dry, log);
|
|
304
313
|
if (dry) return;
|
|
305
314
|
const r = sh('schtasks', ['/Create', '/TN', TASK_NAME, '/SC', 'ONLOGON', '/TR', tr, '/F']);
|
|
306
|
-
if (r.status === 0)
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
315
|
+
if (r.status === 0) {
|
|
316
|
+
// Task Scheduler defaults refuse to start on battery and stop the task when going on battery:
|
|
317
|
+
// a laptop unplugged at logon never got the server (TASK_2468). Re-running install fixes an old task.
|
|
318
|
+
const b = sh('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', BATTERY_PS]);
|
|
319
|
+
if (b.status !== 0) log('WARNING: could not set the task to run on battery (exit ' + b.status + '); on a laptop the server may not start unplugged. Run in PowerShell: ' + BATTERY_PS);
|
|
320
|
+
sh('schtasks', ['/Run', '/TN', TASK_NAME]);
|
|
321
|
+
} else { // ONLOGON tasks can need elevation: an HKCU Run value is the per-user equivalent
|
|
322
|
+
sh('reg', ['add', RUN_KEY, '/v', TASK_NAME, '/t', 'REG_SZ', '/d', plan.runCmd, '/f']);
|
|
323
|
+
const c = spawnFn(plan.bin, ['--source-dir', plan.core], { detached: true, stdio: 'ignore', windowsHide: true });
|
|
324
|
+
c.on('error', () => {}); c.unref();
|
|
311
325
|
// schtasks' stderr is in the console's OEM code page (garbled when echoed); the usual cause is
|
|
312
|
-
// missing admin rights for /SC ONLOGON. The
|
|
313
|
-
log('schtasks needs administrator rights here (exit ' + r.status + ');
|
|
326
|
+
// missing admin rights for /SC ONLOGON. The Run value starts the server at logon the same way.
|
|
327
|
+
log('schtasks needs administrator rights here (exit ' + r.status + '); registered the HKCU Run value instead (also starts at logon)');
|
|
314
328
|
}
|
|
315
329
|
} else if (plan.kind === 'launchd') {
|
|
316
330
|
log('launchctl load -w ' + plan.unit); if (!dry) sh('launchctl', ['load', '-w', plan.unit]);
|
|
@@ -326,14 +340,23 @@ function serviceInstall(plan, dry, log, run = sh, uid) {
|
|
|
326
340
|
} else {
|
|
327
341
|
log('systemctl --user enable --now kenaz-server');
|
|
328
342
|
if (!dry) { sh('systemctl', ['--user', 'daemon-reload']); sh('systemctl', ['--user', 'enable', '--now', 'kenaz-server']); }
|
|
343
|
+
// Without linger the user service starts only at login (headless boxes: never). Best effort.
|
|
344
|
+
const u = linuxUser();
|
|
345
|
+
log('loginctl enable-linger ' + u);
|
|
346
|
+
if (!dry && sh('loginctl', ['enable-linger', u]).status !== 0) log('WARNING: could not enable linger; the server starts at boot only after you log in. Run: loginctl enable-linger ' + u + ' (may need sudo)');
|
|
329
347
|
serviceRestart(plan, dry, log, sh, uid);
|
|
330
348
|
}
|
|
331
349
|
}
|
|
350
|
+
function removeLegacy(plan, dry, log) {
|
|
351
|
+
for (const f of plan.legacy || []) if (fs.existsSync(f)) { log('remove ' + f + ' (old launcher)'); if (!dry) fs.rmSync(f, { force: true }); }
|
|
352
|
+
}
|
|
332
353
|
function serviceUninstall(plan, dry, log, run = sh) {
|
|
333
354
|
if (plan.kind === 'windows') {
|
|
334
355
|
log('schtasks /End + /Delete /TN ' + TASK_NAME);
|
|
335
356
|
if (!dry) { run('schtasks', ['/End', '/TN', TASK_NAME]); run('schtasks', ['/Delete', '/TN', TASK_NAME, '/F']); }
|
|
336
|
-
|
|
357
|
+
log('reg delete ' + RUN_KEY + ' /v ' + TASK_NAME);
|
|
358
|
+
if (!dry) run('reg', ['delete', RUN_KEY, '/v', TASK_NAME, '/f']); // not-found is fine
|
|
359
|
+
removeLegacy(plan, dry, log);
|
|
337
360
|
} else if (plan.kind === 'launchd') {
|
|
338
361
|
log('launchctl unload ' + plan.unit); if (!dry) run('launchctl', ['unload', '-w', plan.unit]);
|
|
339
362
|
} else if (plan.kind === 'cron' || plan.kind === 'manual') {
|
|
@@ -347,7 +370,7 @@ function serviceUninstall(plan, dry, log, run = sh) {
|
|
|
347
370
|
function serviceStatus(plan, run = sh) {
|
|
348
371
|
if (plan.kind === 'cron') { const c = readCron(run); return c && c.includes(CRON_MARK) ? 'cron @reboot entry present' : 'not installed'; }
|
|
349
372
|
if (plan.kind === 'manual') return 'manual (no systemd user session, no crontab)';
|
|
350
|
-
if (plan.kind === 'windows') return run('schtasks', ['/Query', '/TN', TASK_NAME]).status === 0 ? 'scheduled task present' : (
|
|
373
|
+
if (plan.kind === 'windows') return run('schtasks', ['/Query', '/TN', TASK_NAME]).status === 0 ? 'scheduled task present' : (run('reg', ['query', RUN_KEY, '/v', TASK_NAME]).status === 0 ? 'Run key present' : 'not installed');
|
|
351
374
|
if (plan.kind === 'systemd') return run('systemctl', ['--user', 'is-active', 'kenaz-server']).stdout.trim() || 'not installed';
|
|
352
375
|
return fs.existsSync(plan.unit) ? 'plist present' : 'not installed';
|
|
353
376
|
}
|
|
@@ -355,17 +378,20 @@ function serviceStatus(plan, run = sh) {
|
|
|
355
378
|
/** Which mechanism keeps the server running on this machine (for `kenaz doctor`). Read-only, all via `run`. */
|
|
356
379
|
function detectServiceMode(home, core, run = sh, platform = process.platform) {
|
|
357
380
|
if (platform === 'win32') {
|
|
358
|
-
const plan = servicePlan(home, '', core, 'win32');
|
|
359
381
|
if (run('schtasks', ['/Query', '/TN', TASK_NAME]).status === 0) return { mode: 'windows task', detail: 'scheduled task ' + TASK_NAME };
|
|
360
|
-
if (
|
|
361
|
-
return { mode: 'manual', detail: 'no scheduled task or
|
|
382
|
+
if (run('reg', ['query', RUN_KEY, '/v', TASK_NAME]).status === 0) return { mode: 'run key', detail: RUN_KEY + '\\' + TASK_NAME };
|
|
383
|
+
return { mode: 'manual', detail: 'no scheduled task or Run key; run `kenaz install`' };
|
|
362
384
|
}
|
|
363
385
|
if (platform === 'darwin') {
|
|
364
386
|
const p = servicePlan(home, '', core, 'darwin').unit;
|
|
365
387
|
return fs.existsSync(p) ? { mode: 'launchd', detail: p } : { mode: 'manual', detail: 'no launchd agent; run `kenaz install`' };
|
|
366
388
|
}
|
|
367
389
|
const unit = servicePlan(home, '', core, 'linux').unit;
|
|
368
|
-
if (fs.existsSync(unit) && probeLinux(run).systemd)
|
|
390
|
+
if (fs.existsSync(unit) && probeLinux(run).systemd) {
|
|
391
|
+
const u = linuxUser();
|
|
392
|
+
const off = /Linger=no/.test(run('loginctl', ['show-user', u, '-p', 'Linger']).stdout || '');
|
|
393
|
+
return off ? { mode: 'systemd', detail: unit + '; linger is off, the server starts only after login: run loginctl enable-linger ' + u, warn: true } : { mode: 'systemd', detail: unit };
|
|
394
|
+
}
|
|
369
395
|
const c = readCron(run);
|
|
370
396
|
if (c && c.includes(CRON_MARK)) return { mode: 'cron', detail: '@reboot crontab entry (no systemd user session)' };
|
|
371
397
|
return { mode: 'manual', detail: 'no systemd unit or cron entry; run `kenaz install`' };
|
|
@@ -453,4 +479,4 @@ function main(argv, out = console.log, getVersion = claudeVersion, deps = {}) {
|
|
|
453
479
|
}
|
|
454
480
|
|
|
455
481
|
if (require.main === module) process.exit(main(process.argv.slice(2)));
|
|
456
|
-
module.exports = { main, verifyRuntime, healthOnce, serviceInstall, serviceRestart, restartHint, claudeVersion, loadSettings, entriesOf, norm, MIN_CLI, registerPlugin, unregisterPlugin, registerStatusline, unregisterStatusline, retireDashboardHooks, servicePlan, detectServiceMode, probeLinux, cronLine, CRON_MARK,
|
|
482
|
+
module.exports = { main, verifyRuntime, healthOnce, serviceInstall, serviceUninstall, serviceRestart, restartHint, claudeVersion, loadSettings, entriesOf, norm, MIN_CLI, registerPlugin, unregisterPlugin, registerStatusline, unregisterStatusline, retireDashboardHooks, servicePlan, detectServiceMode, probeLinux, cronLine, CRON_MARK, winRunCmd, RUN_KEY, launchdPlist, systemdUnit, parseVersion, cmpVersion };
|
|
@@ -103,7 +103,7 @@ function countLines(text) {
|
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
function git(args, cwd) {
|
|
106
|
-
const result = spawnSync('git', args, { cwd, encoding: 'utf8' });
|
|
106
|
+
const result = spawnSync('git', args, { windowsHide: true, cwd, encoding: 'utf8' });
|
|
107
107
|
return result;
|
|
108
108
|
}
|
|
109
109
|
|
|
@@ -40,7 +40,7 @@ const TASK_API = path.join(ROOT, '.collaboration', 'core', 'task-api.js');
|
|
|
40
40
|
// ─────────────────────────────────────────
|
|
41
41
|
|
|
42
42
|
function runTaskApi(...args) {
|
|
43
|
-
const result = spawnSync('node', [TASK_API, ...args], {
|
|
43
|
+
const result = spawnSync('node', [TASK_API, ...args], { windowsHide: true,
|
|
44
44
|
encoding: 'utf8',
|
|
45
45
|
timeout: 15000,
|
|
46
46
|
cwd: ROOT,
|
|
@@ -72,11 +72,11 @@ const DRY_RUN = !process.argv.includes('--apply');
|
|
|
72
72
|
// ─── Git helpers (GEN-008: dynamic root, never hardcoded) ────────────────────
|
|
73
73
|
|
|
74
74
|
function gitRoot() {
|
|
75
|
-
return execSync('git rev-parse --show-toplevel', { encoding: 'utf8' }).trim();
|
|
75
|
+
return execSync('git rev-parse --show-toplevel', { windowsHide: true, encoding: 'utf8' }).trim();
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
function currentBranch() {
|
|
79
|
-
return execSync('git rev-parse --abbrev-ref HEAD', { encoding: 'utf8' }).trim();
|
|
79
|
+
return execSync('git rev-parse --abbrev-ref HEAD', { windowsHide: true, encoding: 'utf8' }).trim();
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
/**
|
|
@@ -84,7 +84,7 @@ function currentBranch() {
|
|
|
84
84
|
* Uses exit code of `git merge-base --is-ancestor <commit> HEAD`.
|
|
85
85
|
*/
|
|
86
86
|
function isAncestorOfHead(tipCommit) {
|
|
87
|
-
const result = spawnSync('git', ['merge-base', '--is-ancestor', tipCommit, 'HEAD'], {
|
|
87
|
+
const result = spawnSync('git', ['merge-base', '--is-ancestor', tipCommit, 'HEAD'], { windowsHide: true,
|
|
88
88
|
encoding: 'utf8',
|
|
89
89
|
});
|
|
90
90
|
return result.status === 0;
|
|
@@ -95,7 +95,7 @@ function isAncestorOfHead(tipCommit) {
|
|
|
95
95
|
* Each entry: { path, head, branch, locked, lockReason }
|
|
96
96
|
*/
|
|
97
97
|
function listWorktrees() {
|
|
98
|
-
const raw = execSync('git worktree list --porcelain', { encoding: 'utf8' });
|
|
98
|
+
const raw = execSync('git worktree list --porcelain', { windowsHide: true, encoding: 'utf8' });
|
|
99
99
|
const entries = [];
|
|
100
100
|
let current = null;
|
|
101
101
|
|
|
@@ -199,7 +199,7 @@ function listUntrackedAgentDirs(root, trackedPaths) {
|
|
|
199
199
|
function listDanglingAgentBranches(trackedBranches) {
|
|
200
200
|
let raw = '';
|
|
201
201
|
try {
|
|
202
|
-
raw = execSync('git branch --list "worktree-agent-*" --format="%(refname:short)"', { encoding: 'utf8' });
|
|
202
|
+
raw = execSync('git branch --list "worktree-agent-*" --format="%(refname:short)"', { windowsHide: true, encoding: 'utf8' });
|
|
203
203
|
} catch {
|
|
204
204
|
return [];
|
|
205
205
|
}
|
|
@@ -209,7 +209,7 @@ function listDanglingAgentBranches(trackedBranches) {
|
|
|
209
209
|
const b = line.trim();
|
|
210
210
|
if (!b || trackedSet.has(b)) continue;
|
|
211
211
|
let tip = '';
|
|
212
|
-
try { tip = execSync(`git rev-parse "${b}"`, { encoding: 'utf8' }).trim(); } catch { /* ignore */ }
|
|
212
|
+
try { tip = execSync(`git rev-parse "${b}"`, { windowsHide: true, encoding: 'utf8' }).trim(); } catch { /* ignore */ }
|
|
213
213
|
out.push({ branch: b, tip, integrated: tip ? isAncestorOfHead(tip) : false });
|
|
214
214
|
}
|
|
215
215
|
return out;
|
|
@@ -354,7 +354,7 @@ function main() {
|
|
|
354
354
|
// Unlock if locked (harness may have left lock even after pid is gone)
|
|
355
355
|
if (wt.locked) {
|
|
356
356
|
try {
|
|
357
|
-
execSync(`git worktree unlock "${wt.path}"`, { encoding: 'utf8' });
|
|
357
|
+
execSync(`git worktree unlock "${wt.path}"`, { windowsHide: true, encoding: 'utf8' });
|
|
358
358
|
} catch {
|
|
359
359
|
// unlock may fail if git disagrees — proceed, remove --force handles it
|
|
360
360
|
}
|
|
@@ -365,7 +365,8 @@ function main() {
|
|
|
365
365
|
// checkout's node_modules). Reuse the hook's helper (never copy it). If it is
|
|
366
366
|
// unavailable, refuse to remove rather than risk traversal.
|
|
367
367
|
try {
|
|
368
|
-
require(path.join(__dirname, '..', '..', '.claude', 'hooks', 'worktree-create.js')).unlinkNodeModulesLinks(wt.path);
|
|
368
|
+
const unl = require(path.join(__dirname, '..', '..', '.claude', 'hooks', 'worktree-create.js')).unlinkNodeModulesLinks(wt.path);
|
|
369
|
+
if (unl.failed.length) throw new Error('link(s) survive unlink: ' + unl.failed.slice(0, 3).join(', '));
|
|
369
370
|
} catch (err) {
|
|
370
371
|
console.log(` FAILED (node_modules unlink unavailable, not removing): ${err.message.trim()}`);
|
|
371
372
|
failedCount++;
|
|
@@ -374,7 +375,7 @@ function main() {
|
|
|
374
375
|
|
|
375
376
|
// Remove worktree (--force bypasses remaining lock metadata)
|
|
376
377
|
try {
|
|
377
|
-
execSync(`git worktree remove --force "${wt.path}"`, { encoding: 'utf8' });
|
|
378
|
+
execSync(`git worktree remove --force "${wt.path}"`, { windowsHide: true, encoding: 'utf8' });
|
|
378
379
|
} catch (err) {
|
|
379
380
|
console.log(` FAILED (worktree remove): ${err.message.trim()}`);
|
|
380
381
|
failedCount++;
|
|
@@ -384,7 +385,7 @@ function main() {
|
|
|
384
385
|
// Delete the branch (best-effort; branch may already be deleted or missing)
|
|
385
386
|
if (wt.branch) {
|
|
386
387
|
try {
|
|
387
|
-
execSync(`git branch -D "${wt.branch}"`, { encoding: 'utf8' });
|
|
388
|
+
execSync(`git branch -D "${wt.branch}"`, { windowsHide: true, encoding: 'utf8' });
|
|
388
389
|
} catch {
|
|
389
390
|
// Branch may already be deleted — not an error
|
|
390
391
|
}
|
|
@@ -396,7 +397,7 @@ function main() {
|
|
|
396
397
|
|
|
397
398
|
// Prune stale worktree admin dirs (idempotent, always safe)
|
|
398
399
|
try {
|
|
399
|
-
execSync('git worktree prune', { encoding: 'utf8' });
|
|
400
|
+
execSync('git worktree prune', { windowsHide: true, encoding: 'utf8' });
|
|
400
401
|
console.log('\n git worktree prune done');
|
|
401
402
|
} catch (err) {
|
|
402
403
|
console.log(`\n git worktree prune FAILED (non-fatal): ${err.message.trim()}`);
|
|
@@ -419,7 +420,7 @@ function main() {
|
|
|
419
420
|
for (const b of danglingBranches) {
|
|
420
421
|
if (!b.integrated) continue; // keep not-in-HEAD branches for salvage
|
|
421
422
|
try {
|
|
422
|
-
execSync(`git branch -D "${b.branch}"`, { encoding: 'utf8' });
|
|
423
|
+
execSync(`git branch -D "${b.branch}"`, { windowsHide: true, encoding: 'utf8' });
|
|
423
424
|
danglingDeleted++;
|
|
424
425
|
} catch { /* already gone — not an error */ }
|
|
425
426
|
}
|
|
@@ -218,7 +218,7 @@ function parseCliArgs(argv) {
|
|
|
218
218
|
function resolveExecutableWindows(whereFn) {
|
|
219
219
|
whereFn = whereFn || function runWhere() {
|
|
220
220
|
try {
|
|
221
|
-
return cp.execSync('where claude', { encoding: 'utf8' });
|
|
221
|
+
return cp.execSync('where claude', { windowsHide: true, encoding: 'utf8' });
|
|
222
222
|
} catch (e) {
|
|
223
223
|
return '';
|
|
224
224
|
}
|
|
@@ -263,13 +263,13 @@ function escapeCmdExe(exe) {
|
|
|
263
263
|
|
|
264
264
|
function launch(exec, cwd, argv) {
|
|
265
265
|
if (exec.useShell) {
|
|
266
|
-
return cp.spawn(escapeCmdExe(exec.command), argv.map(escapeCmdArg), {
|
|
266
|
+
return cp.spawn(escapeCmdExe(exec.command), argv.map(escapeCmdArg), { windowsHide: true,
|
|
267
267
|
cwd,
|
|
268
268
|
stdio: 'inherit',
|
|
269
269
|
shell: true,
|
|
270
270
|
});
|
|
271
271
|
}
|
|
272
|
-
return cp.spawn(exec.command, argv, { cwd, stdio: 'inherit', shell: false });
|
|
272
|
+
return cp.spawn(exec.command, argv, { windowsHide: true, cwd, stdio: 'inherit', shell: false });
|
|
273
273
|
}
|
|
274
274
|
|
|
275
275
|
// ---- main ----
|
|
@@ -59,12 +59,12 @@ function start(name, exe, args, env, cwd) {
|
|
|
59
59
|
}
|
|
60
60
|
async function stop(p) {
|
|
61
61
|
if (!p || p.exited) return;
|
|
62
|
-
if (process.platform === 'win32') spawnSync('taskkill', ['/PID', String(p.pid), '/T', '/F'], { stdio: 'ignore' }); // our PID only
|
|
62
|
+
if (process.platform === 'win32') spawnSync('taskkill', ['/PID', String(p.pid), '/T', '/F'], { windowsHide: true, stdio: 'ignore' }); // our PID only
|
|
63
63
|
else p.child.kill('SIGKILL');
|
|
64
64
|
await until(`${p.name} exit`, () => p.exited, 15000, 100).catch(() => {});
|
|
65
65
|
}
|
|
66
66
|
function sh(cmd, args, env) {
|
|
67
|
-
const r = spawnSync(cmd, args, { env: { ...process.env, ...env }, encoding: 'utf8' });
|
|
67
|
+
const r = spawnSync(cmd, args, { windowsHide: true, env: { ...process.env, ...env }, encoding: 'utf8' });
|
|
68
68
|
return { code: r.status, out: `${r.stdout || ''}${r.stderr || ''}`.trim() };
|
|
69
69
|
}
|
|
70
70
|
function sqlite(file, readOnly = true) {
|
|
@@ -195,7 +195,9 @@ async function main() {
|
|
|
195
195
|
const missing = Object.entries({ relay: BIN.relay, relayOld: BIN.relayOld, server: BIN.server, serverOldSrc: BIN.serverOldSrc }).filter(([, p]) => !fs.existsSync(p));
|
|
196
196
|
if (missing.length) { console.error(`missing binaries: ${missing.map(([k, p]) => `${k}=${p}`).join(', ')}`); return 2; }
|
|
197
197
|
for (const p of Object.values(PORT)) if (!(await portFree(p))) { console.error(`port ${p} busy; aborting`); return 2; }
|
|
198
|
-
|
|
198
|
+
// TASK_2480: not under os.tmpdir() - the server refuses to register (and prunes) projects in the OS temp dir
|
|
199
|
+
fs.mkdirSync(path.join(REPO, '.tmp'), { recursive: true });
|
|
200
|
+
TMP = fs.mkdtempSync(path.join(REPO, '.tmp', 'kenaz-peer-e2e-'));
|
|
199
201
|
const runId = path.basename(TMP);
|
|
200
202
|
console.log(`peer-identity-e2e: temp dir ${TMP}${CONTROL ? ' (control run: wrong fingerprint in scenario 3)' : ''}`);
|
|
201
203
|
const gitBefore = gitState();
|
|
@@ -398,5 +400,5 @@ async function main() {
|
|
|
398
400
|
return bad ? 1 : 0;
|
|
399
401
|
}
|
|
400
402
|
|
|
401
|
-
process.on('SIGINT', () => { for (const p of procs) if (!p.exited) { if (process.platform === 'win32') spawnSync('taskkill', ['/PID', String(p.pid), '/T', '/F'], { stdio: 'ignore' }); else p.child.kill('SIGKILL'); } process.exit(130); });
|
|
403
|
+
process.on('SIGINT', () => { for (const p of procs) if (!p.exited) { if (process.platform === 'win32') spawnSync('taskkill', ['/PID', String(p.pid), '/T', '/F'], { windowsHide: true, stdio: 'ignore' }); else p.child.kill('SIGKILL'); } process.exit(130); });
|
|
402
404
|
main().then((c) => process.exit(c), (e) => { console.error(e); process.exit(1); });
|
|
@@ -142,7 +142,7 @@ function main() {
|
|
|
142
142
|
const build = spawnSync(
|
|
143
143
|
'cargo',
|
|
144
144
|
['test', '--lib', '--no-run', '--message-format=json'],
|
|
145
|
-
{ cwd: crateDir, encoding: 'utf8', shell: false, maxBuffer: 256 * 1024 * 1024, env }
|
|
145
|
+
{ windowsHide: true, cwd: crateDir, encoding: 'utf8', shell: false, maxBuffer: 256 * 1024 * 1024, env }
|
|
146
146
|
);
|
|
147
147
|
if (build.status !== 0) {
|
|
148
148
|
const compilerErrors = renderCompilerErrors(build.stdout);
|
|
@@ -180,7 +180,7 @@ function main() {
|
|
|
180
180
|
}
|
|
181
181
|
|
|
182
182
|
// 3. Run the artifact directly.
|
|
183
|
-
const run = spawnSync(testExe, exeArgs, { stdio: 'inherit' });
|
|
183
|
+
const run = spawnSync(testExe, exeArgs, { windowsHide: true, stdio: 'inherit' });
|
|
184
184
|
process.exit(run.status ?? 1);
|
|
185
185
|
}
|
|
186
186
|
|
|
@@ -36,7 +36,7 @@ function evaluate(streamText, expected) {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
function copyRepo(dest) {
|
|
39
|
-
const files = execFileSync('git', ['ls-files', '-z'], { cwd: REPO, encoding: 'utf8', maxBuffer: 1 << 28 }).split('\0').filter(Boolean);
|
|
39
|
+
const files = execFileSync('git', ['ls-files', '-z'], { windowsHide: true, cwd: REPO, encoding: 'utf8', maxBuffer: 1 << 28 }).split('\0').filter(Boolean);
|
|
40
40
|
for (const f of files) {
|
|
41
41
|
const from = path.join(REPO, f);
|
|
42
42
|
if (!fs.existsSync(from)) continue;
|
|
@@ -49,11 +49,11 @@ function runScenario(sc, opts) {
|
|
|
49
49
|
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'skill-replay-'));
|
|
50
50
|
try {
|
|
51
51
|
copyRepo(dir);
|
|
52
|
-
execFileSync('git', ['init', '-q'], { cwd: dir });
|
|
52
|
+
execFileSync('git', ['init', '-q'], { windowsHide: true, cwd: dir });
|
|
53
53
|
const prompt = (sc.prefix === undefined ? '/Ansuz ' : sc.prefix) + sc.message;
|
|
54
54
|
// Prompt goes on stdin: with shell:true (needed on Windows) argv is concatenated unquoted, which split the message.
|
|
55
55
|
const r = spawnSync('claude', ['-p', '--output-format', 'stream-json', '--verbose', '--max-turns', String(opts.maxTurns)],
|
|
56
|
-
{ cwd: dir, input: prompt, encoding: 'utf8', maxBuffer: 1 << 28, timeout: opts.timeoutMs, shell: process.platform === 'win32' });
|
|
56
|
+
{ windowsHide: true, cwd: dir, input: prompt, encoding: 'utf8', maxBuffer: 1 << 28, timeout: opts.timeoutMs, shell: process.platform === 'win32' });
|
|
57
57
|
const ev = evaluate(r.stdout || '', sc.expected);
|
|
58
58
|
return { id: sc.id, expected: sc.expected, hit: ev.hit, calls: ev.calls, exit: r.status, error: r.error && r.error.message };
|
|
59
59
|
} finally {
|
|
@@ -120,7 +120,7 @@ async function testSlowServe() {
|
|
|
120
120
|
KENAZ_FIXTURE_SLOW_PHASE_MS: '4000',
|
|
121
121
|
});
|
|
122
122
|
const spawnedAt = Date.now();
|
|
123
|
-
const child = spawn(process.execPath, [SLOW_SERVE], { env, stdio: ['ignore', 'pipe', 'pipe'] });
|
|
123
|
+
const child = spawn(process.execPath, [SLOW_SERVE], { windowsHide: true, env, stdio: ['ignore', 'pipe', 'pipe'] });
|
|
124
124
|
spawnedPids.push(child.pid);
|
|
125
125
|
let out = '';
|
|
126
126
|
child.stdout.on('data', (d) => (out += d.toString()));
|
|
@@ -166,7 +166,7 @@ async function testSlowServe() {
|
|
|
166
166
|
|
|
167
167
|
async function testNeverListens() {
|
|
168
168
|
console.log('\n[selftest] never-listens.server.js');
|
|
169
|
-
const child = spawn(process.execPath, [NEVER_LISTENS], { stdio: ['ignore', 'pipe', 'pipe'] });
|
|
169
|
+
const child = spawn(process.execPath, [NEVER_LISTENS], { windowsHide: true, stdio: ['ignore', 'pipe', 'pipe'] });
|
|
170
170
|
spawnedPids.push(child.pid);
|
|
171
171
|
let exited = false;
|
|
172
172
|
child.on('exit', () => {
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
// TASK_2474 guard: every child process Kenaz starts must be hidden on Windows.
|
|
3
|
+
// - Node: spawn/exec* calls in shipped JS must pass windowsHide (inline in the call, or on an options
|
|
4
|
+
// object defined in the same file). JS_ALLOW = intentionally visible terminals, with reasons.
|
|
5
|
+
// - Rust: Command::new in non-test Rust files outside common/process.rs must be hidden_command.
|
|
6
|
+
const test = require('node:test');
|
|
7
|
+
const assert = require('node:assert');
|
|
8
|
+
const fs = require('node:fs');
|
|
9
|
+
const path = require('node:path');
|
|
10
|
+
|
|
11
|
+
const ROOT = path.resolve(__dirname, '..', '..');
|
|
12
|
+
const JS_DIRS = ['.specialist/tools', '.formation', '.claude/hooks', 'plugins/kenaz/hooks', 'plugins/kenaz/scripts',
|
|
13
|
+
'.collaboration/core', 'packages/kenaz/lib', 'packages/kenaz/bin', 'dashboard/scripts', 'dev/scripts'];
|
|
14
|
+
const RS_DIR = 'dashboard/src-tauri/src';
|
|
15
|
+
|
|
16
|
+
// "relative/path.js:line" -> reason. Intentionally visible terminals only.
|
|
17
|
+
const JS_ALLOW = {
|
|
18
|
+
'dev/scripts/task1961/selftest.js:132': 'false positive: "spawn (took ..." inside a template-string message, not a call',
|
|
19
|
+
};
|
|
20
|
+
// "relative/path.rs" -> reason (whole file may use raw Command::new outside #[cfg(test)]).
|
|
21
|
+
const RS_ALLOW = {
|
|
22
|
+
'dashboard/src-tauri/src/common/process.rs': 'the hidden_command constructors themselves',
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
function walk(dir, exts, out = []) {
|
|
26
|
+
const abs = path.join(ROOT, dir);
|
|
27
|
+
if (!fs.existsSync(abs)) return out;
|
|
28
|
+
for (const e of fs.readdirSync(abs, { withFileTypes: true })) {
|
|
29
|
+
if (['node_modules', '.git', 'target', 'dist', 'fixtures'].includes(e.name)) continue;
|
|
30
|
+
const rel = dir + '/' + e.name;
|
|
31
|
+
if (e.isDirectory()) walk(rel, exts, out);
|
|
32
|
+
else if (exts.some((x) => e.name.endsWith(x)) && !/\.test\.[cm]?js$/.test(e.name)) out.push(rel);
|
|
33
|
+
}
|
|
34
|
+
return out;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// generated (gitignored) copies of scanned sources: core-resolve.js from .claude/hooks, packages/kenaz/vendor/ from
|
|
38
|
+
// dashboard/scripts by packages/kenaz/scripts/stage.js at pack time (a stale local copy must not fail the guard)
|
|
39
|
+
const isGenerated = (rel) => rel === 'plugins/kenaz/hooks/core-resolve.js' || rel.startsWith('packages/kenaz/vendor/');
|
|
40
|
+
|
|
41
|
+
function matchParen(src, open) {
|
|
42
|
+
let depth = 0, q = null;
|
|
43
|
+
for (let i = open; i < src.length; i++) {
|
|
44
|
+
const c = src[i];
|
|
45
|
+
if (q) { if (c === '\\') i++; else if (c === q) q = null; continue; }
|
|
46
|
+
if (c === '"' || c === "'" || c === '`') { q = c; continue; }
|
|
47
|
+
if (c === '(') depth++;
|
|
48
|
+
else if (c === ')' && --depth === 0) return i;
|
|
49
|
+
}
|
|
50
|
+
return src.length;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function scanJs(rel, src) {
|
|
54
|
+
if (!/child_process/.test(src)) return [];
|
|
55
|
+
const bad = [];
|
|
56
|
+
// blank block comments and whole-line // comments (offsets and line numbers preserved)
|
|
57
|
+
src = src.replace(/\/\*[\s\S]*?\*\//g, (c) => c.replace(/[^\n]/g, ' ')).replace(/^[ \t]*\/\/.*$/gm, (c) => ' '.repeat(c.length));
|
|
58
|
+
const re = /(?<![\w$.])(?:(?:cp|child_process|childProcess|proc)\.)?(spawn|spawnSync|exec|execSync|execFile|execFileSync)\s*\(/g;
|
|
59
|
+
let m;
|
|
60
|
+
while ((m = re.exec(src))) {
|
|
61
|
+
const open = m.index + m[0].length - 1;
|
|
62
|
+
const args = src.slice(open, matchParen(src, open) + 1);
|
|
63
|
+
if (/windowsHide/.test(args)) continue;
|
|
64
|
+
// options passed as a bare identifier: accept when that identifier is defined with windowsHide in the file
|
|
65
|
+
const last = args.slice(1, -1).split(',').pop().trim();
|
|
66
|
+
if (/^[A-Za-z_$][\w$]*$/.test(last) && new RegExp(`${last}\\s*=\\s*\\{[^;]*windowsHide`).test(src)) continue;
|
|
67
|
+
const line = src.slice(0, m.index).split('\n').length;
|
|
68
|
+
if (JS_ALLOW[`${rel}:${line}`]) continue;
|
|
69
|
+
bad.push(`${rel}:${line} ${m[1]}`);
|
|
70
|
+
}
|
|
71
|
+
return bad;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function scanRs(rel, src) {
|
|
75
|
+
if (RS_ALLOW[rel]) return [];
|
|
76
|
+
const cut = src.search(/#\[cfg\(test\)\]/);
|
|
77
|
+
const body = cut >= 0 ? src.slice(0, cut) : src;
|
|
78
|
+
const bad = [];
|
|
79
|
+
body.split('\n').forEach((ln, i) => {
|
|
80
|
+
if (/^\s*\/\//.test(ln)) return;
|
|
81
|
+
if (/Command::new\s*\(/.test(ln) && !/hidden_/.test(ln)) bad.push(`${rel}:${i + 1}`);
|
|
82
|
+
});
|
|
83
|
+
return bad;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
test('Node: every child_process call passes windowsHide', () => {
|
|
87
|
+
const files = JS_DIRS.flatMap((d) => walk(d, ['.js', '.cjs', '.mjs'])).filter((f) => !isGenerated(f));
|
|
88
|
+
const bad = files.flatMap((f) => scanJs(f, fs.readFileSync(path.join(ROOT, f), 'utf8')));
|
|
89
|
+
console.log(`node violations: ${bad.length}`);
|
|
90
|
+
assert.deepStrictEqual(bad, []);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
test('Rust: no raw Command::new in production code outside common/process.rs', () => {
|
|
94
|
+
const files = walk(RS_DIR, ['.rs']).filter((f) => !/(^|\/)tests?\.rs$|_tests?\.rs$|\/tests\//.test(f));
|
|
95
|
+
const bad = files.flatMap((f) => scanRs(f, fs.readFileSync(path.join(ROOT, f), 'utf8')));
|
|
96
|
+
console.log(`rust violations: ${bad.length}`);
|
|
97
|
+
assert.deepStrictEqual(bad, []);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// TASK_2478: no script-host autostart (antivirus flags schtasks ONLOGON + wscript + .vbs). The only allowed mentions
|
|
101
|
+
// are the migration cleanup of the old launcher files, marked `legacy-vbs-cleanup` on the same line.
|
|
102
|
+
test('Node: shipped JS neither runs wscript nor writes a .vbs (outside the marked migration cleanup)', () => {
|
|
103
|
+
const files = ['dashboard/scripts', 'packages/kenaz', 'plugins'].flatMap((d) => walk(d, ['.js', '.cjs', '.mjs'])).filter((f) => !isGenerated(f));
|
|
104
|
+
const bad = [];
|
|
105
|
+
for (const f of files) {
|
|
106
|
+
fs.readFileSync(path.join(ROOT, f), 'utf8').split('\n').forEach((ln, i) => {
|
|
107
|
+
if (/wscript|cscript|\.vbs\b/i.test(ln) && !ln.includes('legacy-vbs-cleanup')) bad.push(`${f}:${i + 1}`);
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
console.log(`script-host violations: ${bad.length}`);
|
|
111
|
+
assert.deepStrictEqual(bad, []);
|
|
112
|
+
});
|
|
@@ -2,5 +2,6 @@
|
|
|
2
2
|
- Code navigation: kenaz_lsp_callers / kenaz_lsp_references / kenaz_lsp_definition / kenaz_lsp_symbols (always pass projectPath). Text search: Grep/Glob.
|
|
3
3
|
- Collaboration: kenaz_peer_send / kenaz_peer_threads (other sessions, other machines, Codex), /kenaz ygg status|join.
|
|
4
4
|
- Rooms: when the user pastes a room key or asks to join/create a room, run `kenaz ygg join <key>` / `kenaz ygg create` yourself (never ask them to type it), then relay the status block and any "restart Claude Code" note.
|
|
5
|
+
- Reporting a Kenaz problem or idea: call kenaz_wish_create (scope kenaz) yourself; it uploads to the Kenaz mother (Alaya) automatically, no user step. Claude Code's SendFeedback tool and /feedback go to Anthropic, never to Kenaz.
|
|
5
6
|
- Reply in the user's language. Commands: /Ansuz, /Amelia, /review, /security, /incident, /spec.
|
|
6
7
|
- Switch: /kenaz off | assist | full (or env KENAZ_MODE). off disables every Kenaz hook.
|
|
@@ -221,7 +221,7 @@ if (require.main === module) {
|
|
|
221
221
|
if (!result) process.exit(0); // silent -- non-blocking hook
|
|
222
222
|
|
|
223
223
|
try {
|
|
224
|
-
execFileSync("node", [result.resolved, ...result.args], { stdio: "inherit" });
|
|
224
|
+
execFileSync("node", [result.resolved, ...result.args], { stdio: "inherit", windowsHide: true });
|
|
225
225
|
} catch {
|
|
226
226
|
// Hook errors should not block
|
|
227
227
|
}
|