kenaz 0.3.3 → 0.3.6
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/.agents/skills/typesafe-ai/LICENSE +21 -21
- package/core/.agents/skills/typesafe-ai/SKILL.md +149 -149
- package/core/.claude/commands/Ansuz.md +15 -2
- package/core/.claude/hooks/__tests__/task-2395-project-registration.test.js +84 -0
- package/core/.claude/hooks/handoff-staleness.js +2 -2
- package/core/.claude/hooks/session-init.ps1 +49 -49
- package/core/.claude/hooks/turn-context.js +50 -2
- package/core/.claude/skills/ui-ux-pro-max/data/charts.csv +26 -26
- package/core/.claude/skills/ui-ux-pro-max/data/colors.csv +97 -97
- package/core/.claude/skills/ui-ux-pro-max/data/icons.csv +101 -101
- package/core/.claude/skills/ui-ux-pro-max/data/landing.csv +31 -31
- package/core/.claude/skills/ui-ux-pro-max/data/products.csv +96 -96
- package/core/.claude/skills/ui-ux-pro-max/data/react-performance.csv +45 -45
- package/core/.claude/skills/ui-ux-pro-max/data/stacks/astro.csv +54 -54
- package/core/.claude/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -53
- package/core/.claude/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -56
- package/core/.claude/skills/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -53
- package/core/.claude/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -53
- package/core/.claude/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -51
- package/core/.claude/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -59
- package/core/.claude/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -52
- package/core/.claude/skills/ui-ux-pro-max/data/stacks/react.csv +54 -54
- package/core/.claude/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -61
- package/core/.claude/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -54
- package/core/.claude/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -51
- package/core/.claude/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -50
- package/core/.claude/skills/ui-ux-pro-max/data/styles.csv +68 -68
- package/core/.claude/skills/ui-ux-pro-max/data/typography.csv +57 -57
- package/core/.claude/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -101
- package/core/.claude/skills/ui-ux-pro-max/data/ux-guidelines.csv +99 -99
- package/core/.claude/skills/ui-ux-pro-max/data/web-interface.csv +31 -31
- package/core/.claude/skills/ui-ux-pro-max/scripts/core.py +253 -253
- package/core/.claude/skills/ui-ux-pro-max/scripts/design_system.py +1067 -1067
- package/core/.claude/skills/ui-ux-pro-max/scripts/search.py +106 -106
- package/core/.collaboration/core/task-api.js +1 -4
- package/core/.formation/README.md +21 -146
- package/core/.formation/bifrost/codex-doctor.js +37 -2
- package/core/.formation/bifrost/codex-doctor.test.js +18 -0
- package/core/.formation/bifrost/launch.js +1 -1
- package/core/.formation/bifrost/openai/codex-hook-shim.js +6 -0
- package/core/.formation/bifrost/openai/codex-hook-shim.test.js +11 -1
- package/core/.formation/bifrost/setup-codex.js +3 -0
- package/core/.formation/native/claude/README.md +1 -1
- package/core/.formation/role-map.yaml +3 -3
- package/core/.formation/spec/task_operations.parity.test.js +0 -1
- package/core/.formation/spec/task_operations.yaml +3 -3
- package/core/.formation/tests/hello.txt +2 -2
- package/core/.formation/tools/__tests__/subagent-bifrost-guard.test.js +4 -4
- package/core/.formation/tools/dashboard-models-chain.test.js +0 -6
- package/core/.formation/tools/dispatch-detail/cross-project-worktree.md +1 -9
- package/core/.formation/tools/dispatch-detail/worktree-subagent-mode.md +2 -2
- package/core/.formation/tools/dispatch.js +33 -554
- package/core/.formation/tools/mcp-allowlist.test.js +0 -1
- package/core/.formation/tools/post-complete/task2345.test.js +0 -5
- package/core/.formation/tools/pre-dispatch-snapshot.test.js +0 -100
- package/core/.formation/tools/prompt.js +33 -1623
- package/core/.formation/tools/prompt.test.js +26 -594
- package/core/.formation/unit/do.yaml +2 -4
- package/core/.kenaz/knowledge/ladybug_2c51da1e_shadow_file_frame_group.patch +163 -163
- package/core/.kenaz/knowledge/ladybug_30cf85690e_shadow_page_read_during_checkpoint.patch +393 -393
- package/core/.kenaz/knowledge/ladybug_7a17858d3a_node_group_delete_lock.patch +102 -102
- package/core/.kenaz/knowledge/ladybug_926a0ba1_column_checkpoint.patch +412 -412
- package/core/.kenaz/knowledge/ladybug_a346c4c4b6_pk_index_header_pages.patch +144 -144
- package/core/.kenaz/knowledge/ladybug_ba5f38815b_csr_node_group.patch +86 -86
- package/core/.kenaz/muninn_episode_write.ps1 +17 -17
- package/core/.kenaz/specialist/field_report_watermark.json +1 -1
- package/core/.kenaz/specialist/memory_guard_fired.json +1 -1
- package/core/.kenaz/specialist/memory_guard_trigger_cache.json +1 -1
- package/core/.kenaz/specialist/t1777_probe.txt +1 -1
- package/core/.matrix/index.matrix +5 -5
- package/core/.rule/general/agent-workflow.yaml +4 -4
- package/core/.rule/general/file-size-threshold.yaml +16 -4
- package/core/.rule/general/rust-verify-target.yaml +0 -1
- package/core/.rule/general/system-invariants.yaml +8 -25
- package/core/.specialist/Ansuz/SYSTEM_DOC.md +17 -42
- package/core/.specialist/Ansuz/capability.yaml +7 -14
- package/core/.specialist/Ansuz/concepts/formation_quick_ref.yaml +4 -11
- package/core/.specialist/Ansuz/elixir.yaml +3 -4
- package/core/.specialist/Ansuz/identity_contract.yaml +1 -1
- package/core/.specialist/Ansuz/knowledge.yaml +7 -10
- package/core/.specialist/Ansuz/rule.yaml +2 -2
- package/core/.specialist/Ansuz/tools/verify-and-land.js +22 -0
- package/core/.specialist/Ansuz/tools/verify-and-land.test.js +59 -5
- package/core/.specialist/Ansuz/workflow.yaml +7 -11
- package/core/.specialist/Forseti/core.yaml +1 -1
- package/core/.specialist/Heimdall/SKILL.md +1 -1
- package/core/.specialist/Heimdall/core.yaml +2 -2
- package/core/.specialist/Huginn/rule.yaml +1 -1
- package/core/.specialist/tools/README.md +2 -2
- package/core/.specialist/tools/__tests__/freya-cli-contract.test.js +0 -1
- package/core/.system/collaboration/README.md +1 -1
- package/core/.system/formation/LEGACY_SKILLS.md +2 -0
- package/core/.system/formation/POST_COMPLETE.md +2 -0
- package/core/.system/formation/README.md +2 -0
- package/core/KENAZ_CORE_VERSION +1 -1
- package/core/dev/ANSUZ_STARTUP_INJECTION_REVIEW.md +355 -355
- package/core/dev/JEV_INTEGRATION_PLAN.md +189 -189
- package/core/dev/design/matrix_format_EXAMPLE_memory.matrix +13 -13
- package/core/dev/design/matrix_format_EXAMPLE_project_status.matrix +9 -9
- package/core/dev/design/matrix_format_EXAMPLE_tasks.matrix +14 -14
- package/core/dev/design/matrix_v2_EXAMPLE.matrix +67 -67
- package/core/dev/jev-eval/ACTIVE_CORRECTION.md +52 -52
- package/core/dev/jev-eval/CONTEXT_REVIEW.md +31 -31
- package/core/dev/jev-eval/EVALUATION_STATUS.md +39 -39
- package/core/dev/jev-eval/HISTORICAL_CORPUS.md +33 -33
- package/core/dev/jev-eval/README.md +99 -99
- package/core/dev/jev-eval/THALAMUS_RANKING.md +58 -58
- package/core/dev/jev-eval/reports/annotation-pilot-2026-09-20.json +32 -32
- package/core/dev/jev-eval/reports/context-review-2026-09-20.json +48 -48
- package/core/dev/jev-eval/reports/history-corpus-2026-09-20.json +52 -52
- package/core/dev/pipeline/SELF_ENHANCEMENT_STATUS.json.bak +47 -47
- package/core/dev/pipeline/tasks/.gitkeep +1 -1
- package/core/dev/pipeline/test_results/TASK_TEST_PARALLEL_002_result.txt +27 -27
- package/core/dev/scripts/check-file-size.js +44 -17
- package/core/dev/scripts/init_git.sh +0 -0
- package/core/dev/scripts/init_project.sh +0 -0
- package/core/dev/scripts/legacy/dev_agent_scheduler.ps1.bak +536 -536
- package/core/dev/scripts/legacy/multi_agent_scheduler.ps1.bak +1978 -1978
- package/core/dev/scripts/matrix/src/cli/commands/list-tags.ts.wip +140 -140
- package/core/dev/scripts/matrix/src/cli/commands/manage-tags.ts.wip +173 -173
- package/core/dev/scripts/matrix/src/cli/commands/stats.ts.wip +168 -168
- package/core/dev/scripts/matrix/src/cli/commands/tokens.ts.wip +126 -126
- package/core/dev/scripts/multi_agent_scheduler.sh +0 -0
- package/core/dev/scripts/run_once.sh +0 -0
- package/core/dev/scripts/setup_mcp.sh +0 -0
- package/core/dev/scripts/setup_rag.sh +0 -0
- package/core/dev/scripts/start_dev_agent.sh +0 -0
- package/core/dev/scripts/start_multi_agent.sh +0 -0
- package/core/dev/scripts/sync_task_queue.sh +0 -0
- package/core/k-cli/README.md +1 -94
- package/core/k-cli/test/TEST_SPEC.md +5 -22
- package/core/k-cli/test/run.sh +1 -67
- package/core/plugins/kenaz/commands/Amelia.md +1 -1
- package/core/plugins/kenaz/commands/Ansuz.md +16 -3
- package/core/plugins/kenaz/scripts/kenaz-mode.js +11 -1
- package/core/plugins/kenaz/scripts/sync.js +6 -2
- package/core/plugins/kenaz/scripts/ygg.js +13 -1
- package/core/plugins/kenaz/skills/product_manager/SKILL.md +12 -12
- package/core/plugins/kenaz/skills/ui-ux-pro-max/data/charts.csv +26 -26
- package/core/plugins/kenaz/skills/ui-ux-pro-max/data/colors.csv +97 -97
- package/core/plugins/kenaz/skills/ui-ux-pro-max/data/icons.csv +101 -101
- package/core/plugins/kenaz/skills/ui-ux-pro-max/data/landing.csv +31 -31
- package/core/plugins/kenaz/skills/ui-ux-pro-max/data/products.csv +96 -96
- package/core/plugins/kenaz/skills/ui-ux-pro-max/data/react-performance.csv +45 -45
- package/core/plugins/kenaz/skills/ui-ux-pro-max/data/stacks/astro.csv +54 -54
- package/core/plugins/kenaz/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -53
- package/core/plugins/kenaz/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -56
- package/core/plugins/kenaz/skills/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -53
- package/core/plugins/kenaz/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -53
- package/core/plugins/kenaz/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -51
- package/core/plugins/kenaz/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -59
- package/core/plugins/kenaz/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -52
- package/core/plugins/kenaz/skills/ui-ux-pro-max/data/stacks/react.csv +54 -54
- package/core/plugins/kenaz/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -61
- package/core/plugins/kenaz/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -54
- package/core/plugins/kenaz/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -51
- package/core/plugins/kenaz/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -50
- package/core/plugins/kenaz/skills/ui-ux-pro-max/data/styles.csv +68 -68
- package/core/plugins/kenaz/skills/ui-ux-pro-max/data/typography.csv +57 -57
- package/core/plugins/kenaz/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -101
- package/core/plugins/kenaz/skills/ui-ux-pro-max/data/ux-guidelines.csv +99 -99
- package/core/plugins/kenaz/skills/ui-ux-pro-max/data/web-interface.csv +31 -31
- package/core/plugins/kenaz/skills/ui-ux-pro-max/scripts/core.py +253 -253
- package/core/plugins/kenaz/skills/ui-ux-pro-max/scripts/design_system.py +1067 -1067
- package/core/plugins/kenaz/skills/ui-ux-pro-max/scripts/search.py +106 -106
- package/lib/cli.js +11 -4
- package/package.json +11 -7
- package/vendor/install-kenaz-cli.js +18 -7
- package/core/.formation/legion/forge.yaml +0 -299
- package/core/.formation/legion/hive.yaml +0 -238
- package/core/.formation/squad/blitz.yaml +0 -192
- package/core/.formation/squad/strategy-tribunal.yaml +0 -354
- package/core/.formation/squad/strategy.yaml +0 -349
- package/core/.formation/squad/sweep.yaml +0 -208
- package/core/.formation/tools/broadcast.js +0 -103
- package/core/.formation/tools/dispatch-dryrun.test.js +0 -54
- package/core/.formation/tools/dispatch-notifier.js +0 -84
- package/core/.formation/tools/formations.js +0 -1203
- package/core/.formation/tools/headless-branch-recovery.test.js +0 -64
- package/core/.formation/tools/headless-dryrun.test.js +0 -79
- package/core/.formation/tools/headless-v2.js +0 -659
- package/core/.formation/tools/headless.js +0 -1071
- package/core/.formation/tools/legacy-scheduler.js +0 -1994
- package/core/.formation/tools/logger.js +0 -273
- package/core/.formation/tools/memory-loader.js +0 -422
- package/core/.formation/tools/process-state.js +0 -33
- package/core/.formation/tools/remote-conflict.js +0 -98
- package/core/.formation/tools/runner.js +0 -1332
- package/core/.formation/tools/task-utils.js +0 -344
- package/core/.formation/tools/task2028-headless-worktree.test.js +0 -112
- package/core/.formation/tools/tests/headless-mcp-args-plumbing.test.js +0 -123
- package/core/.formation/tools/worktree-leak.test.js +0 -162
- package/core/k-cli/dist/alaya/run.js +0 -91
- package/core/k-cli/dist/core/output.js +0 -24
- package/core/k-cli/dist/core/process.js +0 -38
- package/core/k-cli/dist/core/project.js +0 -80
- package/core/k-cli/dist/core/spawn.js +0 -268
- package/core/k-cli/dist/core/types.js +0 -2
- package/core/k-cli/dist/dashboard/update.js +0 -53
- package/core/k-cli/dist/dashboard/version.js +0 -20
- package/core/k-cli/dist/dispatch/run.js +0 -241
- package/core/k-cli/dist/dispatch/status.js +0 -103
- package/core/k-cli/dist/index.js +0 -283
- package/core/k-cli/dist/project/initialize.js +0 -301
- package/core/k-cli/dist/project/install.js +0 -89
- package/core/k-cli/dist/project/status.js +0 -138
- package/core/k-cli/dist/specialist/list.js +0 -100
- package/core/k-cli/dist/specialist/run.js +0 -93
- package/core/k-cli/dist/task/create.js +0 -194
- package/core/k-cli/dist/task/delete.js +0 -98
- package/core/k-cli/dist/task/get.js +0 -55
- package/core/k-cli/dist/task/list.js +0 -58
- package/core/k-cli/dist/task/submit.js +0 -156
- package/core/k-cli/dist/ygg/run.js +0 -51
- package/core/k-cli/node_modules/.bin/yaml +0 -16
- package/core/k-cli/node_modules/.bin/yaml.cmd +0 -17
- package/core/k-cli/node_modules/.bin/yaml.ps1 +0 -28
- package/core/k-cli/node_modules/.package-lock.json +0 -23
- package/core/k-cli/node_modules/yaml/LICENSE +0 -13
- package/core/k-cli/node_modules/yaml/README.md +0 -172
- package/core/k-cli/node_modules/yaml/bin.mjs +0 -11
- package/core/k-cli/node_modules/yaml/browser/dist/compose/compose-collection.js +0 -88
- package/core/k-cli/node_modules/yaml/browser/dist/compose/compose-doc.js +0 -43
- package/core/k-cli/node_modules/yaml/browser/dist/compose/compose-node.js +0 -109
- package/core/k-cli/node_modules/yaml/browser/dist/compose/compose-scalar.js +0 -86
- package/core/k-cli/node_modules/yaml/browser/dist/compose/composer.js +0 -217
- package/core/k-cli/node_modules/yaml/browser/dist/compose/resolve-block-map.js +0 -115
- package/core/k-cli/node_modules/yaml/browser/dist/compose/resolve-block-scalar.js +0 -198
- package/core/k-cli/node_modules/yaml/browser/dist/compose/resolve-block-seq.js +0 -49
- package/core/k-cli/node_modules/yaml/browser/dist/compose/resolve-end.js +0 -37
- package/core/k-cli/node_modules/yaml/browser/dist/compose/resolve-flow-collection.js +0 -207
- package/core/k-cli/node_modules/yaml/browser/dist/compose/resolve-flow-scalar.js +0 -223
- package/core/k-cli/node_modules/yaml/browser/dist/compose/resolve-props.js +0 -146
- package/core/k-cli/node_modules/yaml/browser/dist/compose/util-contains-newline.js +0 -34
- package/core/k-cli/node_modules/yaml/browser/dist/compose/util-empty-scalar-position.js +0 -26
- package/core/k-cli/node_modules/yaml/browser/dist/compose/util-flow-indent-check.js +0 -15
- package/core/k-cli/node_modules/yaml/browser/dist/compose/util-map-includes.js +0 -13
- package/core/k-cli/node_modules/yaml/browser/dist/doc/Document.js +0 -335
- package/core/k-cli/node_modules/yaml/browser/dist/doc/anchors.js +0 -71
- package/core/k-cli/node_modules/yaml/browser/dist/doc/applyReviver.js +0 -55
- package/core/k-cli/node_modules/yaml/browser/dist/doc/createNode.js +0 -88
- package/core/k-cli/node_modules/yaml/browser/dist/doc/directives.js +0 -176
- package/core/k-cli/node_modules/yaml/browser/dist/errors.js +0 -57
- package/core/k-cli/node_modules/yaml/browser/dist/index.js +0 -17
- package/core/k-cli/node_modules/yaml/browser/dist/log.js +0 -11
- package/core/k-cli/node_modules/yaml/browser/dist/nodes/Alias.js +0 -114
- package/core/k-cli/node_modules/yaml/browser/dist/nodes/Collection.js +0 -147
- package/core/k-cli/node_modules/yaml/browser/dist/nodes/Node.js +0 -38
- package/core/k-cli/node_modules/yaml/browser/dist/nodes/Pair.js +0 -36
- package/core/k-cli/node_modules/yaml/browser/dist/nodes/Scalar.js +0 -24
- package/core/k-cli/node_modules/yaml/browser/dist/nodes/YAMLMap.js +0 -144
- package/core/k-cli/node_modules/yaml/browser/dist/nodes/YAMLSeq.js +0 -113
- package/core/k-cli/node_modules/yaml/browser/dist/nodes/addPairToJSMap.js +0 -63
- package/core/k-cli/node_modules/yaml/browser/dist/nodes/identity.js +0 -36
- package/core/k-cli/node_modules/yaml/browser/dist/nodes/toJS.js +0 -37
- package/core/k-cli/node_modules/yaml/browser/dist/parse/cst-scalar.js +0 -214
- package/core/k-cli/node_modules/yaml/browser/dist/parse/cst-stringify.js +0 -61
- package/core/k-cli/node_modules/yaml/browser/dist/parse/cst-visit.js +0 -97
- package/core/k-cli/node_modules/yaml/browser/dist/parse/cst.js +0 -98
- package/core/k-cli/node_modules/yaml/browser/dist/parse/lexer.js +0 -717
- package/core/k-cli/node_modules/yaml/browser/dist/parse/line-counter.js +0 -39
- package/core/k-cli/node_modules/yaml/browser/dist/parse/parser.js +0 -967
- package/core/k-cli/node_modules/yaml/browser/dist/public-api.js +0 -102
- package/core/k-cli/node_modules/yaml/browser/dist/schema/Schema.js +0 -37
- package/core/k-cli/node_modules/yaml/browser/dist/schema/common/map.js +0 -17
- package/core/k-cli/node_modules/yaml/browser/dist/schema/common/null.js +0 -15
- package/core/k-cli/node_modules/yaml/browser/dist/schema/common/seq.js +0 -17
- package/core/k-cli/node_modules/yaml/browser/dist/schema/common/string.js +0 -14
- package/core/k-cli/node_modules/yaml/browser/dist/schema/core/bool.js +0 -19
- package/core/k-cli/node_modules/yaml/browser/dist/schema/core/float.js +0 -43
- package/core/k-cli/node_modules/yaml/browser/dist/schema/core/int.js +0 -38
- package/core/k-cli/node_modules/yaml/browser/dist/schema/core/schema.js +0 -23
- package/core/k-cli/node_modules/yaml/browser/dist/schema/json/schema.js +0 -62
- package/core/k-cli/node_modules/yaml/browser/dist/schema/tags.js +0 -96
- package/core/k-cli/node_modules/yaml/browser/dist/schema/yaml-1.1/binary.js +0 -58
- package/core/k-cli/node_modules/yaml/browser/dist/schema/yaml-1.1/bool.js +0 -26
- package/core/k-cli/node_modules/yaml/browser/dist/schema/yaml-1.1/float.js +0 -46
- package/core/k-cli/node_modules/yaml/browser/dist/schema/yaml-1.1/int.js +0 -71
- package/core/k-cli/node_modules/yaml/browser/dist/schema/yaml-1.1/merge.js +0 -64
- package/core/k-cli/node_modules/yaml/browser/dist/schema/yaml-1.1/omap.js +0 -74
- package/core/k-cli/node_modules/yaml/browser/dist/schema/yaml-1.1/pairs.js +0 -78
- package/core/k-cli/node_modules/yaml/browser/dist/schema/yaml-1.1/schema.js +0 -39
- package/core/k-cli/node_modules/yaml/browser/dist/schema/yaml-1.1/set.js +0 -93
- package/core/k-cli/node_modules/yaml/browser/dist/schema/yaml-1.1/timestamp.js +0 -101
- package/core/k-cli/node_modules/yaml/browser/dist/stringify/foldFlowLines.js +0 -146
- package/core/k-cli/node_modules/yaml/browser/dist/stringify/stringify.js +0 -129
- package/core/k-cli/node_modules/yaml/browser/dist/stringify/stringifyCollection.js +0 -153
- package/core/k-cli/node_modules/yaml/browser/dist/stringify/stringifyComment.js +0 -20
- package/core/k-cli/node_modules/yaml/browser/dist/stringify/stringifyDocument.js +0 -85
- package/core/k-cli/node_modules/yaml/browser/dist/stringify/stringifyNumber.js +0 -24
- package/core/k-cli/node_modules/yaml/browser/dist/stringify/stringifyPair.js +0 -150
- package/core/k-cli/node_modules/yaml/browser/dist/stringify/stringifyString.js +0 -336
- package/core/k-cli/node_modules/yaml/browser/dist/util.js +0 -11
- package/core/k-cli/node_modules/yaml/browser/dist/visit.js +0 -233
- package/core/k-cli/node_modules/yaml/browser/index.js +0 -5
- package/core/k-cli/node_modules/yaml/browser/package.json +0 -3
- package/core/k-cli/node_modules/yaml/dist/cli.d.ts +0 -8
- package/core/k-cli/node_modules/yaml/dist/cli.mjs +0 -201
- package/core/k-cli/node_modules/yaml/dist/compose/compose-collection.d.ts +0 -11
- package/core/k-cli/node_modules/yaml/dist/compose/compose-collection.js +0 -90
- package/core/k-cli/node_modules/yaml/dist/compose/compose-doc.d.ts +0 -7
- package/core/k-cli/node_modules/yaml/dist/compose/compose-doc.js +0 -45
- package/core/k-cli/node_modules/yaml/dist/compose/compose-node.d.ts +0 -29
- package/core/k-cli/node_modules/yaml/dist/compose/compose-node.js +0 -112
- package/core/k-cli/node_modules/yaml/dist/compose/compose-scalar.d.ts +0 -5
- package/core/k-cli/node_modules/yaml/dist/compose/compose-scalar.js +0 -88
- package/core/k-cli/node_modules/yaml/dist/compose/composer.d.ts +0 -63
- package/core/k-cli/node_modules/yaml/dist/compose/composer.js +0 -222
- package/core/k-cli/node_modules/yaml/dist/compose/resolve-block-map.d.ts +0 -6
- package/core/k-cli/node_modules/yaml/dist/compose/resolve-block-map.js +0 -117
- package/core/k-cli/node_modules/yaml/dist/compose/resolve-block-scalar.d.ts +0 -11
- package/core/k-cli/node_modules/yaml/dist/compose/resolve-block-scalar.js +0 -200
- package/core/k-cli/node_modules/yaml/dist/compose/resolve-block-seq.d.ts +0 -6
- package/core/k-cli/node_modules/yaml/dist/compose/resolve-block-seq.js +0 -51
- package/core/k-cli/node_modules/yaml/dist/compose/resolve-end.d.ts +0 -6
- package/core/k-cli/node_modules/yaml/dist/compose/resolve-end.js +0 -39
- package/core/k-cli/node_modules/yaml/dist/compose/resolve-flow-collection.d.ts +0 -7
- package/core/k-cli/node_modules/yaml/dist/compose/resolve-flow-collection.js +0 -209
- package/core/k-cli/node_modules/yaml/dist/compose/resolve-flow-scalar.d.ts +0 -10
- package/core/k-cli/node_modules/yaml/dist/compose/resolve-flow-scalar.js +0 -225
- package/core/k-cli/node_modules/yaml/dist/compose/resolve-props.d.ts +0 -23
- package/core/k-cli/node_modules/yaml/dist/compose/resolve-props.js +0 -148
- package/core/k-cli/node_modules/yaml/dist/compose/util-contains-newline.d.ts +0 -2
- package/core/k-cli/node_modules/yaml/dist/compose/util-contains-newline.js +0 -36
- package/core/k-cli/node_modules/yaml/dist/compose/util-empty-scalar-position.d.ts +0 -2
- package/core/k-cli/node_modules/yaml/dist/compose/util-empty-scalar-position.js +0 -28
- package/core/k-cli/node_modules/yaml/dist/compose/util-flow-indent-check.d.ts +0 -3
- package/core/k-cli/node_modules/yaml/dist/compose/util-flow-indent-check.js +0 -17
- package/core/k-cli/node_modules/yaml/dist/compose/util-map-includes.d.ts +0 -4
- package/core/k-cli/node_modules/yaml/dist/compose/util-map-includes.js +0 -15
- package/core/k-cli/node_modules/yaml/dist/doc/Document.d.ts +0 -141
- package/core/k-cli/node_modules/yaml/dist/doc/Document.js +0 -337
- package/core/k-cli/node_modules/yaml/dist/doc/anchors.d.ts +0 -24
- package/core/k-cli/node_modules/yaml/dist/doc/anchors.js +0 -76
- package/core/k-cli/node_modules/yaml/dist/doc/applyReviver.d.ts +0 -9
- package/core/k-cli/node_modules/yaml/dist/doc/applyReviver.js +0 -57
- package/core/k-cli/node_modules/yaml/dist/doc/createNode.d.ts +0 -17
- package/core/k-cli/node_modules/yaml/dist/doc/createNode.js +0 -90
- package/core/k-cli/node_modules/yaml/dist/doc/directives.d.ts +0 -49
- package/core/k-cli/node_modules/yaml/dist/doc/directives.js +0 -178
- package/core/k-cli/node_modules/yaml/dist/errors.d.ts +0 -21
- package/core/k-cli/node_modules/yaml/dist/errors.js +0 -62
- package/core/k-cli/node_modules/yaml/dist/index.d.ts +0 -25
- package/core/k-cli/node_modules/yaml/dist/index.js +0 -50
- package/core/k-cli/node_modules/yaml/dist/log.d.ts +0 -3
- package/core/k-cli/node_modules/yaml/dist/log.js +0 -19
- package/core/k-cli/node_modules/yaml/dist/nodes/Alias.d.ts +0 -29
- package/core/k-cli/node_modules/yaml/dist/nodes/Alias.js +0 -116
- package/core/k-cli/node_modules/yaml/dist/nodes/Collection.d.ts +0 -73
- package/core/k-cli/node_modules/yaml/dist/nodes/Collection.js +0 -151
- package/core/k-cli/node_modules/yaml/dist/nodes/Node.d.ts +0 -53
- package/core/k-cli/node_modules/yaml/dist/nodes/Node.js +0 -40
- package/core/k-cli/node_modules/yaml/dist/nodes/Pair.d.ts +0 -22
- package/core/k-cli/node_modules/yaml/dist/nodes/Pair.js +0 -39
- package/core/k-cli/node_modules/yaml/dist/nodes/Scalar.d.ts +0 -43
- package/core/k-cli/node_modules/yaml/dist/nodes/Scalar.js +0 -27
- package/core/k-cli/node_modules/yaml/dist/nodes/YAMLMap.d.ts +0 -53
- package/core/k-cli/node_modules/yaml/dist/nodes/YAMLMap.js +0 -147
- package/core/k-cli/node_modules/yaml/dist/nodes/YAMLSeq.d.ts +0 -60
- package/core/k-cli/node_modules/yaml/dist/nodes/YAMLSeq.js +0 -115
- package/core/k-cli/node_modules/yaml/dist/nodes/addPairToJSMap.d.ts +0 -4
- package/core/k-cli/node_modules/yaml/dist/nodes/addPairToJSMap.js +0 -65
- package/core/k-cli/node_modules/yaml/dist/nodes/identity.d.ts +0 -23
- package/core/k-cli/node_modules/yaml/dist/nodes/identity.js +0 -53
- package/core/k-cli/node_modules/yaml/dist/nodes/toJS.d.ts +0 -29
- package/core/k-cli/node_modules/yaml/dist/nodes/toJS.js +0 -39
- package/core/k-cli/node_modules/yaml/dist/options.d.ts +0 -350
- package/core/k-cli/node_modules/yaml/dist/parse/cst-scalar.d.ts +0 -64
- package/core/k-cli/node_modules/yaml/dist/parse/cst-scalar.js +0 -218
- package/core/k-cli/node_modules/yaml/dist/parse/cst-stringify.d.ts +0 -8
- package/core/k-cli/node_modules/yaml/dist/parse/cst-stringify.js +0 -63
- package/core/k-cli/node_modules/yaml/dist/parse/cst-visit.d.ts +0 -39
- package/core/k-cli/node_modules/yaml/dist/parse/cst-visit.js +0 -99
- package/core/k-cli/node_modules/yaml/dist/parse/cst.d.ts +0 -109
- package/core/k-cli/node_modules/yaml/dist/parse/cst.js +0 -112
- package/core/k-cli/node_modules/yaml/dist/parse/lexer.d.ts +0 -87
- package/core/k-cli/node_modules/yaml/dist/parse/lexer.js +0 -719
- package/core/k-cli/node_modules/yaml/dist/parse/line-counter.d.ts +0 -22
- package/core/k-cli/node_modules/yaml/dist/parse/line-counter.js +0 -41
- package/core/k-cli/node_modules/yaml/dist/parse/parser.d.ts +0 -84
- package/core/k-cli/node_modules/yaml/dist/parse/parser.js +0 -972
- package/core/k-cli/node_modules/yaml/dist/public-api.d.ts +0 -44
- package/core/k-cli/node_modules/yaml/dist/public-api.js +0 -107
- package/core/k-cli/node_modules/yaml/dist/schema/Schema.d.ts +0 -17
- package/core/k-cli/node_modules/yaml/dist/schema/Schema.js +0 -39
- package/core/k-cli/node_modules/yaml/dist/schema/common/map.d.ts +0 -2
- package/core/k-cli/node_modules/yaml/dist/schema/common/map.js +0 -19
- package/core/k-cli/node_modules/yaml/dist/schema/common/null.d.ts +0 -4
- package/core/k-cli/node_modules/yaml/dist/schema/common/null.js +0 -17
- package/core/k-cli/node_modules/yaml/dist/schema/common/seq.d.ts +0 -2
- package/core/k-cli/node_modules/yaml/dist/schema/common/seq.js +0 -19
- package/core/k-cli/node_modules/yaml/dist/schema/common/string.d.ts +0 -2
- package/core/k-cli/node_modules/yaml/dist/schema/common/string.js +0 -16
- package/core/k-cli/node_modules/yaml/dist/schema/core/bool.d.ts +0 -4
- package/core/k-cli/node_modules/yaml/dist/schema/core/bool.js +0 -21
- package/core/k-cli/node_modules/yaml/dist/schema/core/float.d.ts +0 -4
- package/core/k-cli/node_modules/yaml/dist/schema/core/float.js +0 -47
- package/core/k-cli/node_modules/yaml/dist/schema/core/int.d.ts +0 -4
- package/core/k-cli/node_modules/yaml/dist/schema/core/int.js +0 -42
- package/core/k-cli/node_modules/yaml/dist/schema/core/schema.d.ts +0 -1
- package/core/k-cli/node_modules/yaml/dist/schema/core/schema.js +0 -25
- package/core/k-cli/node_modules/yaml/dist/schema/json/schema.d.ts +0 -2
- package/core/k-cli/node_modules/yaml/dist/schema/json/schema.js +0 -64
- package/core/k-cli/node_modules/yaml/dist/schema/json-schema.d.ts +0 -69
- package/core/k-cli/node_modules/yaml/dist/schema/tags.d.ts +0 -48
- package/core/k-cli/node_modules/yaml/dist/schema/tags.js +0 -99
- package/core/k-cli/node_modules/yaml/dist/schema/types.d.ts +0 -92
- package/core/k-cli/node_modules/yaml/dist/schema/yaml-1.1/binary.d.ts +0 -2
- package/core/k-cli/node_modules/yaml/dist/schema/yaml-1.1/binary.js +0 -70
- package/core/k-cli/node_modules/yaml/dist/schema/yaml-1.1/bool.d.ts +0 -7
- package/core/k-cli/node_modules/yaml/dist/schema/yaml-1.1/bool.js +0 -29
- package/core/k-cli/node_modules/yaml/dist/schema/yaml-1.1/float.d.ts +0 -4
- package/core/k-cli/node_modules/yaml/dist/schema/yaml-1.1/float.js +0 -50
- package/core/k-cli/node_modules/yaml/dist/schema/yaml-1.1/int.d.ts +0 -5
- package/core/k-cli/node_modules/yaml/dist/schema/yaml-1.1/int.js +0 -76
- package/core/k-cli/node_modules/yaml/dist/schema/yaml-1.1/merge.d.ts +0 -9
- package/core/k-cli/node_modules/yaml/dist/schema/yaml-1.1/merge.js +0 -68
- package/core/k-cli/node_modules/yaml/dist/schema/yaml-1.1/omap.d.ts +0 -22
- package/core/k-cli/node_modules/yaml/dist/schema/yaml-1.1/omap.js +0 -77
- package/core/k-cli/node_modules/yaml/dist/schema/yaml-1.1/pairs.d.ts +0 -10
- package/core/k-cli/node_modules/yaml/dist/schema/yaml-1.1/pairs.js +0 -82
- package/core/k-cli/node_modules/yaml/dist/schema/yaml-1.1/schema.d.ts +0 -1
- package/core/k-cli/node_modules/yaml/dist/schema/yaml-1.1/schema.js +0 -41
- package/core/k-cli/node_modules/yaml/dist/schema/yaml-1.1/set.d.ts +0 -28
- package/core/k-cli/node_modules/yaml/dist/schema/yaml-1.1/set.js +0 -96
- package/core/k-cli/node_modules/yaml/dist/schema/yaml-1.1/timestamp.d.ts +0 -6
- package/core/k-cli/node_modules/yaml/dist/schema/yaml-1.1/timestamp.js +0 -105
- package/core/k-cli/node_modules/yaml/dist/stringify/foldFlowLines.d.ts +0 -34
- package/core/k-cli/node_modules/yaml/dist/stringify/foldFlowLines.js +0 -151
- package/core/k-cli/node_modules/yaml/dist/stringify/stringify.d.ts +0 -21
- package/core/k-cli/node_modules/yaml/dist/stringify/stringify.js +0 -132
- package/core/k-cli/node_modules/yaml/dist/stringify/stringifyCollection.d.ts +0 -17
- package/core/k-cli/node_modules/yaml/dist/stringify/stringifyCollection.js +0 -155
- package/core/k-cli/node_modules/yaml/dist/stringify/stringifyComment.d.ts +0 -10
- package/core/k-cli/node_modules/yaml/dist/stringify/stringifyComment.js +0 -24
- package/core/k-cli/node_modules/yaml/dist/stringify/stringifyDocument.d.ts +0 -4
- package/core/k-cli/node_modules/yaml/dist/stringify/stringifyDocument.js +0 -87
- package/core/k-cli/node_modules/yaml/dist/stringify/stringifyNumber.d.ts +0 -2
- package/core/k-cli/node_modules/yaml/dist/stringify/stringifyNumber.js +0 -26
- package/core/k-cli/node_modules/yaml/dist/stringify/stringifyPair.d.ts +0 -3
- package/core/k-cli/node_modules/yaml/dist/stringify/stringifyPair.js +0 -152
- package/core/k-cli/node_modules/yaml/dist/stringify/stringifyString.d.ts +0 -9
- package/core/k-cli/node_modules/yaml/dist/stringify/stringifyString.js +0 -338
- package/core/k-cli/node_modules/yaml/dist/test-events.d.ts +0 -4
- package/core/k-cli/node_modules/yaml/dist/test-events.js +0 -134
- package/core/k-cli/node_modules/yaml/dist/util.d.ts +0 -16
- package/core/k-cli/node_modules/yaml/dist/util.js +0 -28
- package/core/k-cli/node_modules/yaml/dist/visit.d.ts +0 -102
- package/core/k-cli/node_modules/yaml/dist/visit.js +0 -236
- package/core/k-cli/node_modules/yaml/package.json +0 -97
- package/core/k-cli/node_modules/yaml/util.js +0 -2
|
@@ -1,344 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
/**
|
|
3
|
-
* Task Utilities
|
|
4
|
-
*
|
|
5
|
-
* Task management helpers extracted from headless.js.
|
|
6
|
-
*
|
|
7
|
-
* Exports: FIX_QUEUE_FILE, checkAndDispatchFix, checkTaskDependencies,
|
|
8
|
-
* recoverStaleTasks, findNextTask
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
const fs = require('fs');
|
|
12
|
-
const path = require('path');
|
|
13
|
-
const { ROOT } = require('./utils');
|
|
14
|
-
const { readActiveDispatches } = require('./dispatch-registry');
|
|
15
|
-
|
|
16
|
-
// ─────────────────────────────────────────
|
|
17
|
-
// FIX queue — 閉環自動 re-dispatch
|
|
18
|
-
// ─────────────────────────────────────────
|
|
19
|
-
|
|
20
|
-
const FIX_QUEUE_FILE = path.join(ROOT, '.formation', '.fix-queue.json');
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* 檢查 post-complete 是否建立了 FIX 任務,若有則自動 re-dispatch。
|
|
24
|
-
* 讀取後立即刪除 queue 檔 — 防止無限遞迴。
|
|
25
|
-
*/
|
|
26
|
-
function checkAndDispatchFix({ formation, skill, projectPath }) {
|
|
27
|
-
try {
|
|
28
|
-
if (!fs.existsSync(FIX_QUEUE_FILE)) return;
|
|
29
|
-
const queue = JSON.parse(fs.readFileSync(FIX_QUEUE_FILE, 'utf-8'));
|
|
30
|
-
fs.unlinkSync(FIX_QUEUE_FILE); // 消費 queue(atomic)
|
|
31
|
-
|
|
32
|
-
if (!queue.fixTaskId) return;
|
|
33
|
-
|
|
34
|
-
console.log(`\n🔄 Closed-loop: regression FIX detected — auto-dispatching ${queue.fixTaskId}`);
|
|
35
|
-
console.log(` Source: ${queue.sourceTaskId} → Fix: ${queue.fixTaskId}`);
|
|
36
|
-
|
|
37
|
-
// 使用 headless 自身的 main() 邏輯 re-dispatch
|
|
38
|
-
const { spawnSync: spawnS } = require('child_process');
|
|
39
|
-
const headlessPath = path.join(ROOT, '.formation', 'tools', 'headless.js');
|
|
40
|
-
spawnS('node', [
|
|
41
|
-
headlessPath,
|
|
42
|
-
`--formation=${formation}`,
|
|
43
|
-
`--skill=${skill}`,
|
|
44
|
-
`--task=${queue.fixTaskId}`,
|
|
45
|
-
...(projectPath ? [`--project-path=${projectPath}`] : []),
|
|
46
|
-
], {
|
|
47
|
-
cwd: ROOT,
|
|
48
|
-
stdio: 'inherit',
|
|
49
|
-
timeout: 600000, // 10 min max for FIX task
|
|
50
|
-
windowsHide: true,
|
|
51
|
-
});
|
|
52
|
-
} catch (err) {
|
|
53
|
-
console.log(` ⚠️ FIX auto-dispatch failed: ${err.message}`);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// ─────────────────────────────────────────
|
|
58
|
-
// 依賴預檢(與 dispatch.js 共用邏輯)
|
|
59
|
-
// ─────────────────────────────────────────
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* 檢查任務的依賴是否都已完成。
|
|
63
|
-
* @param {string} taskData - JSON 任務文本
|
|
64
|
-
* @param {string|null} projectPath - 子專案路徑
|
|
65
|
-
* @returns {{ blocked: boolean, unmet: string[] }}
|
|
66
|
-
*/
|
|
67
|
-
function checkTaskDependencies(taskData, projectPath) {
|
|
68
|
-
let deps = [];
|
|
69
|
-
try {
|
|
70
|
-
const parsed = JSON.parse(taskData);
|
|
71
|
-
deps = parsed.dependencies || [];
|
|
72
|
-
} catch {
|
|
73
|
-
const match = (taskData || '').match(/^dependencies:\s*\n((?:\s+-\s+\S+\n?)+)/m);
|
|
74
|
-
if (match) {
|
|
75
|
-
deps = match[1].split('\n').map(l => l.trim().replace(/^-\s*/, '')).filter(Boolean);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
if (deps.length === 0) return { blocked: false, unmet: [] };
|
|
79
|
-
|
|
80
|
-
const completedIds = new Set();
|
|
81
|
-
const blockedIds = new Set();
|
|
82
|
-
const scanDir = (dir, bucket) => {
|
|
83
|
-
if (!dir || !fs.existsSync(dir)) return;
|
|
84
|
-
try {
|
|
85
|
-
for (const f of fs.readdirSync(dir)) {
|
|
86
|
-
const m = f.match(/^(TASK_\d+)/); if (m) bucket.add(m[1]);
|
|
87
|
-
}
|
|
88
|
-
} catch { /* ignore */ }
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
const projectRoot = projectPath || ROOT;
|
|
92
|
-
// Scan BOTH task directories — KenazAI core has both .kenaz/tasks/ and .collaboration/tasks/
|
|
93
|
-
const kenazTasks = path.join(projectRoot, '.kenaz', 'tasks');
|
|
94
|
-
const collabTasks = path.join(projectRoot, '.collaboration', 'tasks');
|
|
95
|
-
|
|
96
|
-
scanDir(path.join(kenazTasks, 'done'), completedIds);
|
|
97
|
-
scanDir(path.join(kenazTasks, 'archived'), completedIds);
|
|
98
|
-
scanDir(path.join(collabTasks, 'done'), completedIds);
|
|
99
|
-
scanDir(path.join(collabTasks, 'archived'), completedIds);
|
|
100
|
-
scanDir(path.join(kenazTasks, 'blocked'), blockedIds);
|
|
101
|
-
scanDir(path.join(collabTasks, 'blocked'), blockedIds);
|
|
102
|
-
scanDir(path.join(projectRoot, 'dev', 'pipeline', 'completed'), completedIds);
|
|
103
|
-
|
|
104
|
-
// Only check deps that match TASK_\d+ format; skip descriptive text
|
|
105
|
-
const blockedDeps = deps.filter(dep => {
|
|
106
|
-
const taskId = dep.match(/TASK_\d+/)?.[0];
|
|
107
|
-
if (!taskId) return false;
|
|
108
|
-
return blockedIds.has(taskId);
|
|
109
|
-
});
|
|
110
|
-
const unmet = deps.filter(dep => {
|
|
111
|
-
const taskId = dep.match(/TASK_\d+/)?.[0];
|
|
112
|
-
if (!taskId) return false; // not a real task ID — skip
|
|
113
|
-
return !completedIds.has(taskId);
|
|
114
|
-
});
|
|
115
|
-
return { blocked: unmet.length > 0, unmet, blockedDeps };
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// ─────────────────────────────────────────
|
|
119
|
-
// Stale active-task recovery
|
|
120
|
-
// ─────────────────────────────────────────
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* 偵測卡在 active/ 但沒有對應 dispatch 的任務,自動 complete。
|
|
124
|
-
* 常見原因:互動對話 context 耗盡、手動中斷忘記收尾。
|
|
125
|
-
*
|
|
126
|
-
* 判定條件(全部滿足才觸發):
|
|
127
|
-
* 1. 任務檔在 active/ 目錄
|
|
128
|
-
* 2. claimed_at 超過 STALE_THRESHOLD_HOURS 小時
|
|
129
|
-
* 3. 沒有對應的 .active-dispatches.json 記錄
|
|
130
|
-
* 4. git log 有該任務的 commit(代表程式碼已完成)
|
|
131
|
-
*/
|
|
132
|
-
const STALE_THRESHOLD_HOURS = 2;
|
|
133
|
-
|
|
134
|
-
function recoverStaleTasks(projectPath) {
|
|
135
|
-
const pathMod = require('path');
|
|
136
|
-
const yamlLib = (() => { try { return require('js-yaml'); } catch { return require('../../.vendor/js-yaml.cjs'); } })();
|
|
137
|
-
|
|
138
|
-
const coreRoot = pathMod.resolve(__dirname, '../..');
|
|
139
|
-
const projectRoot = projectPath || coreRoot;
|
|
140
|
-
|
|
141
|
-
// Find active task directories
|
|
142
|
-
const activeDirs = [];
|
|
143
|
-
const kenazActive = pathMod.join(projectRoot, '.kenaz', 'tasks', 'active');
|
|
144
|
-
const collabActive = pathMod.join(projectRoot, '.collaboration', 'tasks', 'active');
|
|
145
|
-
if (fs.existsSync(kenazActive)) activeDirs.push(kenazActive);
|
|
146
|
-
if (fs.existsSync(collabActive)) activeDirs.push(collabActive);
|
|
147
|
-
if (activeDirs.length === 0) return;
|
|
148
|
-
|
|
149
|
-
// Currently running dispatches
|
|
150
|
-
const activeDispatches = readActiveDispatches();
|
|
151
|
-
const dispatchedTaskIds = new Set(activeDispatches.map(d => d.taskId));
|
|
152
|
-
|
|
153
|
-
const now = Date.now();
|
|
154
|
-
let recovered = 0;
|
|
155
|
-
|
|
156
|
-
for (const dir of activeDirs) {
|
|
157
|
-
const files = fs.readdirSync(dir).filter(f => f.endsWith('.yaml'));
|
|
158
|
-
for (const file of files) {
|
|
159
|
-
try {
|
|
160
|
-
const filePath = pathMod.join(dir, file);
|
|
161
|
-
const content = fs.readFileSync(filePath, 'utf-8');
|
|
162
|
-
const data = yamlLib.load(content);
|
|
163
|
-
if (!data || !data.id) continue;
|
|
164
|
-
|
|
165
|
-
// Skip if there's an active dispatch for this task
|
|
166
|
-
if (dispatchedTaskIds.has(data.id)) continue;
|
|
167
|
-
|
|
168
|
-
// Check if claimed_at is stale
|
|
169
|
-
const claimedAt = data.metadata?.claimed_at || data.assigned_to?.timestamp;
|
|
170
|
-
if (!claimedAt) continue;
|
|
171
|
-
const ageHours = (now - new Date(claimedAt).getTime()) / (1000 * 60 * 60);
|
|
172
|
-
if (ageHours < STALE_THRESHOLD_HOURS) continue;
|
|
173
|
-
|
|
174
|
-
// Check if git has a commit for this task (code was completed)
|
|
175
|
-
try {
|
|
176
|
-
const { execSync: es } = require('child_process');
|
|
177
|
-
const gitLog = es(`git log --oneline --all --grep="${data.id}" -1`, {
|
|
178
|
-
cwd: projectRoot, encoding: 'utf8', timeout: 5000, windowsHide: true,
|
|
179
|
-
}).trim();
|
|
180
|
-
if (!gitLog) continue; // No commit found — task may still be in progress manually
|
|
181
|
-
} catch {
|
|
182
|
-
continue;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
// All conditions met — auto-complete
|
|
186
|
-
console.log(`🔧 Stale task recovery: ${data.id} (active for ${ageHours.toFixed(1)}h, has commit, no dispatch)`);
|
|
187
|
-
try {
|
|
188
|
-
const { execSync: es } = require('child_process');
|
|
189
|
-
es(`node "${pathMod.join(coreRoot, '.collaboration', 'core', 'task-api.js')}" complete ${data.id} --by=system --git-user=auto-recovery --skip-post-complete`, {
|
|
190
|
-
cwd: coreRoot, encoding: 'utf8', timeout: 30000, stdio: 'pipe', windowsHide: true,
|
|
191
|
-
});
|
|
192
|
-
recovered++;
|
|
193
|
-
} catch (err) {
|
|
194
|
-
console.warn(` ⚠️ Recovery failed for ${data.id}: ${err.message}`);
|
|
195
|
-
}
|
|
196
|
-
} catch {
|
|
197
|
-
// skip invalid files
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
if (recovered > 0) {
|
|
203
|
-
console.log(`🔧 Recovered ${recovered} stale task(s)\n`);
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
// ─────────────────────────────────────────
|
|
208
|
-
// 自動尋找最高優先任務
|
|
209
|
-
// ─────────────────────────────────────────
|
|
210
|
-
|
|
211
|
-
/**
|
|
212
|
-
* 從 backlog 中找出最高優先級的任務
|
|
213
|
-
* 支援多專案:優先搜尋 projectPath 的 .kenaz/tasks/backlog/,
|
|
214
|
-
* 再 fallback 到 core 的 .collaboration/tasks/backlog/。
|
|
215
|
-
*
|
|
216
|
-
* @param {string} [projectPath] - 子專案路徑(可選)
|
|
217
|
-
* @returns {{ id: string, priority: number, idNum: number, title: string }|null}
|
|
218
|
-
*/
|
|
219
|
-
function findNextTask(projectPath) {
|
|
220
|
-
const fs = require('fs');
|
|
221
|
-
const pathMod = require('path');
|
|
222
|
-
const yamlLib = (() => { try { return require('js-yaml'); } catch { return require('../../.vendor/js-yaml.cjs'); } })();
|
|
223
|
-
|
|
224
|
-
const coreRoot = pathMod.resolve(__dirname, '../..');
|
|
225
|
-
|
|
226
|
-
// Build candidate backlog directories to scan
|
|
227
|
-
const backlogDirs = [];
|
|
228
|
-
if (projectPath) {
|
|
229
|
-
// All projects with projectPath: scan .kenaz/tasks/ first, then .collaboration/tasks/
|
|
230
|
-
backlogDirs.push(pathMod.join(projectPath, '.kenaz', 'tasks', 'backlog'));
|
|
231
|
-
backlogDirs.push(pathMod.join(projectPath, '.collaboration', 'tasks', 'backlog'));
|
|
232
|
-
} else {
|
|
233
|
-
// No projectPath: use core's .collaboration/tasks/
|
|
234
|
-
backlogDirs.push(pathMod.join(coreRoot, '.collaboration', 'tasks', 'backlog'));
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
// Find the first backlog dir that exists and has tasks
|
|
238
|
-
let backlogDir = null;
|
|
239
|
-
for (const dir of backlogDirs) {
|
|
240
|
-
if (fs.existsSync(dir)) {
|
|
241
|
-
const files = fs.readdirSync(dir).filter(f => f.endsWith('.yaml'));
|
|
242
|
-
if (files.length > 0) {
|
|
243
|
-
backlogDir = dir;
|
|
244
|
-
break;
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
if (!backlogDir) return null;
|
|
249
|
-
|
|
250
|
-
const files = fs.readdirSync(backlogDir).filter(f => f.endsWith('.yaml'));
|
|
251
|
-
if (files.length === 0) return null;
|
|
252
|
-
|
|
253
|
-
// Resolve the done dir relative to the same task root
|
|
254
|
-
const taskRoot = pathMod.resolve(backlogDir, '..');
|
|
255
|
-
const doneDir = pathMod.join(taskRoot, 'done');
|
|
256
|
-
|
|
257
|
-
const priorityOrder = { P0: 0, P1: 1, P2: 2, P3: 3 };
|
|
258
|
-
const tasks = [];
|
|
259
|
-
|
|
260
|
-
for (const file of files) {
|
|
261
|
-
try {
|
|
262
|
-
const content = fs.readFileSync(pathMod.join(backlogDir, file), 'utf-8');
|
|
263
|
-
const data = yamlLib.load(content);
|
|
264
|
-
if (!data || !data.id) continue;
|
|
265
|
-
|
|
266
|
-
// 跳過有未完成依賴的任務(done/ + archived/ 都算完成)
|
|
267
|
-
const deps = Array.isArray(data.dependencies) ? data.dependencies : (data.dependencies ? [data.dependencies] : []); // TASK_1771
|
|
268
|
-
if (deps.length > 0) {
|
|
269
|
-
const archivedDir = pathMod.join(taskRoot, 'archived');
|
|
270
|
-
const hasPendingDep = deps.some(dep => {
|
|
271
|
-
const doneFiles = fs.existsSync(doneDir) ? fs.readdirSync(doneDir) : [];
|
|
272
|
-
const archivedFiles = fs.existsSync(archivedDir) ? fs.readdirSync(archivedDir) : [];
|
|
273
|
-
return !doneFiles.some(f => f.startsWith(dep)) && !archivedFiles.some(f => f.startsWith(dep));
|
|
274
|
-
});
|
|
275
|
-
if (hasPendingDep) continue;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
const prio = priorityOrder[data.priority] ?? 99;
|
|
279
|
-
const idNum = parseInt((data.id.match(/\d+/) || [0])[0], 10);
|
|
280
|
-
tasks.push({ id: data.id, priority: prio, idNum, title: data.title });
|
|
281
|
-
} catch {
|
|
282
|
-
// skip invalid files
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
if (tasks.length === 0) return null;
|
|
287
|
-
|
|
288
|
-
// 排序: 優先級 asc, ID asc
|
|
289
|
-
tasks.sort((a, b) => a.priority - b.priority || a.idNum - b.idNum);
|
|
290
|
-
return tasks[0];
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
// ─────────────────────────────────────────
|
|
294
|
-
// Cross-project task verification
|
|
295
|
-
// ─────────────────────────────────────────
|
|
296
|
-
|
|
297
|
-
/**
|
|
298
|
-
* Verify that resolvedTask YAML exists inside the specified projectPath.
|
|
299
|
-
* Prevents cross-project dispatch errors (2026-03-17 incident: TASK_549 → wrong repo).
|
|
300
|
-
*
|
|
301
|
-
* Extracted from launch() in headless.js (TASK_891).
|
|
302
|
-
*
|
|
303
|
-
* @param {string|null} taskData - JSON task data (guard is skipped when null)
|
|
304
|
-
* @param {string} resolvedTask - Task ID (e.g. TASK_891)
|
|
305
|
-
* @param {string|null} projectPath - Sub-project path to search in
|
|
306
|
-
* @returns {boolean} true = valid (or guard not applicable), false = cross-project error
|
|
307
|
-
*/
|
|
308
|
-
function verifyTaskInProject(taskData, resolvedTask, projectPath) {
|
|
309
|
-
if (!taskData || !projectPath || !resolvedTask || !resolvedTask.startsWith('TASK_')) return true;
|
|
310
|
-
|
|
311
|
-
const taskDirs = ['.kenaz/tasks', '.collaboration/tasks'];
|
|
312
|
-
const statusDirs = ['active', 'backlog', 'done', 'blocked', 'todo', 'archived'];
|
|
313
|
-
let foundInProject = false;
|
|
314
|
-
for (const taskDir of taskDirs) {
|
|
315
|
-
for (const status of statusDirs) {
|
|
316
|
-
const dirPath = path.join(projectPath, taskDir, status);
|
|
317
|
-
if (!fs.existsSync(dirPath)) continue;
|
|
318
|
-
try {
|
|
319
|
-
const files = fs.readdirSync(dirPath);
|
|
320
|
-
if (files.some(f => f.startsWith(resolvedTask) && f.endsWith('.yaml'))) {
|
|
321
|
-
foundInProject = true;
|
|
322
|
-
break;
|
|
323
|
-
}
|
|
324
|
-
} catch { /* dir not readable — skip */ }
|
|
325
|
-
}
|
|
326
|
-
if (foundInProject) break;
|
|
327
|
-
}
|
|
328
|
-
if (!foundInProject) {
|
|
329
|
-
console.error(`❌ Task ${resolvedTask} not found in project ${projectPath}`);
|
|
330
|
-
console.error(` Searched: ${taskDirs.map(d => path.join(projectPath, d, '*/')).join(', ')}`);
|
|
331
|
-
console.error(` This may indicate a cross-project dispatch error. Aborting.`);
|
|
332
|
-
return false;
|
|
333
|
-
}
|
|
334
|
-
return true;
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
module.exports = {
|
|
338
|
-
FIX_QUEUE_FILE,
|
|
339
|
-
checkAndDispatchFix,
|
|
340
|
-
checkTaskDependencies,
|
|
341
|
-
recoverStaleTasks,
|
|
342
|
-
findNextTask,
|
|
343
|
-
verifyTaskInProject,
|
|
344
|
-
};
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
/**
|
|
3
|
-
* TASK_2028 follow-up — regression test for the REAL root cause of the stray
|
|
4
|
-
* .formation/worktrees/task_task_<id> worktrees observed on TASK_2025/2027.
|
|
5
|
-
*
|
|
6
|
-
* Pinned root cause (not the dangling-branch collision theory from the first
|
|
7
|
-
* TASK_2028 commit, which remains valid hardening but was not the trigger):
|
|
8
|
-
*
|
|
9
|
-
* post-complete/milestone.js's triggerHuginn(taskId, projectPath) fires
|
|
10
|
-
* every HUGINN_MILESTONE_INTERVAL (10) completions and spawns
|
|
11
|
-
* `headless.js --skill=huginn-think --trigger=milestone --task=<taskId>
|
|
12
|
-
* --skip-post-complete` so the trigger can be attributed back to the task
|
|
13
|
-
* that crossed the milestone. Because --task is set, headless.js's
|
|
14
|
-
* `isRealTask` guard was true, so `formations.setupUnitWorktree({taskId})`
|
|
15
|
-
* ran and created `.formation/worktrees/task_<id>` on branch `task/<id>`
|
|
16
|
-
* at HEAD -- BEFORE the `skill === 'huginn-think'` special route returned.
|
|
17
|
-
* That route calls formations.launchHuginnThink() directly and returns
|
|
18
|
-
* without ever using or cleaning the worktree it was just handed (it never
|
|
19
|
-
* reaches launchUnit's onDone cleanup), so the worktree/branch pair is
|
|
20
|
-
* orphaned every 10th completion. .prefrontal/milestone_counter.json
|
|
21
|
-
* showed count=610 with last_trigger matching the exact minute
|
|
22
|
-
* task_task_2027 appeared; TASK_2026 (count 609) did not trigger it.
|
|
23
|
-
*
|
|
24
|
-
* Fix: the huginn-think special route was moved ABOVE the worktree-setup
|
|
25
|
-
* block in headless.js's launch(), so setupUnitWorktree() is never called
|
|
26
|
-
* for skill=huginn-think regardless of whether --task is set. `observe`
|
|
27
|
-
* (Muninn's milestone-adjacent trigger) is unaffected -- it has no
|
|
28
|
-
* early-return route, so it flows through the normal launchUnit path and
|
|
29
|
-
* already receives the same onDone worktree cleanup as any other dispatch.
|
|
30
|
-
*
|
|
31
|
-
* This test drives the REAL CLI entry point as a child process (not an
|
|
32
|
-
* in-process require+call — headless.js's model-resolution helper is only
|
|
33
|
-
* defined inside its `if (require.main === module)` CLI block, so an
|
|
34
|
-
* in-process call would hit an unrelated pre-existing gap) with --dry-run,
|
|
35
|
-
* which formations.js's launchHuginnThink checks FIRST and returns before
|
|
36
|
-
* ever spawning a real claude session — matching the task's "no real claude
|
|
37
|
-
* launch" requirement — and --project-path pointed at a disposable temp git
|
|
38
|
-
* repo, so nothing under the real KenazAI repo is touched by the assertion
|
|
39
|
-
* itself (the huginn-think route reads/writes nothing there either way).
|
|
40
|
-
*
|
|
41
|
-
* Run: node --test .formation/tools/task2028-headless-worktree.test.js
|
|
42
|
-
*/
|
|
43
|
-
|
|
44
|
-
const test = require('node:test');
|
|
45
|
-
const assert = require('node:assert/strict');
|
|
46
|
-
const fs = require('fs');
|
|
47
|
-
const os = require('os');
|
|
48
|
-
const path = require('path');
|
|
49
|
-
const { execSync, execFileSync } = require('child_process');
|
|
50
|
-
|
|
51
|
-
function git(cmd, cwd) {
|
|
52
|
-
return execSync(cmd, { cwd, encoding: 'utf8', timeout: 20000, stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true }).trim();
|
|
53
|
-
}
|
|
54
|
-
function gitSafe(cmd, cwd) { try { return git(cmd, cwd); } catch { return null; } }
|
|
55
|
-
|
|
56
|
-
function makeFixtureRepo() {
|
|
57
|
-
const tmpRoot = fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(), 'tn2028hl-')));
|
|
58
|
-
const repo = path.join(tmpRoot, 'repo');
|
|
59
|
-
fs.mkdirSync(repo, { recursive: true });
|
|
60
|
-
git('git init -q', repo);
|
|
61
|
-
git('git config user.email "t2028hl@test.local"', repo);
|
|
62
|
-
git('git config user.name "T2028HL"', repo);
|
|
63
|
-
git('git config commit.gpgsign false', repo);
|
|
64
|
-
gitSafe('git checkout -q -b xyz9516', repo);
|
|
65
|
-
for (const d of ['backlog', 'active', 'done', 'blocked']) {
|
|
66
|
-
fs.mkdirSync(path.join(repo, '.kenaz', 'tasks', d), { recursive: true });
|
|
67
|
-
}
|
|
68
|
-
fs.writeFileSync(path.join(repo, 'README.md'), 'init\n');
|
|
69
|
-
git('git add -A', repo);
|
|
70
|
-
git('git commit -q --no-verify -m "init"', repo);
|
|
71
|
-
return { tmpRoot, repo };
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
test('TASK_2028 follow-up: headless.js does NOT create a worktree for skill=huginn-think with --task set', async () => {
|
|
75
|
-
const { tmpRoot, repo } = makeFixtureRepo();
|
|
76
|
-
try {
|
|
77
|
-
const headlessPath = path.join(__dirname, 'headless.js');
|
|
78
|
-
const args = [
|
|
79
|
-
headlessPath,
|
|
80
|
-
'--skill=huginn-think',
|
|
81
|
-
'--trigger=milestone',
|
|
82
|
-
'--task=TASK_9999', // mirrors milestone.js's triggerHuginn(taskId, projectPath)
|
|
83
|
-
`--project-path=${repo}`,
|
|
84
|
-
'--dry-run',
|
|
85
|
-
'--skip-post-complete',
|
|
86
|
-
];
|
|
87
|
-
|
|
88
|
-
let stdout = '';
|
|
89
|
-
let exitCode = 0;
|
|
90
|
-
try {
|
|
91
|
-
stdout = execFileSync(process.execPath, args, {
|
|
92
|
-
encoding: 'utf8', timeout: 60000, windowsHide: true, stdio: ['pipe', 'pipe', 'pipe'],
|
|
93
|
-
});
|
|
94
|
-
} catch (e) {
|
|
95
|
-
stdout = (e.stdout || '').toString();
|
|
96
|
-
exitCode = typeof e.status === 'number' ? e.status : 1;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
assert.match(stdout, /HUGINN THINK DRY RUN/,
|
|
100
|
-
'the huginn-think special route must still run (dry-run banner expected in stdout)');
|
|
101
|
-
assert.equal(exitCode, 0, `headless.js should exit 0 on a dry-run huginn-think dispatch; stdout:\n${stdout}`);
|
|
102
|
-
|
|
103
|
-
assert.equal(fs.existsSync(path.join(repo, '.formation', 'worktrees')), false,
|
|
104
|
-
'no .formation/worktrees/ directory should exist in the fixture repo after a huginn-think dispatch with --task set — this is exactly what leaked .formation/worktrees/task_task_<id> on every 10th real completion');
|
|
105
|
-
|
|
106
|
-
const branches = gitSafe('git branch -a', repo) || '';
|
|
107
|
-
assert.doesNotMatch(branches, /task\/task_9999/,
|
|
108
|
-
'no task/<id> branch should have been created for a huginn-think dispatch either');
|
|
109
|
-
} finally {
|
|
110
|
-
fs.rmSync(tmpRoot, { recursive: true, force: true });
|
|
111
|
-
}
|
|
112
|
-
});
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
// TASK_1929 (Agent Hub M2) — zero-regression + new-flag proof for the
|
|
2
|
-
// --mcp-config-extra / --allowed-tools plumbing added to headless.js /
|
|
3
|
-
// formations.js / runner.js.
|
|
4
|
-
//
|
|
5
|
-
// Runs the REAL headless.js as a child process (not `require`d in-process —
|
|
6
|
-
// spawnClaude calls `process.exit(0)` under the KENAZ_DEBUG_SPAWN_ARGS
|
|
7
|
-
// diagnostic, which would kill an in-process test runner). The diagnostic
|
|
8
|
-
// itself is the point: it exits BEFORE actually spawning `claude`/`node
|
|
9
|
-
// relay.js`, so this test costs zero API calls / zero codex invocations —
|
|
10
|
-
// see runner.js spawnClaude/spawnBifrost's "TASK_1929: opt-in, zero-cost
|
|
11
|
-
// args dump" comment.
|
|
12
|
-
//
|
|
13
|
-
// Run: node --test .formation/tools/tests/headless-mcp-args-plumbing.test.js
|
|
14
|
-
|
|
15
|
-
const { test } = require('node:test');
|
|
16
|
-
const assert = require('node:assert/strict');
|
|
17
|
-
const { spawnSync } = require('node:child_process');
|
|
18
|
-
const path = require('node:path');
|
|
19
|
-
const fs = require('node:fs');
|
|
20
|
-
const os = require('node:os');
|
|
21
|
-
|
|
22
|
-
const ROOT = path.resolve(__dirname, '..', '..', '..');
|
|
23
|
-
const HEADLESS_JS = path.join(ROOT, '.formation', 'tools', 'headless.js');
|
|
24
|
-
|
|
25
|
-
function runHeadless(extraArgs, scratchProject) {
|
|
26
|
-
const args = [
|
|
27
|
-
HEADLESS_JS,
|
|
28
|
-
'--formation=unit',
|
|
29
|
-
'--skill=do',
|
|
30
|
-
`--task=zero-regression check ${Math.random()}`,
|
|
31
|
-
`--project-path=${scratchProject}`,
|
|
32
|
-
'--skip-post-complete',
|
|
33
|
-
...extraArgs,
|
|
34
|
-
];
|
|
35
|
-
const result = spawnSync(process.execPath, args, {
|
|
36
|
-
cwd: ROOT,
|
|
37
|
-
// KENAZ_MAX_DISPATCHES: each KENAZ_DEBUG_SPAWN_ARGS run pre-registers a
|
|
38
|
-
// pid=null dispatch entry (headless.js's own "early dispatch
|
|
39
|
-
// registration") and then exits via process.exit(0) BEFORE ever
|
|
40
|
-
// spawning claude/reaching the normal unregister path — dispatch-
|
|
41
|
-
// registry.js's pruneZombieDispatches() only treats a pid=null entry as
|
|
42
|
-
// prunable once it's >30s old (PENDING_STALE_MS), so three of these
|
|
43
|
-
// tests run back-to-back (well under 30s apart) exhaust the default
|
|
44
|
-
// MAX_CONCURRENT_DISPATCHES=3 slot pool and waitForDispatchSlot() blocks
|
|
45
|
-
// for real (observed: hangs to the 30s spawnSync timeout below). This
|
|
46
|
-
// env var is the existing, documented escape hatch (dispatch-
|
|
47
|
-
// registry.js reads it) — raising it is a test-harness fix for an
|
|
48
|
-
// artifact of the debug diagnostic never registering a real PID, not a
|
|
49
|
-
// product bug.
|
|
50
|
-
env: { ...process.env, KENAZ_DEBUG_SPAWN_ARGS: '1', KENAZ_MAX_DISPATCHES: '1000' },
|
|
51
|
-
encoding: 'utf8',
|
|
52
|
-
timeout: 30_000,
|
|
53
|
-
});
|
|
54
|
-
assert.equal(result.status, 0, `headless.js exited non-zero: stderr=${result.stderr}`);
|
|
55
|
-
const jsonLine = result.stdout.trim().split('\n').filter(Boolean).pop();
|
|
56
|
-
let parsed;
|
|
57
|
-
try {
|
|
58
|
-
parsed = JSON.parse(jsonLine);
|
|
59
|
-
} catch (e) {
|
|
60
|
-
throw new Error(`last stdout line was not the args-dump JSON: ${jsonLine}\nfull stdout:\n${result.stdout}\nstderr:\n${result.stderr}`);
|
|
61
|
-
}
|
|
62
|
-
return parsed;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function makeScratchProject() {
|
|
66
|
-
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'kenaz-task1929-'));
|
|
67
|
-
return dir;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
test('baseline (no new flags): args carry no --mcp-config-extra path and no --allowedTools override', (t) => {
|
|
71
|
-
const scratch = makeScratchProject();
|
|
72
|
-
t.after(() => fs.rmSync(scratch, { recursive: true, force: true }));
|
|
73
|
-
|
|
74
|
-
const { cmd, args } = runHeadless([], scratch);
|
|
75
|
-
assert.ok(cmd.toLowerCase().includes('claude'), 'baseline (no --dispatch-model/--bifrost-adapter) must resolve to the native claude CLI');
|
|
76
|
-
|
|
77
|
-
// The exact default allowedTools list (unchanged shape) — this is the
|
|
78
|
-
// BEFORE-this-task behavior, still produced when no override is passed.
|
|
79
|
-
const idx = args.indexOf('--allowedTools');
|
|
80
|
-
assert.ok(idx !== -1);
|
|
81
|
-
assert.ok(args[idx + 1].startsWith('Bash,Read,Edit,Write,Glob,Grep,ToolSearch,mcp__kenaz-dashboard__kenaz_lsp_callers'));
|
|
82
|
-
|
|
83
|
-
const mcpIdx = args.indexOf('--mcp-config');
|
|
84
|
-
assert.ok(mcpIdx !== -1);
|
|
85
|
-
assert.ok(args[mcpIdx + 1].endsWith('.mcp.json'));
|
|
86
|
-
// Exactly one path follows --mcp-config (the core .mcp.json) — no extra
|
|
87
|
-
// path appended when --mcp-config-extra was never passed.
|
|
88
|
-
const afterMcpConfig = args.slice(mcpIdx + 1);
|
|
89
|
-
assert.equal(afterMcpConfig.length, 1, `expected exactly one --mcp-config value, got: ${JSON.stringify(afterMcpConfig)}`);
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
test('with --mcp-config-extra + --allowed-tools: both are threaded through additively', (t) => {
|
|
93
|
-
const scratch = makeScratchProject();
|
|
94
|
-
t.after(() => fs.rmSync(scratch, { recursive: true, force: true }));
|
|
95
|
-
|
|
96
|
-
const fakeMcpConfigPath = path.join(scratch, 'fake-mcp-config.json');
|
|
97
|
-
fs.writeFileSync(fakeMcpConfigPath, JSON.stringify({ mcpServers: {} }));
|
|
98
|
-
|
|
99
|
-
const { args } = runHeadless(
|
|
100
|
-
['--mcp-config-extra', fakeMcpConfigPath, '--allowed-tools', 'Read,Glob,Grep,mcp__flowpix'],
|
|
101
|
-
scratch
|
|
102
|
-
);
|
|
103
|
-
|
|
104
|
-
const allowedIdx = args.indexOf('--allowedTools');
|
|
105
|
-
assert.equal(args[allowedIdx + 1], 'Read,Glob,Grep,mcp__flowpix', 'allowedTools override must replace the default list verbatim');
|
|
106
|
-
|
|
107
|
-
const mcpIdx = args.indexOf('--mcp-config');
|
|
108
|
-
assert.ok(mcpIdx !== -1);
|
|
109
|
-
const afterMcpConfig = args.slice(mcpIdx + 1);
|
|
110
|
-
assert.equal(afterMcpConfig.length, 2, `expected core .mcp.json + the extra path, got: ${JSON.stringify(afterMcpConfig)}`);
|
|
111
|
-
assert.ok(afterMcpConfig[0].endsWith('.mcp.json'));
|
|
112
|
-
assert.equal(afterMcpConfig[1], fakeMcpConfigPath);
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
test('--dispatch-model routes through --model unchanged', (t) => {
|
|
116
|
-
const scratch = makeScratchProject();
|
|
117
|
-
t.after(() => fs.rmSync(scratch, { recursive: true, force: true }));
|
|
118
|
-
|
|
119
|
-
const { args } = runHeadless(['--dispatch-model', 'claude-sonnet-5'], scratch);
|
|
120
|
-
const idx = args.indexOf('--model');
|
|
121
|
-
assert.ok(idx !== -1);
|
|
122
|
-
assert.equal(args[idx + 1], 'claude-sonnet-5');
|
|
123
|
-
});
|