sneakoscope 4.8.6 → 5.1.2
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/README.md +51 -726
- package/bench/tasks/t01-off-by-one/repo/package.json +9 -0
- package/bench/tasks/t01-off-by-one/repo/src/pagination.js +5 -0
- package/bench/tasks/t01-off-by-one/repo/test.js +5 -0
- package/bench/tasks/t01-off-by-one/task.json +13 -0
- package/bench/tasks/t02-signature-cochange/repo/package.json +9 -0
- package/bench/tasks/t02-signature-cochange/repo/src/admin.js +5 -0
- package/bench/tasks/t02-signature-cochange/repo/src/audit.js +5 -0
- package/bench/tasks/t02-signature-cochange/repo/src/labels.js +3 -0
- package/bench/tasks/t02-signature-cochange/repo/src/profile.js +5 -0
- package/bench/tasks/t02-signature-cochange/repo/test.js +9 -0
- package/bench/tasks/t02-signature-cochange/task.json +12 -0
- package/bench/tasks/t03-type-puzzle/repo/package.json +9 -0
- package/bench/tasks/t03-type-puzzle/repo/src/config.js +4 -0
- package/bench/tasks/t03-type-puzzle/repo/test.js +6 -0
- package/bench/tasks/t03-type-puzzle/task.json +13 -0
- package/bench/tasks/t04-refactor-preserve/repo/package.json +9 -0
- package/bench/tasks/t04-refactor-preserve/repo/src/cart.js +8 -0
- package/bench/tasks/t04-refactor-preserve/repo/test.js +4 -0
- package/bench/tasks/t04-refactor-preserve/task.json +12 -0
- package/bench/tasks/t05-performance/repo/package.json +9 -0
- package/bench/tasks/t05-performance/repo/src/pairs.js +9 -0
- package/bench/tasks/t05-performance/repo/test.js +11 -0
- package/bench/tasks/t05-performance/task.json +12 -0
- package/bench/tasks/t06-mistake-rule/repo/package.json +9 -0
- package/bench/tasks/t06-mistake-rule/repo/src/loader.js +6 -0
- package/bench/tasks/t06-mistake-rule/repo/test.js +7 -0
- package/bench/tasks/t06-mistake-rule/task.json +12 -0
- package/config/bench-baseline.json +7 -0
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/crates/sks-core/src/main.rs +1 -1
- package/dist/bin/install.js +35 -0
- package/dist/bin/sks.js +1 -1
- package/dist/cli/cli-theme.js +51 -0
- package/dist/cli/command-registry.js +75 -42
- package/dist/cli/help-fast.js +18 -8
- package/dist/cli/insane-search-command.js +36 -8
- package/dist/cli/install-helpers.js +147 -47
- package/dist/cli/router.js +58 -2
- package/dist/commands/codex-lb.js +6 -4
- package/dist/commands/doctor.js +146 -8
- package/dist/commands/proof.js +6 -3
- package/dist/commands/zellij-monitor-pane.js +25 -0
- package/dist/commands/zellij-slot-pane.js +39 -2
- package/dist/commands/zellij-viewport-pane.js +56 -0
- package/dist/commands/zellij.js +55 -2
- package/dist/config/skills-manifest.json +493 -0
- package/dist/core/agents/agent-conflict-graph.js +5 -0
- package/dist/core/agents/agent-lease.js +5 -0
- package/dist/core/agents/agent-ledger-schemas.js +1 -0
- package/dist/core/agents/agent-lifecycle.js +86 -35
- package/dist/core/agents/agent-orchestrator.js +287 -72
- package/dist/core/agents/agent-output-validator.js +14 -3
- package/dist/core/agents/agent-patch-queue-store.js +108 -4
- package/dist/core/agents/agent-patch-queue.js +10 -3
- package/dist/core/agents/agent-patch-schema.js +13 -0
- package/dist/core/agents/agent-proof-evidence.js +6 -1
- package/dist/core/agents/agent-runner-fake.js +40 -0
- package/dist/core/agents/agent-scheduler.js +2 -3
- package/dist/core/agents/agent-worker-pipeline.js +36 -2
- package/dist/core/agents/codex-exec-worker-adapter.js +2 -0
- package/dist/core/agents/native-cli-session-swarm.js +30 -13
- package/dist/core/agents/native-cli-worker.js +2 -1
- package/dist/core/agents/native-worker-backend-router.js +58 -1
- package/dist/core/auto-review.js +25 -4
- package/dist/core/codex/agent-config-file-repair.js +15 -2
- package/dist/core/codex/codex-config-eperm-repair.js +8 -2
- package/dist/core/codex/codex-config-guard.js +289 -0
- package/dist/core/codex/codex-config-toml.js +122 -0
- package/dist/core/codex/codex-project-config-policy.js +59 -7
- package/dist/core/codex-app/sks-menubar.js +780 -122
- package/dist/core/codex-app.js +1 -0
- package/dist/core/codex-control/codex-fake-sdk-adapter.js +6 -4
- package/dist/core/codex-control/codex-sdk-config-policy.js +2 -1
- package/dist/core/codex-control/codex-sdk-env-policy.js +1 -1
- package/dist/core/codex-control/codex-task-runner.js +32 -14
- package/dist/core/codex-control/python-codex-sdk-adapter.js +4 -1
- package/dist/core/codex-control/schemas/agent-worker-result.schema.js +12 -3
- package/dist/core/codex-hooks/codex-hook-managed-install.js +5 -0
- package/dist/core/codex-hooks/codex-hook-state-writer.js +70 -11
- package/dist/core/codex-hooks/codex-hook-trust-doctor.js +2 -2
- package/dist/core/codex-lb/codex-lb-env.js +20 -1
- package/dist/core/codex-lb/codex-lb-setup.js +2 -5
- package/dist/core/codex-native/skill-registry-ledger.js +24 -5
- package/dist/core/commands/basic-cli.js +21 -2
- package/dist/core/commands/check-command.js +37 -5
- package/dist/core/commands/command-utils.js +22 -2
- package/dist/core/commands/computer-use-command.js +62 -7
- package/dist/core/commands/db-command.js +31 -5
- package/dist/core/commands/fast-mode-command.js +39 -11
- package/dist/core/commands/gate-result-contract.js +43 -0
- package/dist/core/commands/gates-command.js +6 -1
- package/dist/core/commands/gc-command.js +29 -2
- package/dist/core/commands/goal-command.js +9 -2
- package/dist/core/commands/gx-command.js +79 -7
- package/dist/core/commands/image-ux-review-command.js +188 -13
- package/dist/core/commands/mad-db-command.js +85 -176
- package/dist/core/commands/mad-sks-command.js +248 -34
- package/dist/core/commands/menubar-command.js +146 -0
- package/dist/core/commands/naruto-command.js +64 -10
- package/dist/core/commands/pipeline-command.js +21 -2
- package/dist/core/commands/plan-command.js +76 -0
- package/dist/core/commands/ppt-command.js +159 -24
- package/dist/core/commands/qa-loop-command.js +6 -2
- package/dist/core/commands/release-command.js +55 -2
- package/dist/core/commands/research-command.js +1 -1
- package/dist/core/commands/review-command.js +217 -0
- package/dist/core/commands/route-command.js +62 -0
- package/dist/core/commands/route-success-helpers.js +59 -0
- package/dist/core/commands/run-command.js +19 -7
- package/dist/core/commands/seo-command.js +49 -1
- package/dist/core/commands/status-command.js +21 -1
- package/dist/core/commands/team-legacy-observe-command.js +221 -3
- package/dist/core/commands/ui-command.js +161 -0
- package/dist/core/commands/uninstall-command.js +312 -0
- package/dist/core/db-safety.js +7 -3
- package/dist/core/doctor/codex-startup-config-repair.js +14 -3
- package/dist/core/doctor/confirm-repair.js +27 -0
- package/dist/core/doctor/context7-mcp-repair.js +35 -7
- package/dist/core/doctor/doctor-codex-startup-repair.js +10 -3
- package/dist/core/doctor/doctor-context7-repair.js +17 -4
- package/dist/core/doctor/doctor-dirty-planner.js +27 -9
- package/dist/core/doctor/doctor-native-capability-repair.js +12 -2
- package/dist/core/doctor/doctor-readiness-matrix.js +27 -2
- package/dist/core/doctor/doctor-repair-postcheck.js +4 -0
- package/dist/core/doctor/doctor-transaction.js +21 -5
- package/dist/core/doctor/doctor-zellij-repair.js +1 -0
- package/dist/core/doctor/imagegen-repair.js +161 -0
- package/dist/core/doctor/supabase-mcp-repair.js +23 -5
- package/dist/core/feature-fixture-runner.js +2 -2
- package/dist/core/feature-fixtures.js +65 -37
- package/dist/core/feature-registry.js +106 -3
- package/dist/core/fsx.js +91 -2
- package/dist/core/hooks-runtime/skill-reconcile-preflight.js +43 -0
- package/dist/core/hooks-runtime.js +86 -46
- package/dist/core/image-ux-review/imagegen-adapter.js +48 -11
- package/dist/core/image-ux-review.js +16 -0
- package/dist/core/imagegen/imagegen-capability.js +11 -5
- package/dist/core/imagegen/require-imagegen.js +57 -0
- package/dist/core/init/skills.js +271 -14
- package/dist/core/init.js +13 -10
- package/dist/core/mad-db/mad-db-coordinator.js +96 -20
- package/dist/core/mad-db/mad-db-policy.js +12 -10
- package/dist/core/mad-sks/executors/executor-base.js +8 -2
- package/dist/core/mad-sks/executors/index.js +4 -0
- package/dist/core/mad-sks/executors/sql-plane-executor.js +194 -0
- package/dist/core/mission.js +138 -5
- package/dist/core/naruto/naruto-active-pool.js +84 -30
- package/dist/core/naruto/naruto-backpressure.js +5 -1
- package/dist/core/naruto/naruto-real-worker-child.js +10 -0
- package/dist/core/naruto/naruto-real-worker-runtime.js +9 -7
- package/dist/core/naruto/naruto-role-policy.js +3 -0
- package/dist/core/naruto/naruto-task-hints.js +10 -0
- package/dist/core/naruto/naruto-work-graph.js +8 -2
- package/dist/core/naruto/naruto-work-item.js +6 -0
- package/dist/core/naruto/resource-pressure-monitor.js +33 -15
- package/dist/core/naruto/solution-tournament.js +101 -0
- package/dist/core/permission-gates.js +30 -0
- package/dist/core/pipeline-internals/runtime-core.js +72 -222
- package/dist/core/pipeline-internals/runtime-gates.js +140 -24
- package/dist/core/ppt-review/index.js +6 -1
- package/dist/core/ppt-review/slide-imagegen-review.js +75 -10
- package/dist/core/ppt.js +70 -2
- package/dist/core/proof/auto-finalize.js +70 -11
- package/dist/core/proof/proof-schema.js +2 -0
- package/dist/core/proof/route-adapter.js +5 -1
- package/dist/core/proof/route-finalizer.js +8 -5
- package/dist/core/proof/selftest-proof-fixtures.js +18 -5
- package/dist/core/proof/validation.js +2 -0
- package/dist/core/provider/model-router.js +53 -0
- package/dist/core/questions.js +1 -1
- package/dist/core/recallpulse.js +1 -1
- package/dist/core/release/gate-manifest.js +2 -2
- package/dist/core/release/release-gate-affected-selector.js +3 -10
- package/dist/core/release/release-gate-batch-runner.js +4 -2
- package/dist/core/release/release-gate-cache-v2.js +27 -14
- package/dist/core/release/release-gate-dag.js +6 -1
- package/dist/core/release/release-gate-hermetic-env.js +10 -0
- package/dist/core/release/release-gate-node.js +3 -0
- package/dist/core/release/release-gate-resource-governor.js +1 -0
- package/dist/core/retention.js +89 -4
- package/dist/core/routes/constants.js +1 -1
- package/dist/core/routes/diagnostic-allowlist.js +55 -0
- package/dist/core/routes.js +83 -33
- package/dist/core/safety/mutation-guard.js +5 -1
- package/dist/core/skill-forge.js +9 -4
- package/dist/core/stop-gate/gate-evaluator.js +102 -0
- package/dist/core/stop-gate/stop-gate-check.js +26 -4
- package/dist/core/stop-gate/stop-gate-resolver.js +19 -3
- package/dist/core/stop-gate/stop-gate-writer.js +20 -1
- package/dist/core/team-dag.js +12 -465
- package/dist/core/team-dashboard-renderer.js +13 -94
- package/dist/core/team-live.js +68 -804
- package/dist/core/triwiki/agents-md-projector.js +184 -0
- package/dist/core/triwiki-wrongness/wrongness-schema.js +3 -1
- package/dist/core/trust-kernel/trust-kernel-schema.js +1 -0
- package/dist/core/trust-kernel/trust-report.js +1 -1
- package/dist/core/trust-kernel/trust-status.js +2 -0
- package/dist/core/ui/dashboard-html.js +111 -0
- package/dist/core/update/update-migration-state.js +383 -42
- package/dist/core/update-check.js +201 -78
- package/dist/core/verification/diff-quality.js +100 -0
- package/dist/core/verification/impact-scan.js +164 -0
- package/dist/core/verification/machine-feedback.js +146 -0
- package/dist/core/verification/mistake-rule-compiler.js +195 -0
- package/dist/core/version.js +1 -1
- package/dist/core/zellij/zellij-layout-builder.js +44 -16
- package/dist/core/zellij/zellij-monitor-renderer.js +53 -0
- package/dist/core/zellij/zellij-self-heal.js +27 -32
- package/dist/core/zellij/zellij-slot-pane-renderer.js +162 -153
- package/dist/core/zellij/zellij-slot-telemetry.js +2 -0
- package/dist/core/zellij/zellij-theme.js +67 -0
- package/dist/core/zellij/zellij-ui-mode.js +16 -0
- package/dist/core/zellij/zellij-viewport-binder.js +59 -0
- package/dist/core/zellij/zellij-worker-pane-manager.js +53 -5
- package/dist/scripts/agent-patch-swarm-gate-lib.js +2 -2
- package/dist/scripts/build-dist.js +8 -0
- package/dist/scripts/check-feature-quality.js +2 -2
- package/dist/scripts/cli-output-consistency-check.js +57 -0
- package/dist/scripts/codex-lb-fast-ui-preservation-check.js +106 -0
- package/dist/scripts/codex-lb-gpt55-fast-profile-check.js +105 -0
- package/dist/scripts/codex-lb-missing-env-regression.js +2 -3
- package/dist/scripts/codex-project-config-policy-merge-regression.js +3 -3
- package/dist/scripts/coding-bench-check.js +136 -0
- package/dist/scripts/concurrent-session-collision-check.js +67 -0
- package/dist/scripts/docs-truthfulness-check.js +1 -1
- package/dist/scripts/doctor-imagegen-repair-check.js +62 -0
- package/dist/scripts/ensure-bin-executable.js +11 -3
- package/dist/scripts/gate-policy-audit-check.js +130 -0
- package/dist/scripts/harness-benchmark-check.js +104 -0
- package/dist/scripts/hook-latency-budget-check.js +45 -0
- package/dist/scripts/legacy-update-e2e-check.js +228 -0
- package/dist/scripts/lib/codex-sdk-gate-lib.js +2 -2
- package/dist/scripts/lib/real-codex-parallel-gate.js +2 -2
- package/dist/scripts/loop-directive-check-lib.js +1 -1
- package/dist/scripts/mad-db-command-check.js +11 -8
- package/dist/scripts/mad-db-real-supabase-e2e.js +2 -2
- package/dist/scripts/mad-db-route-identity-check.js +8 -6
- package/dist/scripts/mad-db-safety-conflict-matrix-check.js +31 -8
- package/dist/scripts/mad-db-skill-policy-snapshot-check.js +4 -5
- package/dist/scripts/mad-sks-zellij-default-pane-worker-check.js +3 -2
- package/dist/scripts/mad-sks-zellij-launch-check.js +1 -1
- package/dist/scripts/naruto-zellij-dynamic-right-column-check.js +7 -7
- package/dist/scripts/parallel-claim-enforcement-check.js +14 -5
- package/dist/scripts/ppt-real-imagegen-wiring-check.js +5 -1
- package/dist/scripts/project-skill-dedupe-check.js +23 -5
- package/dist/scripts/proof-root-cause-policy-check.js +2 -0
- package/dist/scripts/release-affected-selector-check.js +2 -2
- package/dist/scripts/release-cache-glob-hashing-check.js +1 -0
- package/dist/scripts/release-dag-full-coverage-check.js +13 -4
- package/dist/scripts/release-gate-dag-runner-check.js +10 -2
- package/dist/scripts/release-gate-dag-runner.js +22 -0
- package/dist/scripts/release-gate-existence-audit.js +2 -1
- package/dist/scripts/release-gate-planner.js +2 -1
- package/dist/scripts/release-gate-script-parity-check.js +1 -1
- package/dist/scripts/release-metadata-1-19-check.js +2 -1
- package/dist/scripts/release-readiness-report.js +38 -7
- package/dist/scripts/release-stability-report-check.js +12 -8
- package/dist/scripts/search-visibility-gate-lib.js +2 -2
- package/dist/scripts/seo-geo-feature-fixture-quality-check.js +1 -1
- package/dist/scripts/skills-manifest-continuity-check.js +46 -0
- package/dist/scripts/sks-1-11-gate-lib.js +8 -6
- package/dist/scripts/sks-menubar-install-check.js +87 -21
- package/dist/scripts/sks-uninstall-regression-check.js +54 -0
- package/dist/scripts/uninstall-inventory-check.js +3 -0
- package/dist/scripts/ux-review-real-loop-fixture-check.js +9 -4
- package/dist/scripts/ux-review-run-wires-imagegen-check.js +4 -0
- package/dist/scripts/zellij-layout-valid-check.js +18 -11
- package/dist/scripts/zellij-right-column-geometry-proof.js +2 -4
- package/dist/scripts/zellij-slot-pane-renderer-check.js +9 -9
- package/dist/scripts/zellij-slot-pane-stale-detection-check.js +3 -4
- package/dist/scripts/zellij-slot-pane-telemetry-renderer-check.js +3 -2
- package/dist/scripts/zellij-slot-telemetry-renderer-check.js +4 -2
- package/dist/scripts/zellij-spawn-on-demand-layout-check.js +8 -2
- package/dist/scripts/zellij-viewport-binder-check.js +9 -0
- package/docs/assets/sneakoscope-architecture-pipeline.jpg +0 -0
- package/docs/demo.tape +28 -0
- package/package.json +70 -3
- package/schemas/codex/completion-proof.schema.json +3 -2
- package/schemas/release/release-gate-node.schema.json +2 -1
- package/dist/scripts/agent-backfill-route-blackbox.js +0 -5
- package/dist/scripts/agent-dynamic-pool-route-blackbox.js +0 -5
- package/dist/scripts/agent-parallel-write-blackbox.js +0 -56
- package/dist/scripts/agent-patch-swarm-route-blackbox.js +0 -10
- package/dist/scripts/agent-route-blackbox-lib.js +0 -132
- package/dist/scripts/blackbox-command-import-smoke.js +0 -143
- package/dist/scripts/blackbox-global-shim.js +0 -77
- package/dist/scripts/blackbox-matrix.js +0 -70
- package/dist/scripts/blackbox-npx-one-shot.js +0 -69
- package/dist/scripts/blackbox-pack-install.js +0 -174
- package/dist/scripts/brand-neutrality-zero-leakage-blackbox.js +0 -4
- package/dist/scripts/build-once-runner-blackbox.js +0 -34
- package/dist/scripts/codex-0140-integration-blackbox.js +0 -13
- package/dist/scripts/codex-agent-type-blackbox.js +0 -4
- package/dist/scripts/codex-app-harness-blackbox.js +0 -4
- package/dist/scripts/codex-app-skill-agent-blackbox.js +0 -4
- package/dist/scripts/codex-hook-approval-blackbox.js +0 -4
- package/dist/scripts/codex-init-deep-directory-local-blackbox.js +0 -4
- package/dist/scripts/codex-native-feature-broker-blackbox.js +0 -4
- package/dist/scripts/codex-native-pattern-analysis-blackbox.js +0 -4
- package/dist/scripts/codex-native-read-repair-split-blackbox.js +0 -55
- package/dist/scripts/codex-native-reference-cache-blackbox.js +0 -41
- package/dist/scripts/core-skill-integrity-blackbox.js +0 -33
- package/dist/scripts/dfix-fast-blackbox-check.js +0 -37
- package/dist/scripts/dfix-parallel-write-blackbox.js +0 -48
- package/dist/scripts/dfix-patch-swarm-route-blackbox.js +0 -10
- package/dist/scripts/doctor-context7-mcp-repair-blackbox.js +0 -16
- package/dist/scripts/doctor-dirty-repair-blackbox.js +0 -22
- package/dist/scripts/doctor-dirty-semantic-blackbox.js +0 -8
- package/dist/scripts/doctor-fix-production-blackbox.js +0 -26
- package/dist/scripts/doctor-native-capability-repair-blackbox.js +0 -39
- package/dist/scripts/doctor-startup-config-repair-blackbox.js +0 -13
- package/dist/scripts/doctor-supabase-mcp-repair-blackbox.js +0 -14
- package/dist/scripts/doctor-transaction-engine-blackbox.js +0 -28
- package/dist/scripts/doctor-zellij-fix-blackbox.js +0 -4
- package/dist/scripts/doctor-zellij-no-homebrew-blackbox.js +0 -4
- package/dist/scripts/doctor-zellij-upgrade-blackbox.js +0 -4
- package/dist/scripts/gate-pack-runner-blackbox.js +0 -27
- package/dist/scripts/gate-pack-v2-blackbox.js +0 -18
- package/dist/scripts/geo-cli-blackbox-check.js +0 -18
- package/dist/scripts/loop-collision-blackbox.js +0 -3
- package/dist/scripts/loop-concurrency-oversubscription-blackbox.js +0 -3
- package/dist/scripts/loop-fixture-production-misuse-blackbox.js +0 -3
- package/dist/scripts/loop-kill-interrupt-real-blackbox.js +0 -3
- package/dist/scripts/loop-merge-strategy-blackbox.js +0 -3
- package/dist/scripts/loop-mesh-production-e2e-blackbox.js +0 -3
- package/dist/scripts/loop-side-effect-blackbox.js +0 -3
- package/dist/scripts/mad-db-operation-lifecycle-blackbox.js +0 -29
- package/dist/scripts/mad-sks-actual-executor-blackbox.js +0 -5
- package/dist/scripts/mad-zellij-headless-fallback-blackbox.js +0 -4
- package/dist/scripts/mad-zellij-self-heal-blackbox.js +0 -4
- package/dist/scripts/naruto-loop-mesh-blackbox.js +0 -3
- package/dist/scripts/naruto-real-parallelism-blackbox.js +0 -307
- package/dist/scripts/naruto-worktree-coding-blackbox.js +0 -29
- package/dist/scripts/parallel-runtime-real-blackbox.js +0 -44
- package/dist/scripts/pipeline-codex-native-doctor-mad-routing-real-blackbox.js +0 -77
- package/dist/scripts/pipeline-codex-native-e2e-blackbox.js +0 -13
- package/dist/scripts/pipeline-codex-native-image-routing-real-blackbox.js +0 -50
- package/dist/scripts/pipeline-codex-native-loop-routing-real-blackbox.js +0 -74
- package/dist/scripts/pipeline-codex-native-qa-routing-real-blackbox.js +0 -51
- package/dist/scripts/pipeline-codex-native-research-routing-real-blackbox.js +0 -45
- package/dist/scripts/pipeline-execution-profile-routing-blackbox.js +0 -4
- package/dist/scripts/postinstall-global-doctor-blackbox.js +0 -12
- package/dist/scripts/ppt-full-e2e-blackbox-check.js +0 -109
- package/dist/scripts/ppt-imagegen-blackbox-check.js +0 -46
- package/dist/scripts/project-skill-dedupe-blackbox.js +0 -36
- package/dist/scripts/qa-backfill-route-blackbox.js +0 -5
- package/dist/scripts/qa-patch-swarm-route-blackbox.js +0 -10
- package/dist/scripts/release-full-parallelism-blackbox.js +0 -41
- package/dist/scripts/release-triwiki-first-runner-blackbox.js +0 -48
- package/dist/scripts/release-wiring-3110-blackbox.js +0 -27
- package/dist/scripts/release-wiring-3112-blackbox.js +0 -17
- package/dist/scripts/release-wiring-3113-blackbox.js +0 -17
- package/dist/scripts/research-backfill-route-blackbox.js +0 -5
- package/dist/scripts/research-final-reviewer-blackbox.js +0 -70
- package/dist/scripts/research-stage-cycle-runtime-blackbox.js +0 -40
- package/dist/scripts/research-synthesis-writer-blackbox.js +0 -24
- package/dist/scripts/route-blackbox-realism-check.js +0 -21
- package/dist/scripts/scheduler-resource-claim-blackbox.js +0 -24
- package/dist/scripts/seo-cli-blackbox-check.js +0 -18
- package/dist/scripts/sks-3110-all-feature-regression-blackbox.js +0 -116
- package/dist/scripts/sks-3112-all-feature-regression-blackbox.js +0 -29
- package/dist/scripts/sks-3113-all-feature-regression-blackbox.js +0 -17
- package/dist/scripts/sks-400-all-feature-regression-blackbox.js +0 -21
- package/dist/scripts/sks-400-extreme-parallel-blackbox.js +0 -8
- package/dist/scripts/sks-400-five-minute-blackbox.js +0 -9
- package/dist/scripts/sks-400-legacy-purge-blackbox.js +0 -8
- package/dist/scripts/sks-401-all-feature-regression-blackbox.js +0 -46
- package/dist/scripts/sks-401-five-minute-actual-blackbox.js +0 -23
- package/dist/scripts/sks-402-all-feature-regression-blackbox.js +0 -9
- package/dist/scripts/sks-402-five-minute-real-blackbox.js +0 -22
- package/dist/scripts/sksd-warm-cache-blackbox.js +0 -12
- package/dist/scripts/supabase-secret-preservation-blackbox.js +0 -29
- package/dist/scripts/team-backfill-route-blackbox.js +0 -5
- package/dist/scripts/team-parallel-write-blackbox.js +0 -55
- package/dist/scripts/team-patch-swarm-route-blackbox.js +0 -10
- package/dist/scripts/triwiki-affected-graph-blackbox.js +0 -28
- package/dist/scripts/triwiki-proof-bank-blackbox.js +0 -30
- package/dist/scripts/triwiki-proof-bank-lock-blackbox.js +0 -7
- package/dist/scripts/update-preserves-supabase-keys-blackbox.js +0 -27
- package/dist/scripts/ux-patch-swarm-route-blackbox.js +0 -10
- package/dist/scripts/ux-review-imagegen-blackbox-check.js +0 -67
- package/dist/scripts/zellij-initial-main-only-blackbox.js +0 -28
- package/dist/scripts/zellij-pane-lock-concurrency-blackbox.js +0 -80
- package/dist/scripts/zellij-pane-lock-open-worker-integration-blackbox.js +0 -137
- package/dist/scripts/zellij-self-heal-typed-blackbox.js +0 -4
- package/dist/scripts/zellij-slot-telemetry-real-blackbox.js +0 -20
- package/dist/scripts/zellij-stacked-fallback-integration-blackbox.js +0 -81
- package/dist/scripts/zellij-worker-pane-real-ui-blackbox.js +0 -202
package/dist/core/team-live.js
CHANGED
|
@@ -1,39 +1,6 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
|
-
import { appendJsonlBounded, nowIso, readJson, readText, writeJsonAtomic, writeTextAtomic } from './fsx.js';
|
|
3
|
-
import { reasoningProfileName, triwikiContextTracking, triwikiContextTrackingText } from './routes.js';
|
|
4
|
-
import { MIN_TEAM_REVIEWER_LANES, MIN_TEAM_REVIEW_STAGE_AGENT_SESSIONS } from './team-review-policy.js';
|
|
5
1
|
import { MAX_AGENT_COUNT } from './agents/agent-schema.js';
|
|
2
|
+
import { MIN_TEAM_REVIEWER_LANES } from './team-review-policy.js';
|
|
6
3
|
export { MIN_TEAM_REVIEWER_LANES, MIN_TEAM_REVIEW_POLICY_TEXT, MIN_TEAM_REVIEW_STAGE_AGENT_SESSIONS, evaluateTeamReviewPolicyGate, teamReviewPolicy } from './team-review-policy.js';
|
|
7
|
-
const MAX_LIVE_BYTES = 192 * 1024;
|
|
8
|
-
const TEAM_RUNTIME_TASKS_ARTIFACT = 'team-runtime-tasks.json';
|
|
9
|
-
const TEAM_SESSION_CLEANUP_ARTIFACT = 'team-session-cleanup.json';
|
|
10
|
-
const DEFAULT_AGENTS = ['parent_orchestrator', 'native_agent_orchestrator', 'agent_central_ledger', 'agent_proof_evidence', 'agent_review_lane', 'agent_integration_lane'];
|
|
11
|
-
const TERMINAL_TEAM_AGENT_STATUSES = new Set([
|
|
12
|
-
'agent_closed',
|
|
13
|
-
'agent_done',
|
|
14
|
-
'cancelled',
|
|
15
|
-
'canceled',
|
|
16
|
-
'cleanup',
|
|
17
|
-
'cleanup_requested',
|
|
18
|
-
'closed',
|
|
19
|
-
'complete',
|
|
20
|
-
'completed',
|
|
21
|
-
'done',
|
|
22
|
-
'ended',
|
|
23
|
-
'failed',
|
|
24
|
-
'stopped',
|
|
25
|
-
'terminal',
|
|
26
|
-
'zellij_lane_closed'
|
|
27
|
-
]);
|
|
28
|
-
const CHAT_COLOR_CODES = {
|
|
29
|
-
blue: '34',
|
|
30
|
-
cyan: '36',
|
|
31
|
-
yellow: '33',
|
|
32
|
-
magenta: '35',
|
|
33
|
-
red: '31',
|
|
34
|
-
green: '32',
|
|
35
|
-
gray: '90'
|
|
36
|
-
};
|
|
37
4
|
export const DEFAULT_TEAM_ROLE_COUNTS = { user: 1, planner: 1, reviewer: MIN_TEAM_REVIEWER_LANES, executor: 3 };
|
|
38
5
|
export const MAX_TEAM_AGENT_SESSIONS = MAX_AGENT_COUNT;
|
|
39
6
|
export const DEFAULT_MAX_TEAM_AGENT_SESSIONS = MAX_TEAM_AGENT_SESSIONS;
|
|
@@ -41,253 +8,22 @@ const ROLE_ALIASES = {
|
|
|
41
8
|
user: 'user',
|
|
42
9
|
users: 'user',
|
|
43
10
|
customer: 'user',
|
|
44
|
-
customers: 'user',
|
|
45
11
|
client: 'user',
|
|
46
|
-
enduser: 'user',
|
|
47
|
-
stakeholder: 'user',
|
|
48
12
|
planner: 'planner',
|
|
49
13
|
planners: 'planner',
|
|
50
14
|
architect: 'planner',
|
|
51
|
-
architects: 'planner',
|
|
52
15
|
lead: 'planner',
|
|
53
16
|
executor: 'executor',
|
|
54
17
|
executors: 'executor',
|
|
55
18
|
implementer: 'executor',
|
|
56
|
-
implementers: 'executor',
|
|
57
19
|
developer: 'executor',
|
|
58
|
-
developers: 'executor',
|
|
59
20
|
dev: 'executor',
|
|
60
|
-
devs: 'executor',
|
|
61
21
|
reviewer: 'reviewer',
|
|
62
22
|
reviewers: 'reviewer',
|
|
63
23
|
critic: 'reviewer',
|
|
64
|
-
critics: 'reviewer',
|
|
65
24
|
qa: 'reviewer',
|
|
66
|
-
verifier: 'reviewer'
|
|
67
|
-
verifiers: 'reviewer'
|
|
25
|
+
verifier: 'reviewer'
|
|
68
26
|
};
|
|
69
|
-
const TEAM_REASONING_POLICY_VERSION = 1;
|
|
70
|
-
const XHIGH_SIGNAL_RE = /(frontier|autoresearch|novelty|hypothesis|falsify|forensic|from-chat-img|image\s*work\s*order|새로운\s*연구|가설|포렌식)/i;
|
|
71
|
-
const HIGH_SIGNAL_RE = /(research|current docs?|library|framework|sdk|api|database|supabase|sql|migration|security|permission|mad|release|publish|deploy|commit|push|architecture|algorithm|policy|위험|보안|배포|커밋|푸쉬|마이그레이션|데이터베이스|권한|리서치|문서)/i;
|
|
72
|
-
const MEDIUM_SIGNAL_RE = /(tmux|terminal|cli|cmd|warp|tool(?:\s|-)?call|hook|router|routing|orchestrat|pipeline|multi[-\s]?pane|pane|process|config|many files?|여러\s*파일|터미널|라우팅|파이프라인|훅|도구|툴)/i;
|
|
73
|
-
const SIMPLE_SIGNAL_RE = /(tiny|simple|small|one[-\s]?line|typo|copy|label|spacing|rename|text|readme|docs?|config wording|간단|단순|오타|문구|라벨|간격|색상)/i;
|
|
74
|
-
export function teamAgentReasoning(input = {}) {
|
|
75
|
-
const prompt = String(input.prompt || '');
|
|
76
|
-
const role = String(input.role || '').toLowerCase();
|
|
77
|
-
const id = String(input.id || input.agentId || '').toLowerCase();
|
|
78
|
-
const base = teamPromptReasoning(prompt);
|
|
79
|
-
let effort = base.effort;
|
|
80
|
-
let reason = base.reason;
|
|
81
|
-
if (/db|safety/.test(id) || role === 'safety') {
|
|
82
|
-
effort = base.effort === 'xhigh' ? 'xhigh' : 'high';
|
|
83
|
-
reason = 'db_or_safety_reviewer';
|
|
84
|
-
}
|
|
85
|
-
else if (/review|qa/.test(id) || role === 'reviewer') {
|
|
86
|
-
effort = base.effort === 'low' ? 'medium' : base.effort;
|
|
87
|
-
reason = base.effort === 'low' ? 'review_requires_more_than_low' : base.reason;
|
|
88
|
-
}
|
|
89
|
-
else if (/planner|consensus|debate/.test(id) || role === 'planner') {
|
|
90
|
-
effort = base.effort === 'low' ? 'medium' : base.effort;
|
|
91
|
-
reason = base.effort === 'low' ? 'planning_uses_medium_minimum' : base.reason;
|
|
92
|
-
}
|
|
93
|
-
else if (/user/.test(id) || role === 'user') {
|
|
94
|
-
effort = 'low';
|
|
95
|
-
reason = 'user_persona_lane';
|
|
96
|
-
}
|
|
97
|
-
else if (/executor|implementation/.test(id) || role === 'executor') {
|
|
98
|
-
effort = base.effort === 'xhigh' ? 'high' : base.effort;
|
|
99
|
-
reason = base.effort === 'xhigh' ? 'implementation_capped_at_high' : base.reason;
|
|
100
|
-
}
|
|
101
|
-
const profile = reasoningProfileName(effort);
|
|
102
|
-
return {
|
|
103
|
-
policy_version: TEAM_REASONING_POLICY_VERSION,
|
|
104
|
-
reasoning_effort: effort,
|
|
105
|
-
model_reasoning_effort: effort,
|
|
106
|
-
reasoning_profile: profile,
|
|
107
|
-
service_tier: 'fast',
|
|
108
|
-
fast_mode: true,
|
|
109
|
-
reasoning_reason: reason,
|
|
110
|
-
routing: 'dynamic_team_agent_reasoning'
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
export function teamPromptReasoning(prompt = '') {
|
|
114
|
-
const text = String(prompt || '');
|
|
115
|
-
if (XHIGH_SIGNAL_RE.test(text))
|
|
116
|
-
return { effort: 'xhigh', reason: 'research_forensic_or_frontier_signal' };
|
|
117
|
-
if (HIGH_SIGNAL_RE.test(text))
|
|
118
|
-
return { effort: 'high', reason: 'knowledge_safety_release_or_db_signal' };
|
|
119
|
-
if (SIMPLE_SIGNAL_RE.test(text) && !MEDIUM_SIGNAL_RE.test(text))
|
|
120
|
-
return { effort: 'low', reason: 'simple_bounded_code_or_content_change' };
|
|
121
|
-
if (MEDIUM_SIGNAL_RE.test(text))
|
|
122
|
-
return { effort: 'medium', reason: 'tooling_or_runtime_orchestration_signal' };
|
|
123
|
-
return { effort: 'medium', reason: 'default_team_balanced_reasoning' };
|
|
124
|
-
}
|
|
125
|
-
export function formatAgentReasoning(agent = {}) {
|
|
126
|
-
const effort = agent.reasoning_effort || agent.model_reasoning_effort || 'medium';
|
|
127
|
-
const profile = agent.reasoning_profile || reasoningProfileName(effort);
|
|
128
|
-
const reason = agent.reasoning_reason || 'default_team_balanced_reasoning';
|
|
129
|
-
return `${effort}/${profile}, fast, ${reason}`;
|
|
130
|
-
}
|
|
131
|
-
export function teamReasoningPolicy(prompt = '', roster = {}) {
|
|
132
|
-
const agents = Array.isArray(roster.all_agents) ? roster.all_agents : [];
|
|
133
|
-
const counts = {};
|
|
134
|
-
for (const agent of agents)
|
|
135
|
-
counts[agent.reasoning_effort || 'medium'] = (counts[agent.reasoning_effort || 'medium'] || 0) + 1;
|
|
136
|
-
return {
|
|
137
|
-
schema_version: TEAM_REASONING_POLICY_VERSION,
|
|
138
|
-
dynamic: true,
|
|
139
|
-
service_tier: 'fast',
|
|
140
|
-
prompt_policy: teamPromptReasoning(prompt),
|
|
141
|
-
allowed_efforts: ['low', 'medium', 'high', 'xhigh'],
|
|
142
|
-
profile_map: {
|
|
143
|
-
low: reasoningProfileName('low'),
|
|
144
|
-
medium: reasoningProfileName('medium'),
|
|
145
|
-
high: reasoningProfileName('high'),
|
|
146
|
-
xhigh: reasoningProfileName('xhigh')
|
|
147
|
-
},
|
|
148
|
-
counts,
|
|
149
|
-
rule: 'Assign per-agent reasoning from prompt risk and role; simple bounded work can use low, tool-heavy runtime work medium, knowledge/research/safety/release work high or xhigh.'
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
export function teamLogPaths(dir) {
|
|
153
|
-
return {
|
|
154
|
-
live: path.join(dir, 'team-live.md'),
|
|
155
|
-
transcript: path.join(dir, 'team-transcript.jsonl'),
|
|
156
|
-
dashboard: path.join(dir, 'team-dashboard.json'),
|
|
157
|
-
control: path.join(dir, 'team-control.json')
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
export function defaultTeamDashboard(id, prompt, opts = {}) {
|
|
161
|
-
const spec = normalizeTeamSpec({ ...opts, prompt });
|
|
162
|
-
return {
|
|
163
|
-
schema_version: 1,
|
|
164
|
-
mission_id: id,
|
|
165
|
-
prompt,
|
|
166
|
-
agent_session_count: spec.agentSessions,
|
|
167
|
-
role_counts: spec.roleCounts,
|
|
168
|
-
session_policy: `Use at most ${spec.agentSessions} native multi-session lanes at a time; parent orchestrator is not counted.`,
|
|
169
|
-
bundle_size: spec.bundleSize,
|
|
170
|
-
roster: spec.roster,
|
|
171
|
-
context_tracking: triwikiContextTracking(),
|
|
172
|
-
updated_at: nowIso(),
|
|
173
|
-
live_files: {
|
|
174
|
-
markdown: 'team-live.md',
|
|
175
|
-
transcript: 'team-transcript.jsonl',
|
|
176
|
-
dashboard: 'team-dashboard.json'
|
|
177
|
-
},
|
|
178
|
-
commands: {
|
|
179
|
-
status: `sks team status ${id}`,
|
|
180
|
-
log: `sks team log ${id}`,
|
|
181
|
-
tail: `sks team tail ${id}`,
|
|
182
|
-
open_zellij: `sks team open-zellij ${id}`,
|
|
183
|
-
watch: `sks team watch ${id}`,
|
|
184
|
-
lane: `sks team lane ${id} --agent <agent> --follow`,
|
|
185
|
-
event: `sks team event ${id} --agent <agent> --phase <phase> --message "..."`,
|
|
186
|
-
message: `sks team message ${id} --from <agent> --to <agent|all> --message "..."`,
|
|
187
|
-
cleanup: `sks team cleanup-zellij ${id}`
|
|
188
|
-
},
|
|
189
|
-
agents: Object.fromEntries([...new Set([...DEFAULT_AGENTS, ...spec.roster.all_agents.map((agent) => agent.id)])].map((name) => [name, { status: 'pending', phase: null, last_seen: null }])),
|
|
190
|
-
phases: ['native_agent_intake', 'triwiki_refresh', 'debate_team', 'triwiki_refresh_after_consensus', 'parallel_development_team', 'triwiki_refresh_after_implementation', 'strict_review_and_user_acceptance', 'session_cleanup'],
|
|
191
|
-
latest_messages: []
|
|
192
|
-
};
|
|
193
|
-
}
|
|
194
|
-
export function teamLiveMarkdown(id, prompt, opts = {}) {
|
|
195
|
-
const spec = normalizeTeamSpec({ ...opts, prompt });
|
|
196
|
-
const contextTracking = triwikiContextTrackingText();
|
|
197
|
-
return `# SKS Team Live Transcript
|
|
198
|
-
|
|
199
|
-
Mission: ${id}
|
|
200
|
-
|
|
201
|
-
Agent session budget: ${spec.agentSessions}
|
|
202
|
-
|
|
203
|
-
Bundle size: ${spec.bundleSize}
|
|
204
|
-
|
|
205
|
-
Role counts: ${formatRoleCounts(spec.roleCounts)}
|
|
206
|
-
|
|
207
|
-
Task:
|
|
208
|
-
${prompt}
|
|
209
|
-
|
|
210
|
-
## How to Read
|
|
211
|
-
|
|
212
|
-
- This file is the Codex App-visible replacement for Zellij-style team panes.
|
|
213
|
-
- Use at most ${spec.agentSessions} native multi-session lanes at a time unless the mission is recreated with a different budget.
|
|
214
|
-
- Team mode has three bundles: parallel native agent intake agents first, debate team second, then fresh parallel development team.
|
|
215
|
-
- Use relevant TriWiki context before every stage, hydrate low-trust claims from source during the stage, refresh after findings/artifact changes, and validate before handoffs or final claims.
|
|
216
|
-
- Native agent intake agents are read-only and split repo, docs, tests, risk, API, and user-flow investigation before the parent refreshes TriWiki for debate.
|
|
217
|
-
- executor:N means build N debate participants and then a separate N-person executor development team.
|
|
218
|
-
- N:agents or N:agent means use up to N native multi-session agents for Team bundles, capped at ${MAX_TEAM_AGENT_SESSIONS}.
|
|
219
|
-
- Debate uses compact Hyperplan-derived adversarial lenses: challenge framing, subtract surface, demand evidence, test integration risk, and consider one simpler alternative.
|
|
220
|
-
- User personas are intentionally impatient, self-interested, stubborn, low-context, and dislike inconvenience.
|
|
221
|
-
- Executors are capable developers with disjoint ownership.
|
|
222
|
-
- Team reviewer lane policy enforces at least ${MIN_TEAM_REVIEWER_LANES} strict reviewers and enough review-stage parallel capacity.
|
|
223
|
-
- Reviewers are strict and adversarial about correctness, safety, tests, and evidence.
|
|
224
|
-
- Every useful native-session status, debate result, handoff, review finding, and integration decision must be appended here.
|
|
225
|
-
- Before reflection/final, close or account for all Team native sessions and write team-session-cleanup.json.
|
|
226
|
-
- Machine-readable events are mirrored to team-transcript.jsonl.
|
|
227
|
-
- Dashboard state is mirrored to team-dashboard.json.
|
|
228
|
-
- ${contextTracking}
|
|
229
|
-
|
|
230
|
-
## Commands
|
|
231
|
-
|
|
232
|
-
\`\`\`bash
|
|
233
|
-
sks team status ${id}
|
|
234
|
-
sks team log ${id}
|
|
235
|
-
sks team tail ${id}
|
|
236
|
-
sks team open-zellij ${id}
|
|
237
|
-
sks team watch ${id}
|
|
238
|
-
sks team lane ${id} --agent native_agent_1 --follow
|
|
239
|
-
sks team event ${id} --agent native_agent_1 --phase native_agent_intake --message "mapped repo slice"
|
|
240
|
-
sks team message ${id} --from native_agent_1 --to executor_1 --message "handoff note"
|
|
241
|
-
sks team cleanup-zellij ${id}
|
|
242
|
-
\`\`\`
|
|
243
|
-
|
|
244
|
-
## Roster
|
|
245
|
-
|
|
246
|
-
Native agent intake (${spec.roster.analysis_team.length} agents):
|
|
247
|
-
${spec.roster.analysis_team.map(formatRosterLine).join('\n')}
|
|
248
|
-
|
|
249
|
-
Debate team (${spec.roster.debate_team.length} participants):
|
|
250
|
-
${spec.roster.debate_team.map(formatRosterLine).join('\n')}
|
|
251
|
-
|
|
252
|
-
Development team (${spec.roster.development_team.length} executors):
|
|
253
|
-
${spec.roster.development_team.map(formatRosterLine).join('\n')}
|
|
254
|
-
|
|
255
|
-
Validation team:
|
|
256
|
-
${spec.roster.validation_team.map(formatRosterLine).join('\n')}
|
|
257
|
-
|
|
258
|
-
## Live Events
|
|
259
|
-
`;
|
|
260
|
-
}
|
|
261
|
-
export async function initTeamLive(id, dir, prompt, opts = {}) {
|
|
262
|
-
const files = teamLogPaths(dir);
|
|
263
|
-
const spec = normalizeTeamSpec({ ...opts, prompt });
|
|
264
|
-
await writeJsonAtomic(files.dashboard, defaultTeamDashboard(id, prompt, opts));
|
|
265
|
-
await writeJsonAtomic(files.control, defaultTeamControl(id));
|
|
266
|
-
await writeTextAtomic(files.live, teamLiveMarkdown(id, prompt, opts));
|
|
267
|
-
await writeTextAtomic(files.transcript, '');
|
|
268
|
-
await appendTeamEvent(dir, { agent: 'parent_orchestrator', phase: 'mission_created', type: 'status', message: 'Team mission created and live transcript initialized.' });
|
|
269
|
-
for (const analysisAgent of spec.roster.analysis_team || []) {
|
|
270
|
-
await appendTeamEvent(dir, {
|
|
271
|
-
agent: analysisAgent.id,
|
|
272
|
-
phase: 'native_agent_intake',
|
|
273
|
-
type: 'assigned',
|
|
274
|
-
message: `${analysisAgent.id} agent lane assigned; waiting for read-only repository/docs/tests/API/risk slice activity.`
|
|
275
|
-
});
|
|
276
|
-
}
|
|
277
|
-
return files;
|
|
278
|
-
}
|
|
279
|
-
export function defaultTeamControl(id) {
|
|
280
|
-
return {
|
|
281
|
-
schema_version: 1,
|
|
282
|
-
mission_id: id,
|
|
283
|
-
status: 'running',
|
|
284
|
-
cleanup_requested: false,
|
|
285
|
-
cleanup_requested_at: null,
|
|
286
|
-
cleanup_requested_by: null,
|
|
287
|
-
cleanup_reason: null,
|
|
288
|
-
final_message: null
|
|
289
|
-
};
|
|
290
|
-
}
|
|
291
27
|
export function normalizeTeamAgentSessions(value, fallback = 3) {
|
|
292
28
|
const n = Number(value ?? fallback);
|
|
293
29
|
const fallbackNumber = Number(fallback);
|
|
@@ -301,34 +37,11 @@ export function parseTeamSpecArgs(args = []) {
|
|
|
301
37
|
let explicitExecutor = false;
|
|
302
38
|
for (let i = 0; i < args.length; i++) {
|
|
303
39
|
const arg = String(args[i]);
|
|
304
|
-
const
|
|
305
|
-
if (
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
continue;
|
|
310
|
-
}
|
|
311
|
-
const rolePair = parseRolePair(arg);
|
|
312
|
-
if (rolePair) {
|
|
313
|
-
roleCounts[rolePair.role] = rolePair.count;
|
|
314
|
-
if (rolePair.role === 'executor')
|
|
315
|
-
explicitExecutor = true;
|
|
316
|
-
continue;
|
|
317
|
-
}
|
|
318
|
-
const flagPair = arg.match(/^--([A-Za-z_-]+)=(\d+)$/);
|
|
319
|
-
if (flagPair) {
|
|
320
|
-
const role = normalizeTeamRole(flagPair[1]);
|
|
321
|
-
if (role) {
|
|
322
|
-
roleCounts[role] = normalizeTeamAgentSessions(flagPair[2], roleCounts[role] || 1);
|
|
323
|
-
if (role === 'executor')
|
|
324
|
-
explicitExecutor = true;
|
|
325
|
-
continue;
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
if (/^--(?:max-agents|max-sessions|max-team)$/.test(arg)) {
|
|
329
|
-
explicitSession = DEFAULT_MAX_TEAM_AGENT_SESSIONS;
|
|
330
|
-
if (!explicitExecutor)
|
|
331
|
-
roleCounts.executor = DEFAULT_MAX_TEAM_AGENT_SESSIONS;
|
|
40
|
+
const parsed = parseBudgetOrRoleToken(arg, roleCounts, explicitExecutor, explicitSession);
|
|
41
|
+
if (parsed.consumed) {
|
|
42
|
+
roleCounts = parsed.roleCounts;
|
|
43
|
+
explicitExecutor = parsed.explicitExecutor;
|
|
44
|
+
explicitSession = parsed.explicitSession;
|
|
332
45
|
continue;
|
|
333
46
|
}
|
|
334
47
|
if (/^--(?:agents|sessions|team-size)$/.test(arg)) {
|
|
@@ -338,35 +51,21 @@ export function parseTeamSpecArgs(args = []) {
|
|
|
338
51
|
i++;
|
|
339
52
|
continue;
|
|
340
53
|
}
|
|
341
|
-
if (/^--(?:
|
|
342
|
-
|
|
343
|
-
continue;
|
|
344
|
-
}
|
|
345
|
-
if (/^--(?:work-items|target-active-slots|minimum-work-items|max-queue-expansion)=\d+$/.test(arg))
|
|
346
|
-
continue;
|
|
347
|
-
const sessionEq = arg.match(/^--(?:agents|sessions|team-size)=(\d+)$/);
|
|
348
|
-
if (sessionEq) {
|
|
349
|
-
explicitSession = normalizeTeamAgentSessions(sessionEq[1]);
|
|
54
|
+
if (/^--(?:max-agents|max-sessions|max-team)$/.test(arg)) {
|
|
55
|
+
explicitSession = DEFAULT_MAX_TEAM_AGENT_SESSIONS;
|
|
350
56
|
if (!explicitExecutor)
|
|
351
|
-
roleCounts.executor =
|
|
57
|
+
roleCounts.executor = DEFAULT_MAX_TEAM_AGENT_SESSIONS;
|
|
352
58
|
continue;
|
|
353
59
|
}
|
|
354
|
-
|
|
355
|
-
const role = flagRole ? normalizeTeamRole(flagRole[1]) : null;
|
|
356
|
-
if (role && args[i + 1] && /^\d+$/.test(String(args[i + 1]))) {
|
|
357
|
-
roleCounts[role] = normalizeTeamAgentSessions(args[i + 1], roleCounts[role] || 1);
|
|
358
|
-
if (role === 'executor')
|
|
359
|
-
explicitExecutor = true;
|
|
60
|
+
if (/^--(?:work-items|target-active-slots|minimum-work-items|max-queue-expansion|ollama-model|local-model-model|ollama-base-url|local-model-base-url)$/.test(arg)) {
|
|
360
61
|
i++;
|
|
361
62
|
continue;
|
|
362
63
|
}
|
|
363
|
-
if (/^--(?:
|
|
364
|
-
i++;
|
|
64
|
+
if (/^--(?:work-items|target-active-slots|minimum-work-items|max-queue-expansion)=/.test(arg))
|
|
365
65
|
continue;
|
|
366
|
-
}
|
|
367
66
|
if (/^--(?:ollama-model|local-model-model|ollama-base-url|local-model-base-url)=/.test(arg))
|
|
368
67
|
continue;
|
|
369
|
-
if (
|
|
68
|
+
if (/^--(?:json|open-zellij|zellij-open|no-open-zellij|no-zellij|no-attach|separate-session|new-session|legacy-team-session|ollama|local-model|no-ollama|no-local-model)$/.test(arg))
|
|
370
69
|
continue;
|
|
371
70
|
const consumed = consumeTeamSpecText(arg, { roleCounts, explicitExecutor, explicitSession });
|
|
372
71
|
roleCounts = consumed.roleCounts;
|
|
@@ -378,15 +77,18 @@ export function parseTeamSpecArgs(args = []) {
|
|
|
378
77
|
return { cleanArgs, ...normalizeTeamSpec({ roleCounts, agentSessions: explicitSession }) };
|
|
379
78
|
}
|
|
380
79
|
export function parseTeamSpecText(text = '') {
|
|
381
|
-
let roleCounts = { ...DEFAULT_TEAM_ROLE_COUNTS };
|
|
382
|
-
let explicitSession = null;
|
|
383
80
|
const wantsMaxAgents = /\b(max|maximum|maximal|available agents?)\b|최대|가용가능/i.test(String(text || ''));
|
|
384
|
-
const consumed = consumeTeamSpecText(text, { roleCounts, explicitExecutor: false, explicitSession });
|
|
385
|
-
roleCounts = consumed.roleCounts;
|
|
386
|
-
explicitSession = consumed.explicitSession;
|
|
81
|
+
const consumed = consumeTeamSpecText(text, { roleCounts: { ...DEFAULT_TEAM_ROLE_COUNTS }, explicitExecutor: false, explicitSession: null });
|
|
387
82
|
if (wantsMaxAgents && !consumed.explicitExecutor)
|
|
388
|
-
roleCounts.executor = DEFAULT_MAX_TEAM_AGENT_SESSIONS;
|
|
389
|
-
return {
|
|
83
|
+
consumed.roleCounts.executor = DEFAULT_MAX_TEAM_AGENT_SESSIONS;
|
|
84
|
+
return {
|
|
85
|
+
prompt: consumed.prompt,
|
|
86
|
+
...normalizeTeamSpec({
|
|
87
|
+
roleCounts: consumed.roleCounts,
|
|
88
|
+
agentSessions: consumed.explicitSession ?? (wantsMaxAgents ? consumed.roleCounts.executor : undefined),
|
|
89
|
+
prompt: consumed.prompt
|
|
90
|
+
})
|
|
91
|
+
};
|
|
390
92
|
}
|
|
391
93
|
export function normalizeTeamSpec(opts = {}) {
|
|
392
94
|
const roleCounts = normalizeTeamRoleCounts(opts.roleCounts);
|
|
@@ -394,9 +96,8 @@ export function normalizeTeamSpec(opts = {}) {
|
|
|
394
96
|
roleCounts.executor = normalizeTeamAgentSessions(opts.agentSessions, roleCounts.executor);
|
|
395
97
|
}
|
|
396
98
|
const bundleSize = normalizeTeamAgentSessions(roleCounts.executor, DEFAULT_TEAM_ROLE_COUNTS.executor);
|
|
397
|
-
const
|
|
398
|
-
|
|
399
|
-
return { agentSessions, bundleSize, roleCounts, roster: buildTeamRoster(roleCounts, { prompt: opts.prompt || opts.task || '' }) };
|
|
99
|
+
const agentSessions = Math.max(normalizeTeamAgentSessions(opts.agentSessions ?? bundleSize), normalizeTeamAgentSessions(roleCounts.reviewer, MIN_TEAM_REVIEWER_LANES));
|
|
100
|
+
return { agentSessions, bundleSize, roleCounts, roster: buildTeamRoster(roleCounts) };
|
|
400
101
|
}
|
|
401
102
|
export function normalizeTeamRoleCounts(input = {}) {
|
|
402
103
|
const counts = { ...DEFAULT_TEAM_ROLE_COUNTS };
|
|
@@ -408,496 +109,59 @@ export function normalizeTeamRoleCounts(input = {}) {
|
|
|
408
109
|
counts.reviewer = Math.max(MIN_TEAM_REVIEWER_LANES, counts.reviewer ?? 0);
|
|
409
110
|
return counts;
|
|
410
111
|
}
|
|
411
|
-
export function buildTeamRoster(roleCounts = DEFAULT_TEAM_ROLE_COUNTS
|
|
112
|
+
export function buildTeamRoster(roleCounts = DEFAULT_TEAM_ROLE_COUNTS) {
|
|
412
113
|
const counts = normalizeTeamRoleCounts(roleCounts);
|
|
413
|
-
const prompt = String(opts.prompt || opts.task || '');
|
|
414
114
|
const bundleSize = normalizeTeamAgentSessions(counts.executor);
|
|
415
|
-
const
|
|
416
|
-
const
|
|
417
|
-
const
|
|
418
|
-
const
|
|
419
|
-
const
|
|
420
|
-
|
|
421
|
-
const developmentExecutors = numberedAgents('executor', bundleSize, 'Capable developer executor: owns one disjoint implementation slice and coordinates without reverting others.', 'executor', { prompt });
|
|
422
|
-
const validationReviewers = numberedAgents('reviewer', counts.reviewer, 'Strict reviewer: adversarial about correctness, safety, DB risk, tests, regressions, and unsupported claims.', 'reviewer', { prompt });
|
|
423
|
-
const validationUsers = numberedAgents('user', counts.user, 'Impatient final user acceptance persona: low-context, self-interested, stubborn, dislikes inconvenience, rejects clever work that feels annoying.', 'user', { prompt });
|
|
424
|
-
return {
|
|
425
|
-
role_counts: counts,
|
|
426
|
-
bundle_size: bundleSize,
|
|
427
|
-
analysis_team: nativeAgents.map((agent) => ({ ...agent, write_policy: 'bounded workspace-write native analysis lease', output: 'team-analysis.md' })),
|
|
428
|
-
debate_team: debateTeam,
|
|
429
|
-
development_team: developmentExecutors.map((agent) => ({ ...agent, write_policy: 'workspace-write with explicit ownership' })),
|
|
430
|
-
validation_team: [
|
|
431
|
-
...validationReviewers.map((agent) => ({ ...agent, write_policy: 'read-only strict review' })),
|
|
432
|
-
...validationUsers.map((agent) => ({ ...agent, phase_role: 'acceptance_persona' }))
|
|
433
|
-
],
|
|
434
|
-
all_agents: [...nativeAgents, ...debateTeam, ...developmentExecutors, ...validationReviewers, ...validationUsers]
|
|
435
|
-
};
|
|
115
|
+
const numbered = (prefix, count, role = prefix) => Array.from({ length: normalizeTeamAgentSessions(count, 1) }, (_, i) => ({ id: `${prefix}_${i + 1}`, role, index: i + 1 }));
|
|
116
|
+
const analysis = numbered('native_agent', bundleSize, 'analysis');
|
|
117
|
+
const debate = [...numbered('debate_user', counts.user, 'user'), ...numbered('debate_planner', counts.planner, 'planner'), ...numbered('debate_reviewer', counts.reviewer, 'reviewer'), ...numbered('debate_executor', bundleSize, 'executor')].slice(0, bundleSize);
|
|
118
|
+
const development = numbered('executor', bundleSize, 'executor');
|
|
119
|
+
const validation = [...numbered('reviewer', counts.reviewer, 'reviewer'), ...numbered('user', counts.user, 'user')];
|
|
120
|
+
return { role_counts: counts, bundle_size: bundleSize, analysis_team: analysis, debate_team: debate, development_team: development, validation_team: validation, all_agents: [...analysis, ...debate, ...development, ...validation] };
|
|
436
121
|
}
|
|
437
122
|
export function formatRoleCounts(roleCounts = DEFAULT_TEAM_ROLE_COUNTS) {
|
|
438
|
-
|
|
439
|
-
return Object.entries(counts).map(([role, count]) => `${role}:${count}`).join(' ');
|
|
440
|
-
}
|
|
441
|
-
function numberedAgents(prefix, count, persona, role = prefix, opts = {}) {
|
|
442
|
-
return Array.from({ length: normalizeTeamAgentSessions(count, 1) }, (_, i) => {
|
|
443
|
-
const id = `${prefix}_${i + 1}`;
|
|
444
|
-
return { id, role, index: i + 1, persona, ...teamAgentReasoning({ prompt: opts.prompt || '', role, id }) };
|
|
445
|
-
});
|
|
446
|
-
}
|
|
447
|
-
function formatRosterLine(agent = {}) {
|
|
448
|
-
return `- ${agent.id}: ${agent.persona} [reasoning: ${formatAgentReasoning(agent)}]`;
|
|
449
|
-
}
|
|
450
|
-
function composeDebateTeam({ users, planners, reviewers, executors, bundleSize }) {
|
|
451
|
-
const selected = [];
|
|
452
|
-
const used = new Set();
|
|
453
|
-
const add = (agent) => {
|
|
454
|
-
if (!agent || selected.length >= bundleSize || used.has(agent.id))
|
|
455
|
-
return;
|
|
456
|
-
selected.push(agent);
|
|
457
|
-
used.add(agent.id);
|
|
458
|
-
};
|
|
459
|
-
add(users[0]);
|
|
460
|
-
add(planners[0]);
|
|
461
|
-
add(executors[0]);
|
|
462
|
-
for (const agent of reviewers)
|
|
463
|
-
add(agent);
|
|
464
|
-
for (const agent of users.slice(1))
|
|
465
|
-
add(agent);
|
|
466
|
-
for (const agent of planners.slice(1))
|
|
467
|
-
add(agent);
|
|
468
|
-
for (const agent of executors.slice(1))
|
|
469
|
-
add(agent);
|
|
470
|
-
return selected.slice(0, bundleSize);
|
|
471
|
-
}
|
|
472
|
-
function parseRolePair(token) {
|
|
473
|
-
const match = String(token || '').match(/^([A-Za-z][A-Za-z_-]*):(\d+)$/);
|
|
474
|
-
if (!match)
|
|
475
|
-
return null;
|
|
476
|
-
const role = normalizeTeamRole(match[1]);
|
|
477
|
-
if (!role)
|
|
478
|
-
return null;
|
|
479
|
-
return { role, count: normalizeTeamAgentSessions(match[2], DEFAULT_TEAM_ROLE_COUNTS[role] || 1) };
|
|
123
|
+
return Object.entries(normalizeTeamRoleCounts(roleCounts)).map(([role, count]) => `${role}:${count}`).join(' ');
|
|
480
124
|
}
|
|
481
|
-
function
|
|
482
|
-
const
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
125
|
+
function parseBudgetOrRoleToken(token, roleCounts, explicitExecutor, explicitSession) {
|
|
126
|
+
const state = { consumed: false, roleCounts, explicitExecutor, explicitSession };
|
|
127
|
+
const budget = token.match(/^(\d+):(agents?|sessions?|team)$/i);
|
|
128
|
+
if (budget) {
|
|
129
|
+
const count = normalizeTeamAgentSessions(budget[1], DEFAULT_TEAM_ROLE_COUNTS.executor);
|
|
130
|
+
if (!explicitExecutor)
|
|
131
|
+
state.roleCounts = { ...roleCounts, executor: count };
|
|
132
|
+
return { ...state, consumed: true, explicitSession: count };
|
|
133
|
+
}
|
|
134
|
+
const rolePair = token.match(/^(?:--)?([A-Za-z][A-Za-z_-]*)(?::|=)(\d+)$/);
|
|
135
|
+
const role = rolePair ? normalizeTeamRole(rolePair[1]) : null;
|
|
136
|
+
if (!rolePair || !role)
|
|
137
|
+
return state;
|
|
138
|
+
const count = normalizeTeamAgentSessions(rolePair[2], DEFAULT_TEAM_ROLE_COUNTS[role] || 1);
|
|
139
|
+
return { consumed: true, roleCounts: { ...roleCounts, [role]: count }, explicitExecutor: explicitExecutor || role === 'executor', explicitSession };
|
|
140
|
+
}
|
|
141
|
+
function consumeTeamSpecText(text, state) {
|
|
142
|
+
let roleCounts = { ...(state.roleCounts || DEFAULT_TEAM_ROLE_COUNTS) };
|
|
489
143
|
let explicitExecutor = state.explicitExecutor === true;
|
|
490
144
|
let explicitSession = state.explicitSession ?? null;
|
|
491
|
-
const prompt = String(text || '')
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
const parsed =
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
145
|
+
const prompt = String(text || '')
|
|
146
|
+
.replace(/\b(\d+):(agents?|sessions?|team)\b/gi, (token) => {
|
|
147
|
+
const parsed = parseBudgetOrRoleToken(token, roleCounts, explicitExecutor, explicitSession);
|
|
148
|
+
roleCounts = parsed.roleCounts;
|
|
149
|
+
explicitExecutor = parsed.explicitExecutor;
|
|
150
|
+
explicitSession = parsed.explicitSession;
|
|
151
|
+
return parsed.consumed ? '' : token;
|
|
152
|
+
})
|
|
153
|
+
.replace(/\b([A-Za-z][A-Za-z_-]*):(\d+)\b/g, (token) => {
|
|
154
|
+
const parsed = parseBudgetOrRoleToken(token, roleCounts, explicitExecutor, explicitSession);
|
|
155
|
+
roleCounts = parsed.roleCounts;
|
|
156
|
+
explicitExecutor = parsed.explicitExecutor;
|
|
157
|
+
explicitSession = parsed.explicitSession;
|
|
158
|
+
return parsed.consumed ? '' : token;
|
|
159
|
+
})
|
|
160
|
+
.replace(/\s+/g, ' ')
|
|
161
|
+
.trim();
|
|
508
162
|
return { prompt, roleCounts, explicitExecutor, explicitSession };
|
|
509
163
|
}
|
|
510
164
|
function normalizeTeamRole(role) {
|
|
511
165
|
return ROLE_ALIASES[String(role || '').trim().toLowerCase().replace(/[^a-z_-]/g, '')] || null;
|
|
512
166
|
}
|
|
513
|
-
export async function appendTeamEvent(dir, event) {
|
|
514
|
-
const files = teamLogPaths(dir);
|
|
515
|
-
const record = normalizeEvent(event);
|
|
516
|
-
await appendJsonlBounded(files.transcript, record, 1024 * 1024);
|
|
517
|
-
const dashboard = await readJson(files.dashboard, null);
|
|
518
|
-
if (dashboard) {
|
|
519
|
-
dashboard.updated_at = record.ts;
|
|
520
|
-
dashboard.latest_messages = [...(dashboard.latest_messages || []), record].slice(-20);
|
|
521
|
-
const agent = record.agent || 'unknown';
|
|
522
|
-
const terminalStatus = terminalTeamAgentStatusFromEvent(record);
|
|
523
|
-
dashboard.agents ||= {};
|
|
524
|
-
dashboard.agents[agent] ||= {};
|
|
525
|
-
dashboard.agents[agent].status = terminalStatus || record.type || 'active';
|
|
526
|
-
dashboard.agents[agent].phase = record.phase || null;
|
|
527
|
-
dashboard.agents[agent].last_seen = record.ts;
|
|
528
|
-
if (terminalStatus)
|
|
529
|
-
dashboard.agents[agent].closed_at = record.ts;
|
|
530
|
-
await writeJsonAtomic(files.dashboard, dashboard);
|
|
531
|
-
}
|
|
532
|
-
const current = await readText(files.live, teamLiveMarkdown('unknown', 'unknown'));
|
|
533
|
-
const target = record.to ? ` -> ${record.to}` : '';
|
|
534
|
-
const line = `\n- ${record.ts} [${record.phase || 'general'}] ${record.agent || 'unknown'}${target}: ${record.message || ''}${record.artifact ? ` (${record.artifact})` : ''}\n`;
|
|
535
|
-
await writeTextAtomic(files.live, trimLiveMarkdown(`${current.trimEnd()}${line}`));
|
|
536
|
-
return record;
|
|
537
|
-
}
|
|
538
|
-
export async function readTeamControl(dir) {
|
|
539
|
-
const control = await readJson(teamLogPaths(dir).control, defaultTeamControl(path.basename(dir)));
|
|
540
|
-
const cleanup = await readJson(path.join(dir, TEAM_SESSION_CLEANUP_ARTIFACT), null).catch(() => null);
|
|
541
|
-
if (!cleanup || (cleanup.passed !== true && cleanup.live_transcript_finalized !== true && cleanup.all_sessions_closed !== true))
|
|
542
|
-
return control;
|
|
543
|
-
return {
|
|
544
|
-
...defaultTeamControl(path.basename(dir)),
|
|
545
|
-
...control,
|
|
546
|
-
status: 'ended',
|
|
547
|
-
cleanup_requested: true,
|
|
548
|
-
cleanup_requested_at: cleanup.updated_at || cleanup.completed_at || cleanup.closed_at || control.cleanup_requested_at || 'artifact',
|
|
549
|
-
cleanup_requested_by: cleanup.agent || control.cleanup_requested_by || 'parent_orchestrator',
|
|
550
|
-
cleanup_reason: cleanup.reason || control.cleanup_reason || `${TEAM_SESSION_CLEANUP_ARTIFACT} passed.`,
|
|
551
|
-
final_message: cleanup.final_message || control.final_message || 'Team session ended. Lane follow loops stop and managed Zellij Team panes should close.'
|
|
552
|
-
};
|
|
553
|
-
}
|
|
554
|
-
export async function requestTeamSessionCleanup(dir, opts = {}) {
|
|
555
|
-
const files = teamLogPaths(dir);
|
|
556
|
-
const current = await readTeamControl(dir);
|
|
557
|
-
const next = {
|
|
558
|
-
...defaultTeamControl(current?.mission_id || opts.missionId || path.basename(dir)),
|
|
559
|
-
...current,
|
|
560
|
-
status: 'cleanup_requested',
|
|
561
|
-
cleanup_requested: true,
|
|
562
|
-
cleanup_requested_at: opts.ts || nowIso(),
|
|
563
|
-
cleanup_requested_by: opts.agent || 'parent_orchestrator',
|
|
564
|
-
cleanup_reason: opts.reason || 'Team session cleanup requested.',
|
|
565
|
-
final_message: opts.finalMessage || 'Team session ended. Lane/watch follow loops stop after this summary; managed Zellij Team panes are closed when reachable.'
|
|
566
|
-
};
|
|
567
|
-
await writeJsonAtomic(files.control, next);
|
|
568
|
-
return next;
|
|
569
|
-
}
|
|
570
|
-
export function teamCleanupRequested(control = {}) {
|
|
571
|
-
return Boolean(control?.cleanup_requested || control?.status === 'cleanup_requested' || control?.status === 'ended');
|
|
572
|
-
}
|
|
573
|
-
export function isTerminalTeamAgentStatus(status = '') {
|
|
574
|
-
const normalized = String(status || '').trim().toLowerCase();
|
|
575
|
-
return TERMINAL_TEAM_AGENT_STATUSES.has(normalized) || /(?:^|_)(?:done|complete|completed|closed|cleanup|cancelled|canceled|failed|ended|stopped)(?:_|$)/.test(normalized);
|
|
576
|
-
}
|
|
577
|
-
export function terminalTeamAgentStatusFromEvent(event = {}) {
|
|
578
|
-
const type = String(event.type || '').trim().toLowerCase();
|
|
579
|
-
if (isTerminalTeamAgentStatus(type))
|
|
580
|
-
return type;
|
|
581
|
-
const phase = String(event.phase || '').trim().toLowerCase();
|
|
582
|
-
if (isTerminalTeamAgentStatus(phase))
|
|
583
|
-
return phase;
|
|
584
|
-
const message = String(event.message || '').trim();
|
|
585
|
-
if (/^(?:done|complete|completed|finished|final|closed|agent_done|agent_closed)\b/i.test(message))
|
|
586
|
-
return 'completed';
|
|
587
|
-
if (/(?:작업|분석|구현|검토|리뷰|qa|lane|agent|에이전트).{0,40}(?:완료|종료|끝)/i.test(message))
|
|
588
|
-
return 'completed';
|
|
589
|
-
return '';
|
|
590
|
-
}
|
|
591
|
-
export function renderTeamCleanupSummary(control = {}) {
|
|
592
|
-
if (!teamCleanupRequested(control))
|
|
593
|
-
return '';
|
|
594
|
-
return [
|
|
595
|
-
'# SKS Team Session Cleanup',
|
|
596
|
-
'',
|
|
597
|
-
`Status: ${control.status || 'cleanup_requested'}`,
|
|
598
|
-
`Requested at: ${control.cleanup_requested_at || 'unknown'}`,
|
|
599
|
-
`Requested by: ${control.cleanup_requested_by || 'unknown'}`,
|
|
600
|
-
`Reason: ${control.cleanup_reason || 'Team session cleanup requested.'}`,
|
|
601
|
-
'',
|
|
602
|
-
control.final_message || 'Team session ended. managed Zellij Team panes are closed when reachable.'
|
|
603
|
-
].join('\n');
|
|
604
|
-
}
|
|
605
|
-
export async function readTeamDashboard(dir) {
|
|
606
|
-
return readJson(teamLogPaths(dir).dashboard, null);
|
|
607
|
-
}
|
|
608
|
-
export async function readTeamLive(dir) {
|
|
609
|
-
return readText(teamLogPaths(dir).live, '');
|
|
610
|
-
}
|
|
611
|
-
export async function readTeamTranscriptTail(dir, count = 20) {
|
|
612
|
-
const text = await readText(teamLogPaths(dir).transcript, '');
|
|
613
|
-
return text.split(/\n/).filter(Boolean).slice(-Math.max(1, Number(count) || 20));
|
|
614
|
-
}
|
|
615
|
-
export async function renderTeamAgentLane(dir, opts = {}) {
|
|
616
|
-
const agent = String(opts.agent || opts.agentId || 'parent_orchestrator');
|
|
617
|
-
const phase = opts.phase ? String(opts.phase) : null;
|
|
618
|
-
const lines = Math.max(1, Number(opts.lines) || 12);
|
|
619
|
-
const dashboard = await readTeamDashboard(dir);
|
|
620
|
-
const control = await readTeamControl(dir);
|
|
621
|
-
const runtime = await readJson(path.join(dir, TEAM_RUNTIME_TASKS_ARTIFACT), null);
|
|
622
|
-
const missionId = opts.missionId || dashboard?.mission_id || runtime?.mission_id || path.basename(dir);
|
|
623
|
-
const status = dashboard?.agents?.[agent] || {};
|
|
624
|
-
const runtimeTasks = Array.isArray(runtime?.tasks) ? runtime.tasks : Array.isArray(runtime) ? runtime : [];
|
|
625
|
-
const eventWindow = await readTeamTranscriptTail(dir, Math.max(lines * 8, 80));
|
|
626
|
-
const parsedWindow = eventWindow.map(parseTranscriptLine).filter(Boolean);
|
|
627
|
-
const aliases = teamLaneAliases(agent, parsedWindow, dashboard, runtimeTasks);
|
|
628
|
-
const aliasSet = new Set(aliases);
|
|
629
|
-
const statusAliases = aliases.length > 1 ? [...aliases.slice(1), aliases[0]] : aliases;
|
|
630
|
-
const laneStatus = statusAliases.map((id) => dashboard?.agents?.[id]).find((entry) => entry && entry.status && entry.status !== 'pending') || status;
|
|
631
|
-
const assignedTasks = runtimeTasks.filter((task) => aliasSet.has(task?.worker) || aliasSet.has(task?.agent_hint));
|
|
632
|
-
const agentEvents = parsedWindow.filter((event) => aliasSet.has(event?.agent) || aliases.some((id) => eventAddressedTo(event, id))).slice(-lines);
|
|
633
|
-
const directMessages = parsedWindow.filter((event) => event?.type === 'message' && aliases.some((id) => eventAddressedTo(event, id))).slice(-lines);
|
|
634
|
-
const chatEvents = uniqueTranscriptEvents([...agentEvents, ...directMessages])
|
|
635
|
-
.sort((a, b) => String(a.ts || '').localeCompare(String(b.ts || '')))
|
|
636
|
-
.slice(-lines);
|
|
637
|
-
const laneStyle = teamLaneTextStyle(agent);
|
|
638
|
-
const colorChat = terminalChatColorEnabled(opts);
|
|
639
|
-
return [
|
|
640
|
-
`# SKS Team Agent Lane`,
|
|
641
|
-
'',
|
|
642
|
-
`Mission: ${missionId}`,
|
|
643
|
-
`Agent: ${agent}`,
|
|
644
|
-
aliases.length > 1 ? `Mirrored agents: ${aliases.slice(1).join(', ')}` : null,
|
|
645
|
-
`Lane color: ${laneStyle.color_name}`,
|
|
646
|
-
`Requested phase: ${phase || 'any'}`,
|
|
647
|
-
teamCleanupRequested(control) ? `Cleanup: requested at ${control.cleanup_requested_at || 'unknown'}` : null,
|
|
648
|
-
'',
|
|
649
|
-
`## Agent Status`,
|
|
650
|
-
`- status: ${laneStatus.status || 'pending'}`,
|
|
651
|
-
`- phase: ${laneStatus.phase || 'unknown'}`,
|
|
652
|
-
`- last_seen: ${laneStatus.last_seen || 'never'}`,
|
|
653
|
-
'',
|
|
654
|
-
`## Assigned Runtime Tasks`,
|
|
655
|
-
...(runtime ? formatRuntimeTasks(assignedTasks) : ['- team-runtime-tasks.json not available yet.']),
|
|
656
|
-
'',
|
|
657
|
-
`## Codex Chat`,
|
|
658
|
-
...(chatEvents.length ? chatEvents.map((event) => formatChatTranscriptEvent(event, aliases[0], { color: colorChat })) : ['- waiting for live agent messages...']),
|
|
659
|
-
opts.includeGlobalTail ? '' : null,
|
|
660
|
-
opts.includeGlobalTail ? `## Global Tail` : null,
|
|
661
|
-
...(opts.includeGlobalTail
|
|
662
|
-
? (await readTeamTranscriptTail(dir, lines)).map(parseTranscriptLine).filter(Boolean).map(formatTranscriptEvent)
|
|
663
|
-
: []),
|
|
664
|
-
teamCleanupRequested(control) ? ['', renderTeamCleanupSummary(control)].join('\n') : null
|
|
665
|
-
].filter((line) => line !== null).join('\n');
|
|
666
|
-
}
|
|
667
|
-
export async function renderTeamWatch(dir, opts = {}) {
|
|
668
|
-
const lines = Math.max(1, Number(opts.lines) || 20);
|
|
669
|
-
const dashboard = await readTeamDashboard(dir);
|
|
670
|
-
const control = await readTeamControl(dir);
|
|
671
|
-
const runtime = await readJson(path.join(dir, TEAM_RUNTIME_TASKS_ARTIFACT), null);
|
|
672
|
-
const missionId = opts.missionId || dashboard?.mission_id || runtime?.mission_id || path.basename(dir);
|
|
673
|
-
const visibleAgents = visibleDashboardAgentEntries(dashboard);
|
|
674
|
-
const events = (await readTeamTranscriptTail(dir, lines)).map(parseTranscriptLine).filter(Boolean);
|
|
675
|
-
const runtimeTasks = Array.isArray(runtime?.tasks) ? runtime.tasks : Array.isArray(runtime) ? runtime : [];
|
|
676
|
-
return [
|
|
677
|
-
'# SKS Team Live Orchestration',
|
|
678
|
-
'',
|
|
679
|
-
`Mission: ${missionId}`,
|
|
680
|
-
`Updated: ${dashboard?.updated_at || 'unknown'}`,
|
|
681
|
-
`Agent session budget: ${dashboard?.agent_session_count || 'unknown'}`,
|
|
682
|
-
dashboard?.role_counts ? `Role counts: ${formatRoleCounts(dashboard.role_counts)}` : null,
|
|
683
|
-
teamCleanupRequested(control) ? `Cleanup: requested at ${control.cleanup_requested_at || 'unknown'}` : null,
|
|
684
|
-
'',
|
|
685
|
-
'## Split-Screen Map',
|
|
686
|
-
'- This overview pane follows the whole mission transcript.',
|
|
687
|
-
'- Run `sks team open-zellij ...` to materialize or reopen the split-pane Team Zellij view for an existing mission.',
|
|
688
|
-
'- Inside an SKS-owned Zellij session, Team panes are reconciled with the Codex pane on the left and Team lanes stacked on the right.',
|
|
689
|
-
'- Neighbor Zellij panes follow individual `sks team lane ... --agent <name>` chat-style views.',
|
|
690
|
-
'- Use `sks team event ...` to mirror native analysis, debate, executor, review, and verification status into the live panes.',
|
|
691
|
-
'- Use `sks team message ... --from <agent> --to <agent|all>` for bounded inter-agent communication in transcript/lane views.',
|
|
692
|
-
'- Use `sks team cleanup-zellij ...` at session end; follow loops show cleanup and managed Team panes close when reachable.',
|
|
693
|
-
'',
|
|
694
|
-
'## Cockpit Views',
|
|
695
|
-
'- Mission / Goal | Agents | MultiAgentV2 | Work Orders | Skills | Memory Health | Forget Queue',
|
|
696
|
-
'- Mistake Immunity | Tool Reliability | Harness Experiments | Dogfood Evidence | Code Structure | Statusline/Title',
|
|
697
|
-
'',
|
|
698
|
-
'## Visible Agent Lanes',
|
|
699
|
-
...(visibleAgents.length
|
|
700
|
-
? visibleAgents.map(([name, status]) => `- ${name}: ${status.status || 'pending'} | ${status.phase || 'unknown'} | last_seen:${status.last_seen || 'never'}`)
|
|
701
|
-
: ['- No agent lanes registered yet.']),
|
|
702
|
-
'',
|
|
703
|
-
'## Runtime Task Snapshot',
|
|
704
|
-
...(runtimeTasks.length ? formatRuntimeTasks(runtimeTasks.slice(0, 8)) : ['- team-runtime-tasks.json not available yet.']),
|
|
705
|
-
'',
|
|
706
|
-
'## Recent Mission Events',
|
|
707
|
-
...(events.length ? events.map(formatTranscriptEvent) : ['- No transcript events yet.']),
|
|
708
|
-
teamCleanupRequested(control) ? ['', renderTeamCleanupSummary(control)].join('\n') : null
|
|
709
|
-
].filter((line) => line !== null).join('\n');
|
|
710
|
-
}
|
|
711
|
-
function visibleDashboardAgentEntries(dashboard = {}) {
|
|
712
|
-
const agents = dashboard?.agents || {};
|
|
713
|
-
const roster = dashboard?.roster || {};
|
|
714
|
-
const analysis = uniqueAgentIds(roster.analysis_team || []);
|
|
715
|
-
const debate = uniqueAgentIds(roster.debate_team || []);
|
|
716
|
-
const development = uniqueAgentIds(roster.development_team || []);
|
|
717
|
-
const validation = uniqueAgentIds(roster.validation_team || []);
|
|
718
|
-
const reviewers = validation.filter((id) => /review|qa|validation/i.test(id));
|
|
719
|
-
const reviewerTarget = Math.max(MIN_TEAM_REVIEWER_LANES, Number(dashboard?.role_counts?.reviewer) || 0);
|
|
720
|
-
const reviewLanes = reviewers.slice(0, reviewerTarget);
|
|
721
|
-
const phaseRepresentatives = [development[0], debate[0]].filter(Boolean);
|
|
722
|
-
const requiredVisible = [...analysis, ...reviewLanes, ...phaseRepresentatives];
|
|
723
|
-
const concreteAgentIds = Object.keys(agents).filter((name) => name !== 'parent_orchestrator' && !DEFAULT_AGENTS.includes(name));
|
|
724
|
-
const fallbackAgentIds = Object.keys(agents).filter((name) => name !== 'parent_orchestrator');
|
|
725
|
-
const limit = Math.max(3, Number(dashboard?.agent_session_count) || 3, requiredVisible.length);
|
|
726
|
-
return uniqueAgentIds([...requiredVisible, ...concreteAgentIds, ...debate, ...development, ...validation, ...fallbackAgentIds])
|
|
727
|
-
.slice(0, limit)
|
|
728
|
-
.map((id) => [id, agents[id] || { status: 'pending', phase: null, last_seen: null }]);
|
|
729
|
-
}
|
|
730
|
-
function normalizeEvent(event = {}) {
|
|
731
|
-
return {
|
|
732
|
-
ts: event.ts || nowIso(),
|
|
733
|
-
agent: String(event.agent || 'parent_orchestrator'),
|
|
734
|
-
phase: String(event.phase || 'general'),
|
|
735
|
-
type: String(event.type || 'status'),
|
|
736
|
-
to: event.to ? String(event.to).slice(0, 200) : undefined,
|
|
737
|
-
message: String(event.message || '').slice(0, 4000),
|
|
738
|
-
artifact: event.artifact ? String(event.artifact) : undefined
|
|
739
|
-
};
|
|
740
|
-
}
|
|
741
|
-
function uniqueAgentIds(agents = []) {
|
|
742
|
-
const ids = [];
|
|
743
|
-
const seen = new Set();
|
|
744
|
-
for (const agent of agents) {
|
|
745
|
-
const id = agent?.id || String(agent || '');
|
|
746
|
-
if (!id || seen.has(id))
|
|
747
|
-
continue;
|
|
748
|
-
seen.add(id);
|
|
749
|
-
ids.push(id);
|
|
750
|
-
}
|
|
751
|
-
return ids;
|
|
752
|
-
}
|
|
753
|
-
function parseTranscriptLine(line) {
|
|
754
|
-
try {
|
|
755
|
-
return JSON.parse(line);
|
|
756
|
-
}
|
|
757
|
-
catch {
|
|
758
|
-
return { raw: String(line || '').slice(0, 1000) };
|
|
759
|
-
}
|
|
760
|
-
}
|
|
761
|
-
function formatTranscriptEvent(event = {}) {
|
|
762
|
-
if (event.raw)
|
|
763
|
-
return `- ${event.raw}`;
|
|
764
|
-
const parts = [
|
|
765
|
-
event.ts || 'no-ts',
|
|
766
|
-
`[${event.phase || 'general'}]`,
|
|
767
|
-
event.agent || 'unknown',
|
|
768
|
-
event.to ? `-> ${event.to}` : null,
|
|
769
|
-
event.type ? `(${event.type})` : null
|
|
770
|
-
].filter(Boolean);
|
|
771
|
-
const suffix = event.artifact ? ` (${event.artifact})` : '';
|
|
772
|
-
return `- ${parts.join(' ')}: ${String(event.message || '').slice(0, 500)}${suffix}`;
|
|
773
|
-
}
|
|
774
|
-
function uniqueTranscriptEvents(events = []) {
|
|
775
|
-
const seen = new Set();
|
|
776
|
-
const out = [];
|
|
777
|
-
for (const event of events) {
|
|
778
|
-
const key = event?.raw || [event?.ts, event?.agent, event?.to, event?.type, event?.message].map((value) => String(value || '')).join('\t');
|
|
779
|
-
if (seen.has(key))
|
|
780
|
-
continue;
|
|
781
|
-
seen.add(key);
|
|
782
|
-
out.push(event);
|
|
783
|
-
}
|
|
784
|
-
return out;
|
|
785
|
-
}
|
|
786
|
-
function formatChatTranscriptEvent(event = {}, laneAgent = '', opts = {}) {
|
|
787
|
-
if (event.raw)
|
|
788
|
-
return codexChatBlock({ speaker: 'system', kind: 'raw', style: teamLaneTextStyle('overview'), color: opts.color, message: event.raw });
|
|
789
|
-
const from = event.agent || 'unknown';
|
|
790
|
-
const ts = event.ts ? `${event.ts} ` : '';
|
|
791
|
-
const artifact = event.artifact ? ` (${event.artifact})` : '';
|
|
792
|
-
const isLaneAgent = String(from) === String(laneAgent);
|
|
793
|
-
return codexChatBlock({
|
|
794
|
-
speaker: isLaneAgent ? `me (${from})` : from,
|
|
795
|
-
to: event.to || '',
|
|
796
|
-
kind: event.type || 'message',
|
|
797
|
-
meta: ts.trim(),
|
|
798
|
-
style: teamLaneTextStyle(from),
|
|
799
|
-
color: opts.color,
|
|
800
|
-
message: `${String(event.message || '').slice(0, 500)}${artifact}`
|
|
801
|
-
});
|
|
802
|
-
}
|
|
803
|
-
function codexChatBlock({ speaker = 'agent', to = '', kind = '', meta = '', style = {}, color = false, message = '' } = {}) {
|
|
804
|
-
const role = style?.role || 'agent';
|
|
805
|
-
const roleKind = [kind, role].filter(Boolean).join('/');
|
|
806
|
-
const target = to ? ` -> ${to}` : '';
|
|
807
|
-
const header = [
|
|
808
|
-
colorizeChatText(`${speaker}${target}`, style, color, { bold: true }),
|
|
809
|
-
roleKind ? colorizeChatText(`[${roleKind}]`, style, color) : null,
|
|
810
|
-
meta ? colorizeChatText(`| ${meta}`, { color_name: 'Gray' }, color) : null
|
|
811
|
-
].filter(Boolean).join(' ');
|
|
812
|
-
const border = (text) => colorizeChatText(text, style, color);
|
|
813
|
-
const body = String(message || '').split(/\r?\n/).map((line) => `${border('│')} ${colorizeChatText(line || ' ', style, color)}`).join('\n');
|
|
814
|
-
return [`${border('╭─')} ${header}`, body || `${border('│')} `, border('╰─')].join('\n');
|
|
815
|
-
}
|
|
816
|
-
function terminalChatColorEnabled(opts = {}) {
|
|
817
|
-
if (Object.prototype.hasOwnProperty.call(opts, 'color'))
|
|
818
|
-
return Boolean(opts.color);
|
|
819
|
-
if (process.env.NO_COLOR)
|
|
820
|
-
return false;
|
|
821
|
-
return Boolean(process.stdout?.isTTY);
|
|
822
|
-
}
|
|
823
|
-
function colorizeChatText(text, style = {}, enabled = false, opts = {}) {
|
|
824
|
-
if (!enabled)
|
|
825
|
-
return text;
|
|
826
|
-
const colorName = String(style?.color_name || 'gray').toLowerCase();
|
|
827
|
-
const colorCode = CHAT_COLOR_CODES[colorName] || CHAT_COLOR_CODES.gray;
|
|
828
|
-
const code = opts.bold ? `1;${colorCode}` : colorCode;
|
|
829
|
-
return `\x1b[${code}m${text}\x1b[0m`;
|
|
830
|
-
}
|
|
831
|
-
function eventAddressedTo(event = {}, agent = '') {
|
|
832
|
-
if (!event?.to)
|
|
833
|
-
return false;
|
|
834
|
-
const target = String(event.to || '').trim().toLowerCase();
|
|
835
|
-
const name = String(agent || '').trim().toLowerCase();
|
|
836
|
-
return target === name || target === 'all' || target === '*' || target === 'broadcast';
|
|
837
|
-
}
|
|
838
|
-
function teamLaneAliases(agent = '', events = [], dashboard = null, runtimeTasks = []) {
|
|
839
|
-
const primary = String(agent || '').trim();
|
|
840
|
-
if (!primary)
|
|
841
|
-
return [];
|
|
842
|
-
const aliases = [primary];
|
|
843
|
-
const ordinal = numberedLaneOrdinal(primary);
|
|
844
|
-
if (!ordinal)
|
|
845
|
-
return aliases;
|
|
846
|
-
const role = teamLaneTextStyle(primary).role;
|
|
847
|
-
const candidates = uniqueAgentIds([
|
|
848
|
-
...Object.keys(dashboard?.agents || {}),
|
|
849
|
-
...events.map((event) => event?.agent).filter(Boolean),
|
|
850
|
-
...runtimeTasks.flatMap((task) => [task?.worker, task?.agent_hint]).filter(Boolean)
|
|
851
|
-
])
|
|
852
|
-
.filter((id) => id !== primary)
|
|
853
|
-
.filter((id) => !DEFAULT_AGENTS.includes(id))
|
|
854
|
-
.filter((id) => teamLaneTextStyle(id).role === role)
|
|
855
|
-
.filter((id) => !numberedLaneOrdinal(id));
|
|
856
|
-
const concrete = candidates[ordinal - 1];
|
|
857
|
-
if (concrete)
|
|
858
|
-
aliases.push(concrete);
|
|
859
|
-
return aliases;
|
|
860
|
-
}
|
|
861
|
-
function numberedLaneOrdinal(agent = '') {
|
|
862
|
-
const match = String(agent || '').match(/_(\d+)$/);
|
|
863
|
-
return match ? Number(match[1]) : 0;
|
|
864
|
-
}
|
|
865
|
-
function teamLaneTextStyle(agentId = '') {
|
|
866
|
-
const id = String(agentId || '').toLowerCase();
|
|
867
|
-
if (!id || id === 'mission_overview' || id === 'overview')
|
|
868
|
-
return { role: 'overview', color_name: 'Blue' };
|
|
869
|
-
if (/analysis|native_agent/.test(id))
|
|
870
|
-
return { role: 'agent', color_name: 'Cyan' };
|
|
871
|
-
if (/debate|consensus|planner|user/.test(id))
|
|
872
|
-
return { role: 'planning', color_name: 'Yellow' };
|
|
873
|
-
if (/db|safety/.test(id))
|
|
874
|
-
return { role: 'safety', color_name: 'Magenta' };
|
|
875
|
-
if (/review|qa|validation/.test(id))
|
|
876
|
-
return { role: 'review', color_name: 'Red' };
|
|
877
|
-
if (/executor|implementation|worker|developer/.test(id))
|
|
878
|
-
return { role: 'execution', color_name: 'Green' };
|
|
879
|
-
return { role: 'planning', color_name: 'Yellow' };
|
|
880
|
-
}
|
|
881
|
-
function formatRuntimeTasks(tasks = []) {
|
|
882
|
-
if (!tasks.length)
|
|
883
|
-
return ['- No assigned runtime tasks found.'];
|
|
884
|
-
return tasks.slice(0, 12).map((task) => {
|
|
885
|
-
const details = [
|
|
886
|
-
task.status || 'pending',
|
|
887
|
-
task.phase || task.role || 'team',
|
|
888
|
-
task.depends_on?.length ? `deps:${task.depends_on.join(',')}` : null,
|
|
889
|
-
task.file_paths?.length ? `files:${task.file_paths.slice(0, 3).join(',')}` : null
|
|
890
|
-
].filter(Boolean).join(' | ');
|
|
891
|
-
return `- ${task.task_id || 'task'} ${task.subject || task.symbolic_id || 'untitled'} (${details})`;
|
|
892
|
-
});
|
|
893
|
-
}
|
|
894
|
-
function trimLiveMarkdown(text) {
|
|
895
|
-
if (Buffer.byteLength(text) <= MAX_LIVE_BYTES)
|
|
896
|
-
return text.endsWith('\n') ? text : `${text}\n`;
|
|
897
|
-
const marker = '## Live Events\n';
|
|
898
|
-
const i = text.indexOf(marker);
|
|
899
|
-
const head = i >= 0 ? text.slice(0, i + marker.length) : '# SKS Team Live Transcript\n\n## Live Events\n';
|
|
900
|
-
const tail = Buffer.from(text.slice(-MAX_LIVE_BYTES + Buffer.byteLength(head) - 80)).toString('utf8').replace(/^.*?\n/, '');
|
|
901
|
-
return `${head}\n- Older events were compacted; read team-transcript.jsonl for the bounded machine log.\n${tail.endsWith('\n') ? tail : `${tail}\n`}`;
|
|
902
|
-
}
|
|
903
167
|
//# sourceMappingURL=team-live.js.map
|