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
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import fs from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { ensureDir, nowIso, runProcess, writeJsonAtomic } from '../fsx.js';
|
|
4
|
+
import { withHeartbeat } from '../../cli/cli-theme.js';
|
|
4
5
|
import { createRequestedScopeContract } from '../safety/requested-scope-contract.js';
|
|
5
6
|
import { guardContextForRoute, guardedPackageInstall } from '../safety/mutation-guard.js';
|
|
6
7
|
import { mutationLedgerPath } from '../safety/mutation-ledger.js';
|
|
8
|
+
import { confirmRepair } from '../doctor/confirm-repair.js';
|
|
7
9
|
import { checkZellijCapability, ZELLIJ_MIN_VERSION } from './zellij-capability.js';
|
|
8
10
|
import { compareVersionLike } from './zellij-command.js';
|
|
9
11
|
import { askHomebrewInstallAllowed, HOMEBREW_INSTALL_COMMAND, resolveHomebrewInstallPolicy } from './homebrew-policy.js';
|
|
@@ -44,17 +46,20 @@ export async function repairZellijForSks(input) {
|
|
|
44
46
|
if (dryRun) {
|
|
45
47
|
return dryRunResult(root, input, env, before, latest, brew, mutationArtifact);
|
|
46
48
|
}
|
|
47
|
-
if (!autoApproved
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
:
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
return
|
|
49
|
+
if (!autoApproved) {
|
|
50
|
+
const approval = await confirmRepair({
|
|
51
|
+
autoApprove: autoApproved,
|
|
52
|
+
interactive: input.interactive === true,
|
|
53
|
+
question: before.status === 'missing'
|
|
54
|
+
? 'Zellij is missing. Install it with Homebrew now? [Y/n] '
|
|
55
|
+
: `Zellij ${before.version || 'unknown'} needs repair. Upgrade with Homebrew now? [Y/n] `
|
|
56
|
+
});
|
|
57
|
+
if (!approval.approved) {
|
|
58
|
+
const reason = approval.reason === 'non_interactive_requires_yes' ? approval.reason : 'operator_declined_zellij_repair';
|
|
59
|
+
return input.allowHeadlessFallback === true
|
|
60
|
+
? headlessResult(root, input, before, latest, brew, reason)
|
|
61
|
+
: manualResult(root, input, env, before, latest, brew, reason, approval.next_actions);
|
|
62
|
+
}
|
|
58
63
|
}
|
|
59
64
|
let brewBin = brew.bin;
|
|
60
65
|
let homebrewInstallAttempted = false;
|
|
@@ -76,7 +81,7 @@ export async function repairZellijForSks(input) {
|
|
|
76
81
|
: manualResult(root, input, env, before, latest, brew, policy.blockers[0] || 'homebrew_missing');
|
|
77
82
|
}
|
|
78
83
|
homebrewInstallAttempted = true;
|
|
79
|
-
const homebrewRun = await runHomebrewInstall(root, env);
|
|
84
|
+
const homebrewRun = await runHomebrewInstall(root, env, input.quiet === true);
|
|
80
85
|
if (homebrewRun.code !== 0) {
|
|
81
86
|
return persistSelfHeal(root, input.missionDir, {
|
|
82
87
|
schema: 'sks.zellij-self-heal.v1',
|
|
@@ -108,7 +113,7 @@ export async function repairZellijForSks(input) {
|
|
|
108
113
|
: install ? 'brew-install-zellij'
|
|
109
114
|
: 'brew-upgrade-zellij';
|
|
110
115
|
const command = `brew ${brewArgs.join(' ')}`;
|
|
111
|
-
const run = await runZellijBrew(root, env, brewBin, brewArgs, command);
|
|
116
|
+
const run = await runZellijBrew(root, env, brewBin, brewArgs, command, input.quiet === true);
|
|
112
117
|
if (run.code !== 0 && /already installed|already up-to-date/i.test(`${run.stdout}\n${run.stderr}`)) {
|
|
113
118
|
const after = await capabilitySnapshot(root, env, 'after-noop');
|
|
114
119
|
return persistSelfHeal(root, input.missionDir, {
|
|
@@ -246,7 +251,7 @@ async function findBrew(env) {
|
|
|
246
251
|
return { present: true, bin: 'brew' };
|
|
247
252
|
return { present: false, bin: null };
|
|
248
253
|
}
|
|
249
|
-
async function runZellijBrew(root, env, brewBin, args, command) {
|
|
254
|
+
async function runZellijBrew(root, env, brewBin, args, command, quiet = false) {
|
|
250
255
|
if (env.SKS_ZELLIJ_SELF_HEAL_FAKE_RUN === '1') {
|
|
251
256
|
await appendFakeBrewLog(env, args);
|
|
252
257
|
return { code: Number(env.SKS_ZELLIJ_SELF_HEAL_FAKE_RUN_CODE || 0), stdout: 'fake brew ok', stderr: '' };
|
|
@@ -257,7 +262,7 @@ async function runZellijBrew(root, env, brewBin, args, command) {
|
|
|
257
262
|
projectRoot: root,
|
|
258
263
|
overrides: { package_install: true, zellij_install: true }
|
|
259
264
|
});
|
|
260
|
-
|
|
265
|
+
const work = guardedPackageInstall(guardContextForRoute(root, contract, command), 'zellij', {
|
|
261
266
|
confirmed: true,
|
|
262
267
|
command: brewBin,
|
|
263
268
|
args,
|
|
@@ -265,8 +270,9 @@ async function runZellijBrew(root, env, brewBin, args, command) {
|
|
|
265
270
|
timeoutMs: 180000,
|
|
266
271
|
maxOutputBytes: 256 * 1024
|
|
267
272
|
}).catch((err) => ({ code: 1, stdout: '', stderr: errorMessage(err) }));
|
|
273
|
+
return quiet ? await work : await withHeartbeat('brew zellij repair', work, { warnAfterMs: 30_000 });
|
|
268
274
|
}
|
|
269
|
-
async function runHomebrewInstall(root, env) {
|
|
275
|
+
async function runHomebrewInstall(root, env, quiet = false) {
|
|
270
276
|
if (env.SKS_ZELLIJ_SELF_HEAL_FAKE_RUN === '1') {
|
|
271
277
|
await appendFakeBrewLog(env, ['install-homebrew']);
|
|
272
278
|
return { code: Number(env.SKS_ZELLIJ_SELF_HEAL_FAKE_HOMEBREW_CODE || 0), stdout: 'fake homebrew install ok', stderr: '' };
|
|
@@ -277,7 +283,7 @@ async function runHomebrewInstall(root, env) {
|
|
|
277
283
|
projectRoot: root,
|
|
278
284
|
overrides: { package_install: true, zellij_install: true }
|
|
279
285
|
});
|
|
280
|
-
|
|
286
|
+
const work = guardedPackageInstall(guardContextForRoute(root, contract, HOMEBREW_INSTALL_COMMAND), 'homebrew', {
|
|
281
287
|
confirmed: true,
|
|
282
288
|
command: '/bin/bash',
|
|
283
289
|
args: ['-c', 'curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh | /bin/bash'],
|
|
@@ -285,6 +291,7 @@ async function runHomebrewInstall(root, env) {
|
|
|
285
291
|
timeoutMs: 600000,
|
|
286
292
|
maxOutputBytes: 256 * 1024
|
|
287
293
|
}).catch((err) => ({ code: 1, stdout: '', stderr: errorMessage(err) }));
|
|
294
|
+
return quiet ? await work : await withHeartbeat('Homebrew install', work, { warnAfterMs: 60_000 });
|
|
288
295
|
}
|
|
289
296
|
async function appendFakeBrewLog(env, args) {
|
|
290
297
|
if (!env.SKS_FAKE_BREW_LOG)
|
|
@@ -342,7 +349,7 @@ async function dryRunResult(root, input, env, before, latest, brew, mutationArti
|
|
|
342
349
|
warnings: ['dry_run_no_mutation_performed']
|
|
343
350
|
});
|
|
344
351
|
}
|
|
345
|
-
async function manualResult(root, input, env, before, latest, brew, reason) {
|
|
352
|
+
async function manualResult(root, input, env, before, latest, brew, reason, nextActions = []) {
|
|
346
353
|
const command = brew.present ? 'sks doctor --fix --yes' : 'sks doctor --fix --install-homebrew --yes';
|
|
347
354
|
return persistSelfHeal(root, input.missionDir, {
|
|
348
355
|
schema: 'sks.zellij-self-heal.v1',
|
|
@@ -359,7 +366,8 @@ async function manualResult(root, input, env, before, latest, brew, reason) {
|
|
|
359
366
|
mutation_guard_artifact: null,
|
|
360
367
|
homebrew: { present: brew.present, bin: brew.bin, install_attempted: false, install_allowed: false },
|
|
361
368
|
blockers: [reason],
|
|
362
|
-
warnings: []
|
|
369
|
+
warnings: [],
|
|
370
|
+
next_actions: nextActions.length ? nextActions : [`Run: ${command}`]
|
|
363
371
|
});
|
|
364
372
|
}
|
|
365
373
|
async function headlessResult(root, input, before, latest, brew, reason) {
|
|
@@ -392,19 +400,6 @@ async function persistSelfHeal(root, missionDir, result) {
|
|
|
392
400
|
await writeJsonAtomic(path.join(missionDir, 'zellij-self-heal.json'), normalized).catch(() => undefined);
|
|
393
401
|
return normalized;
|
|
394
402
|
}
|
|
395
|
-
async function askZellijRepairAllowed(question) {
|
|
396
|
-
if (!(process.stdin.isTTY && process.stdout.isTTY))
|
|
397
|
-
return false;
|
|
398
|
-
const rl = (await import('node:readline')).createInterface({ input: process.stdin, output: process.stdout });
|
|
399
|
-
try {
|
|
400
|
-
const answer = await new Promise((resolve) => rl.question(question, resolve));
|
|
401
|
-
const trimmed = String(answer || '').trim();
|
|
402
|
-
return trimmed === '' || /^(y|yes|예|네|응)$/i.test(trimmed);
|
|
403
|
-
}
|
|
404
|
-
finally {
|
|
405
|
-
rl.close();
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
403
|
function errorMessage(err) {
|
|
409
404
|
return err instanceof Error ? err.message : String(err);
|
|
410
405
|
}
|
|
@@ -1,76 +1,158 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { readZellijSlotTelemetrySnapshot } from './zellij-slot-telemetry.js';
|
|
4
|
+
import { resolveZellijTheme, paint, statusBadge, progressBar, elapsed, ANSI_CODES } from './zellij-theme.js';
|
|
4
5
|
export function renderZellijSlotPane(input) {
|
|
6
|
+
const theme = resolveZellijTheme();
|
|
7
|
+
const W = Math.max(20, theme.width - 4);
|
|
8
|
+
const t = (s, w = W) => trimInline(String(s ?? ''), w);
|
|
5
9
|
const mode = input.mode || 'compact-slots';
|
|
6
|
-
const maxLines = mode === 'compact-slots' ?
|
|
7
|
-
const task = trimInline(input.currentTask || input.currentFile || 'waiting for worker intake', 78);
|
|
8
|
-
const heartbeat = input.heartbeatAgeMs == null
|
|
9
|
-
? 'unknown'
|
|
10
|
-
: input.heartbeatAgeMs < 1000
|
|
11
|
-
? 'now'
|
|
12
|
-
: `${Math.max(1, Math.round(input.heartbeatAgeMs / 1000))}s ago`;
|
|
13
|
-
const files = firstNonEmptyList(input.changedFiles, input.patchFiles, input.plannedFiles, input.currentFile ? [input.currentFile] : []);
|
|
10
|
+
const maxLines = mode === 'compact-slots' ? 14 : mode === 'dashboard-plus-slots' ? 18 : 30;
|
|
14
11
|
const events = (input.eventLines || []).filter(Boolean).slice(-10);
|
|
15
12
|
const stdout = (input.stdoutTail || []).filter(Boolean).slice(-6);
|
|
16
13
|
const stderr = (input.stderrTail || []).filter(Boolean).slice(-1);
|
|
14
|
+
const fullDebug = mode === 'full-debug';
|
|
17
15
|
const fixtureLoopProof = String(input.backend || '').includes('fixture') || String(input.patchStatus || '').includes('fixture');
|
|
16
|
+
const meta = [input.model || input.provider || '?', input.serviceTier || '?'].filter(Boolean).join('·');
|
|
17
|
+
const head = `${statusBadge(theme, input.status || 'queued')} ${paint(theme, ANSI_CODES.bold, input.slotId)}` +
|
|
18
|
+
` ${t(input.role || 'worker', 12)} ${paint(theme, ANSI_CODES.dim, t(meta, 28))}`;
|
|
19
|
+
const prog = input.progress && input.progress.total > 0
|
|
20
|
+
? progressBar(theme, input.progress.done, input.progress.total)
|
|
21
|
+
: paint(theme, ANSI_CODES.dim, `elapsed ${elapsed(input.telemetryTs) || '-'} heartbeat ${formatHeartbeat(input.heartbeatAgeMs)}`);
|
|
22
|
+
const doing = `${paint(theme, ANSI_CODES.bold, '▸ ')}${t(input.currentTask || 'waiting for work item')}`;
|
|
23
|
+
const file = input.currentFile ? paint(theme, ANSI_CODES.dim, `file ${t(input.currentFile)}`) : null;
|
|
24
|
+
const worktree = input.worktreeId ? paint(theme, ANSI_CODES.dim, `worktree ${t(input.worktreeId, 32)}`) : null;
|
|
25
|
+
const patch = ((input.patchStatus && input.patchStatus !== 'queued') || (input.verifyStatus && input.verifyStatus !== 'queued'))
|
|
26
|
+
? `patch ${t(input.patchStatus || '-', 18)} · verify ${t(input.verifyStatus || '-', 18)}`
|
|
27
|
+
: null;
|
|
28
|
+
const blockers = (input.blockers || []).slice(0, 2).map((b) => paint(theme, ANSI_CODES.red, `! ${t(b)}`));
|
|
29
|
+
const tail = [
|
|
30
|
+
...stderr.slice(-1).map((line) => paint(theme, ANSI_CODES.red, `err ${t(line)}`)),
|
|
31
|
+
...stdout.slice(-3).map((line) => paint(theme, ANSI_CODES.dim, ` ${t(line)}`))
|
|
32
|
+
];
|
|
18
33
|
const rows = [
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
head,
|
|
35
|
+
prog,
|
|
36
|
+
doing,
|
|
37
|
+
file,
|
|
38
|
+
worktree,
|
|
39
|
+
patch,
|
|
40
|
+
input.qaAppHandoffPending ? `QA app handoff pending: ${t(input.qaAppHandoffArtifact || 'qa-loop/app-handoff.json')}` : null,
|
|
41
|
+
...blockers,
|
|
42
|
+
...tail,
|
|
43
|
+
...(fullDebug ? [
|
|
44
|
+
input.sessionId ? `session ${t(input.sessionId, 62)}` : null,
|
|
45
|
+
input.loopId ? `loop ${t(input.loopId, 28)} · ${t(input.loopRole || input.role || 'worker', 14)}` : null,
|
|
46
|
+
input.loopGate ? `gate ${t(input.loopGate)}` : null,
|
|
47
|
+
fixtureLoopProof ? 'fixture loop proof · not production execution' : null,
|
|
48
|
+
...events.map((event) => `event ${t(event)}`)
|
|
49
|
+
] : [])
|
|
35
50
|
].filter((row) => Boolean(row));
|
|
36
|
-
return frameSlotPane(
|
|
51
|
+
return frameSlotPane(input.slotId, rows.slice(0, Math.max(1, maxLines - 2)), theme);
|
|
37
52
|
}
|
|
38
53
|
export async function renderZellijSlotPaneFromArtifacts(input) {
|
|
39
|
-
const
|
|
54
|
+
const detail = await renderInputFromArtifactDir(input).catch(() => null);
|
|
40
55
|
if (input.missionId && input.missionId !== 'latest') {
|
|
41
|
-
const telemetry = await
|
|
42
|
-
|
|
43
|
-
|
|
56
|
+
const telemetry = await readZellijSlotTelemetrySnapshot(path.resolve(input.artifactRoot || input.artifactDir), input.missionId).catch(() => null);
|
|
57
|
+
const live = findTelemetrySlot(telemetry, input.slotId, input.generationIndex);
|
|
58
|
+
const merged = mergeRenderInputWithLiveTelemetry({
|
|
44
59
|
slotId: input.slotId,
|
|
45
60
|
generationIndex: input.generationIndex,
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
61
|
+
role: input.role ?? null,
|
|
62
|
+
backend: input.backend ?? null,
|
|
63
|
+
provider: input.provider ?? null,
|
|
64
|
+
model: input.model ?? null,
|
|
65
|
+
serviceTier: input.serviceTier ?? null,
|
|
66
|
+
reasoningEffort: input.reasoningEffort ?? null,
|
|
67
|
+
currentTask: input.currentTask ?? null,
|
|
68
|
+
status: 'launching',
|
|
69
|
+
mode: input.mode || 'compact-slots',
|
|
70
|
+
...(detail || {})
|
|
71
|
+
}, live);
|
|
72
|
+
return renderZellijSlotPane(merged);
|
|
57
73
|
}
|
|
58
|
-
if (artifactRender)
|
|
59
|
-
return artifactRender;
|
|
60
74
|
const fallbackInput = {
|
|
61
75
|
slotId: input.slotId,
|
|
62
76
|
generationIndex: input.generationIndex,
|
|
63
77
|
status: 'launching',
|
|
64
|
-
currentTask: 'waiting for worker intake',
|
|
78
|
+
currentTask: input.currentTask || 'waiting for worker intake',
|
|
65
79
|
mode: input.mode || 'compact-slots'
|
|
66
80
|
};
|
|
67
81
|
if (input.role !== undefined)
|
|
68
82
|
fallbackInput.role = input.role;
|
|
69
83
|
if (input.backend !== undefined)
|
|
70
84
|
fallbackInput.backend = input.backend;
|
|
71
|
-
|
|
85
|
+
if (input.provider !== undefined)
|
|
86
|
+
fallbackInput.provider = input.provider;
|
|
87
|
+
if (input.model !== undefined)
|
|
88
|
+
fallbackInput.model = input.model;
|
|
89
|
+
if (input.serviceTier !== undefined)
|
|
90
|
+
fallbackInput.serviceTier = input.serviceTier;
|
|
91
|
+
if (input.reasoningEffort !== undefined)
|
|
92
|
+
fallbackInput.reasoningEffort = input.reasoningEffort;
|
|
93
|
+
return renderZellijSlotPane(detail || fallbackInput);
|
|
94
|
+
}
|
|
95
|
+
function mergeRenderInputWithLiveTelemetry(detail, live) {
|
|
96
|
+
if (!live)
|
|
97
|
+
return detail;
|
|
98
|
+
return {
|
|
99
|
+
...detail,
|
|
100
|
+
status: live.status ?? detail.status,
|
|
101
|
+
currentTask: live.task_title || detail.currentTask || null,
|
|
102
|
+
currentFile: live.current_file || detail.currentFile || null,
|
|
103
|
+
role: live.role || detail.role || null,
|
|
104
|
+
backend: live.backend || detail.backend || null,
|
|
105
|
+
provider: live.provider || detail.provider || null,
|
|
106
|
+
serviceTier: live.service_tier || detail.serviceTier || null,
|
|
107
|
+
progress: live.progress ?? null,
|
|
108
|
+
blockers: live.blockers || [],
|
|
109
|
+
telemetryTs: live.latest_ts || null,
|
|
110
|
+
heartbeatAgeMs: live.latest_ts ? Math.max(0, Date.now() - Date.parse(live.latest_ts)) : detail.heartbeatAgeMs ?? null,
|
|
111
|
+
worktreeId: live.worktree_id || detail.worktreeId || null
|
|
112
|
+
};
|
|
72
113
|
}
|
|
73
114
|
async function renderZellijSlotPaneFromArtifactDir(input) {
|
|
115
|
+
const detail = await renderInputFromArtifactDir(input);
|
|
116
|
+
if (!detail)
|
|
117
|
+
return null;
|
|
118
|
+
return renderZellijSlotPane(detail);
|
|
119
|
+
}
|
|
120
|
+
async function renderInputFromArtifactDir(input) {
|
|
121
|
+
const envDefaults = {
|
|
122
|
+
provider: (input.provider ?? process.env.SKS_SLOT_PROVIDER) || null,
|
|
123
|
+
model: (input.model ?? process.env.SKS_SLOT_MODEL) || null,
|
|
124
|
+
serviceTier: (input.serviceTier ?? process.env.SKS_SLOT_TIER) || null,
|
|
125
|
+
reasoningEffort: (input.reasoningEffort ?? process.env.SKS_SLOT_REASONING) || null,
|
|
126
|
+
currentTask: (input.currentTask ?? process.env.SKS_SLOT_TASK) || null,
|
|
127
|
+
role: (input.role ?? process.env.SKS_SLOT_ROLE) || null
|
|
128
|
+
};
|
|
129
|
+
const detail = await renderInputFromArtifactDirRaw(input);
|
|
130
|
+
if (!detail) {
|
|
131
|
+
return {
|
|
132
|
+
slotId: input.slotId,
|
|
133
|
+
generationIndex: input.generationIndex,
|
|
134
|
+
role: envDefaults.role,
|
|
135
|
+
backend: input.backend || null,
|
|
136
|
+
provider: envDefaults.provider,
|
|
137
|
+
model: envDefaults.model,
|
|
138
|
+
serviceTier: envDefaults.serviceTier,
|
|
139
|
+
reasoningEffort: envDefaults.reasoningEffort,
|
|
140
|
+
currentTask: envDefaults.currentTask || 'waiting for worker intake',
|
|
141
|
+
status: 'launching',
|
|
142
|
+
mode: input.mode || 'compact-slots'
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
...detail,
|
|
147
|
+
role: detail.role || envDefaults.role,
|
|
148
|
+
provider: detail.provider || envDefaults.provider,
|
|
149
|
+
model: detail.model || envDefaults.model,
|
|
150
|
+
serviceTier: detail.serviceTier || envDefaults.serviceTier,
|
|
151
|
+
reasoningEffort: detail.reasoningEffort || envDefaults.reasoningEffort,
|
|
152
|
+
currentTask: detail.currentTask || envDefaults.currentTask
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
async function renderInputFromArtifactDirRaw(input) {
|
|
74
156
|
const artifactDir = path.resolve(input.artifactDir);
|
|
75
157
|
const result = await readJson(path.join(artifactDir, 'worker-result.json'));
|
|
76
158
|
const intake = await readJson(path.join(artifactDir, 'worker-intake.json'));
|
|
@@ -105,7 +187,7 @@ async function renderZellijSlotPaneFromArtifactDir(input) {
|
|
|
105
187
|
const qaAppHandoff = await readQaAppHandoffNearArtifactDir(artifactDir);
|
|
106
188
|
if (!result && !intake && !backendReport && !processReport && !paneReport && !codexProof && !localProof && !heartbeatMtime && !eventRows.length)
|
|
107
189
|
return null;
|
|
108
|
-
return
|
|
190
|
+
return {
|
|
109
191
|
slotId: input.slotId,
|
|
110
192
|
generationIndex: input.generationIndex,
|
|
111
193
|
sessionId: result?.session_id || intake?.agent?.session_id || backendReport?.session_id || null,
|
|
@@ -164,7 +246,7 @@ async function renderZellijSlotPaneFromArtifactDir(input) {
|
|
|
164
246
|
qaAppHandoffPending: ['pending', 'blocked_for_desktop_review'].includes(String(qaAppHandoff?.status || '')),
|
|
165
247
|
qaAppHandoffArtifact: qaAppHandoff?.artifact_path || null,
|
|
166
248
|
mode: input.mode || 'compact-slots'
|
|
167
|
-
}
|
|
249
|
+
};
|
|
168
250
|
}
|
|
169
251
|
async function readQaAppHandoffNearArtifactDir(artifactDir) {
|
|
170
252
|
let current = path.resolve(artifactDir);
|
|
@@ -226,78 +308,25 @@ export function buildZellijSlotPaneCommand(input) {
|
|
|
226
308
|
...(input.role ? ['--role', input.role] : []),
|
|
227
309
|
...(input.watch ? ['--watch'] : [])
|
|
228
310
|
];
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
// tail). Telemetry freshness only tells us the worker is alive — the user
|
|
242
|
-
// still needs to see WHAT the worker is doing right now.
|
|
243
|
-
const liveRows = fallbackRows;
|
|
244
|
-
if (slot.status === 'failed') {
|
|
245
|
-
return [
|
|
246
|
-
`${slot.slot_id} gen-${slot.generation_index} · FAILED`,
|
|
247
|
-
...staleRows,
|
|
248
|
-
...liveRows,
|
|
249
|
-
`blocker: ${trimInline(slot.blockers[0] || 'worker_failed', 78)}`,
|
|
250
|
-
`artifact: ${trimInline(slot.artifact_paths[slot.artifact_paths.length - 1] || '-', 78)}`
|
|
251
|
-
].join('\n');
|
|
252
|
-
}
|
|
253
|
-
if (slot.status === 'completed' || slot.status === 'drained') {
|
|
254
|
-
return [
|
|
255
|
-
`${slot.slot_id} gen-${slot.generation_index} · done`,
|
|
256
|
-
...staleRows,
|
|
257
|
-
...liveRows,
|
|
258
|
-
`artifacts ${slot.artifact_paths.length} · ${slot.latest_event_type === 'verification_passed' ? 'verify passed' : 'verify queued'}`,
|
|
259
|
-
'closing in 3s'
|
|
260
|
-
].join('\n');
|
|
261
|
-
}
|
|
262
|
-
const backend = [slot.backend, slot.service_tier, slot.worktree_id].filter((value) => value && value !== 'unknown').join(' · ') || 'worker';
|
|
263
|
-
const heartbeat = slot.latest_ts ? `${Math.max(0, Math.round((Date.now() - Date.parse(slot.latest_ts)) / 1000))}s` : '?';
|
|
264
|
-
return [
|
|
265
|
-
`${slot.slot_id} gen-${slot.generation_index} · ${trimInline(slot.role || 'worker', 28)}`,
|
|
266
|
-
...staleRows,
|
|
267
|
-
...liveRows,
|
|
268
|
-
trimInline(backend, 78),
|
|
269
|
-
`${slot.status}: ${trimInline(slot.task_title || 'worker task', 68)}`,
|
|
270
|
-
`${formatTelemetryProgress(slot.progress, slot.started_at || slot.latest_ts)} · latest ${slot.latest_event_type} ${heartbeat}`,
|
|
271
|
-
`${slot.latest_event_type === 'patch_candidate' ? 'patch candidate' : 'patch'}: ${slot.latest_event_type === 'patch_candidate' ? 'queued' : trimInline(slot.current_file || '-', 42)}`
|
|
272
|
-
].join('\n');
|
|
273
|
-
}
|
|
274
|
-
function artifactFallbackRows(text) {
|
|
275
|
-
if (!text)
|
|
276
|
-
return [];
|
|
277
|
-
return String(text)
|
|
278
|
-
.split(/\r?\n/)
|
|
279
|
-
.map((line) => line.replace(/^\|\s?/, '').replace(/\s?\|$/, '').trim())
|
|
280
|
-
.filter((line) => /^(heartbeat|doing|files|event|out|err):\s+/i.test(line))
|
|
281
|
-
.filter((line) => !/unknown|waiting for worker intake|no changed file yet/i.test(line))
|
|
282
|
-
.slice(-12)
|
|
283
|
-
.map((line) => `live: ${trimInline(line, 72)}`);
|
|
311
|
+
const env = {
|
|
312
|
+
SKS_SLOT_PROVIDER: String(input.provider || ''),
|
|
313
|
+
SKS_SLOT_MODEL: String(input.model || ''),
|
|
314
|
+
SKS_SLOT_TIER: String(input.serviceTier || ''),
|
|
315
|
+
SKS_SLOT_REASONING: String(input.reasoningEffort || ''),
|
|
316
|
+
SKS_SLOT_TASK: String(input.currentTask || '').slice(0, 200),
|
|
317
|
+
SKS_SLOT_ROLE: String(input.role || '')
|
|
318
|
+
};
|
|
319
|
+
const envPrefix = Object.entries(env)
|
|
320
|
+
.filter(([, value]) => value)
|
|
321
|
+
.map(([key, value]) => `${key}=${shellQuote(value)}`);
|
|
322
|
+
return [...envPrefix, input.nodePath || process.execPath, ...args].map((part, index) => index < envPrefix.length ? part : shellQuote(part)).join(' ');
|
|
284
323
|
}
|
|
285
324
|
function findTelemetrySlot(snapshot, slotId, generationIndex) {
|
|
325
|
+
if (!snapshot)
|
|
326
|
+
return null;
|
|
286
327
|
const generation = Math.max(1, Math.floor(Number(generationIndex) || 1));
|
|
287
328
|
return Object.values(snapshot.slots || {}).find((row) => row.slot_id === slotId && Number(row.generation_index) === generation) || null;
|
|
288
329
|
}
|
|
289
|
-
function formatTelemetryProgress(progress, startedAt) {
|
|
290
|
-
if (!progress || (progress.total === 0 && progress.done > 0))
|
|
291
|
-
return `elapsed ${formatElapsedSince(startedAt)}`;
|
|
292
|
-
return `progress ${progress.done}/${progress.total}${progress.label ? ` ${trimInline(progress.label, 24)}` : ''}`;
|
|
293
|
-
}
|
|
294
|
-
function formatElapsedSince(startedAt) {
|
|
295
|
-
const start = Date.parse(String(startedAt || ''));
|
|
296
|
-
const seconds = Number.isFinite(start) ? Math.max(0, Math.floor((Date.now() - start) / 1000)) : 0;
|
|
297
|
-
const mins = Math.floor(seconds / 60);
|
|
298
|
-
const secs = seconds % 60;
|
|
299
|
-
return `${String(mins).padStart(2, '0')}:${String(secs).padStart(2, '0')}`;
|
|
300
|
-
}
|
|
301
330
|
function telemetryStatus(snapshot) {
|
|
302
331
|
const parsed = snapshot?.updated_at ? Date.parse(snapshot.updated_at) : NaN;
|
|
303
332
|
const telemetryAgeMs = Number.isFinite(parsed) ? Math.max(0, Date.now() - parsed) : Number.MAX_SAFE_INTEGER;
|
|
@@ -309,15 +338,6 @@ function telemetryStatus(snapshot) {
|
|
|
309
338
|
telemetry_age_ms: telemetryAgeMs
|
|
310
339
|
};
|
|
311
340
|
}
|
|
312
|
-
function staleTelemetryRows(ageMs) {
|
|
313
|
-
if (!Number.isFinite(ageMs))
|
|
314
|
-
return ['telemetry stale; worker may still be running'];
|
|
315
|
-
if (ageMs > 60000)
|
|
316
|
-
return ['telemetry stale; worker may still be running'];
|
|
317
|
-
if (ageMs > 15000)
|
|
318
|
-
return [`telemetry stale ${(ageMs / 1000).toFixed(1)}s`];
|
|
319
|
-
return [];
|
|
320
|
-
}
|
|
321
341
|
async function readJson(file) {
|
|
322
342
|
try {
|
|
323
343
|
return JSON.parse(await fs.promises.readFile(file, 'utf8'));
|
|
@@ -463,14 +483,6 @@ function firstDefined(...values) {
|
|
|
463
483
|
}
|
|
464
484
|
return null;
|
|
465
485
|
}
|
|
466
|
-
function firstNonEmptyList(...values) {
|
|
467
|
-
for (const value of values) {
|
|
468
|
-
const normalized = normalizeList(value || []);
|
|
469
|
-
if (normalized.length)
|
|
470
|
-
return normalized;
|
|
471
|
-
}
|
|
472
|
-
return [];
|
|
473
|
-
}
|
|
474
486
|
function normalizeList(values) {
|
|
475
487
|
return [...new Set((Array.isArray(values) ? values : [values]).map((value) => String(value || '').trim()).filter(Boolean))];
|
|
476
488
|
}
|
|
@@ -478,31 +490,28 @@ function trimInline(value, max) {
|
|
|
478
490
|
const text = String(value || '').replace(/\s+/g, ' ').trim();
|
|
479
491
|
if (text.length <= max)
|
|
480
492
|
return text;
|
|
481
|
-
return text.slice(0, Math.max(1, max -
|
|
482
|
-
}
|
|
483
|
-
function
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
}
|
|
496
|
-
function frameSlotPane(title, rows) {
|
|
497
|
-
const width = Math.min(96, Math.max(44, title.length + 6, ...rows.map((row) => row.length + 4)));
|
|
498
|
-
const line = '+' + '-'.repeat(width - 2) + '+';
|
|
499
|
-
const label = ` ${trimInline(title, width - 4)} `;
|
|
500
|
-
const titleLine = '|' + label.padEnd(width - 2, ' ') + '|';
|
|
493
|
+
return text.slice(0, Math.max(1, max - 1)) + '…';
|
|
494
|
+
}
|
|
495
|
+
function formatHeartbeat(value) {
|
|
496
|
+
if (value == null || !Number.isFinite(value))
|
|
497
|
+
return 'unknown';
|
|
498
|
+
if (value < 1000)
|
|
499
|
+
return 'now';
|
|
500
|
+
return `${Math.max(1, Math.round(value / 1000))}s`;
|
|
501
|
+
}
|
|
502
|
+
function frameSlotPane(title, rows, theme) {
|
|
503
|
+
const width = theme.width;
|
|
504
|
+
const strip = (s) => s.replace(/\x1b\[[0-9;]*m/g, '');
|
|
505
|
+
const inner = width - 2;
|
|
506
|
+
const visibleTitle = strip(title);
|
|
507
|
+
const top = `┌─ ${title} ${'─'.repeat(Math.max(0, inner - visibleTitle.length - 4))}┐`;
|
|
501
508
|
const body = rows.map((row) => {
|
|
502
|
-
const
|
|
503
|
-
|
|
509
|
+
const visible = strip(row);
|
|
510
|
+
const clipped = visible.length > inner - 2 ? trimInline(row, inner - 2) : row;
|
|
511
|
+
const pad = Math.max(0, inner - strip(clipped).length - 1);
|
|
512
|
+
return `│ ${clipped}${' '.repeat(pad)}│`;
|
|
504
513
|
});
|
|
505
|
-
return [
|
|
514
|
+
return [paint(theme, ANSI_CODES.gray, top), ...body, paint(theme, ANSI_CODES.gray, `└${'─'.repeat(inner)}┘`)].join('\n');
|
|
506
515
|
}
|
|
507
516
|
function shellQuote(value) {
|
|
508
517
|
return `'${String(value).replace(/'/g, `'\\''`)}'`;
|
|
@@ -186,6 +186,7 @@ function normalizeTelemetryEvent(event) {
|
|
|
186
186
|
...(event.task_id ? { task_id: String(event.task_id) } : {}),
|
|
187
187
|
...(event.task_title ? { task_title: String(event.task_title) } : {}),
|
|
188
188
|
current_file: event.current_file == null ? null : String(event.current_file),
|
|
189
|
+
...(event.spawned_at ? { spawned_at: String(event.spawned_at) } : {}),
|
|
189
190
|
...(event.progress ? (() => {
|
|
190
191
|
const progress = normalizeProgress(event.progress);
|
|
191
192
|
return progress ? { progress } : {};
|
|
@@ -220,6 +221,7 @@ function mergeSlotTelemetry(previous, event) {
|
|
|
220
221
|
latest_event_type: stale ? previous.latest_event_type : event.event_type,
|
|
221
222
|
latest_ts: stale ? previous.latest_ts : event.ts,
|
|
222
223
|
started_at: previous?.started_at || event.ts,
|
|
224
|
+
spawned_at: event.spawned_at || previous?.spawned_at || event.ts,
|
|
223
225
|
progress: stale ? previous.progress || (terminalRegression ? null : event.progress || null) : event.progress || previous?.progress || null,
|
|
224
226
|
artifact_paths: unique([...(previous?.artifact_paths || []), ...(event.artifact_paths || [])]),
|
|
225
227
|
blockers: unique([...(previous?.blockers || []), ...(event.blockers || [])]),
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
const ANSI = {
|
|
2
|
+
reset: '\x1b[0m',
|
|
3
|
+
dim: '\x1b[2m',
|
|
4
|
+
bold: '\x1b[1m',
|
|
5
|
+
red: '\x1b[31m',
|
|
6
|
+
green: '\x1b[32m',
|
|
7
|
+
yellow: '\x1b[33m',
|
|
8
|
+
cyan: '\x1b[36m',
|
|
9
|
+
magenta: '\x1b[35m',
|
|
10
|
+
gray: '\x1b[90m'
|
|
11
|
+
};
|
|
12
|
+
export function resolveZellijTheme() {
|
|
13
|
+
const noColor = process.env.NO_COLOR === '1' || process.env.SKS_ZELLIJ_COLOR === '0';
|
|
14
|
+
return {
|
|
15
|
+
color: !noColor && process.stdout.isTTY !== false,
|
|
16
|
+
width: Math.min(Math.max(Number(process.stdout.columns) || 100, 60), 140),
|
|
17
|
+
statusIcon: {
|
|
18
|
+
running: '●',
|
|
19
|
+
verifying: '◍',
|
|
20
|
+
queued: '◌',
|
|
21
|
+
launching: '◌',
|
|
22
|
+
done: '✔',
|
|
23
|
+
completed: '✔',
|
|
24
|
+
failed: '✖',
|
|
25
|
+
blocked: '■',
|
|
26
|
+
timed_out: '⏱',
|
|
27
|
+
headless: '·',
|
|
28
|
+
drained: '✔'
|
|
29
|
+
},
|
|
30
|
+
statusColor: {
|
|
31
|
+
running: ANSI.green,
|
|
32
|
+
verifying: ANSI.cyan,
|
|
33
|
+
queued: ANSI.gray,
|
|
34
|
+
launching: ANSI.gray,
|
|
35
|
+
done: ANSI.green,
|
|
36
|
+
completed: ANSI.green,
|
|
37
|
+
failed: ANSI.red,
|
|
38
|
+
blocked: ANSI.yellow,
|
|
39
|
+
timed_out: ANSI.red,
|
|
40
|
+
headless: ANSI.gray,
|
|
41
|
+
drained: ANSI.green
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
export function paint(theme, code, text) {
|
|
46
|
+
return theme.color && code ? `${code}${text}${ANSI.reset}` : text;
|
|
47
|
+
}
|
|
48
|
+
export function statusBadge(theme, status) {
|
|
49
|
+
const s = String(status || 'queued').toLowerCase();
|
|
50
|
+
const icon = theme.statusIcon[s] || '●';
|
|
51
|
+
return paint(theme, theme.statusColor[s] || '', `${icon} ${s}`);
|
|
52
|
+
}
|
|
53
|
+
export function progressBar(theme, done, total, width = 10) {
|
|
54
|
+
if (!Number.isFinite(total) || total <= 0)
|
|
55
|
+
return '';
|
|
56
|
+
const filled = Math.max(0, Math.min(width, Math.round((done / total) * width)));
|
|
57
|
+
return `${paint(theme, ANSI.green, '▉'.repeat(filled))}${paint(theme, ANSI.gray, '▁'.repeat(width - filled))} ${done}/${total}`;
|
|
58
|
+
}
|
|
59
|
+
export function elapsed(sinceIso) {
|
|
60
|
+
const t = Date.parse(String(sinceIso || ''));
|
|
61
|
+
if (!Number.isFinite(t))
|
|
62
|
+
return '';
|
|
63
|
+
const s = Math.max(0, Math.floor((Date.now() - t) / 1000));
|
|
64
|
+
return `${String(Math.floor(s / 60)).padStart(2, '0')}:${String(s % 60).padStart(2, '0')}`;
|
|
65
|
+
}
|
|
66
|
+
export const ANSI_CODES = ANSI;
|
|
67
|
+
//# sourceMappingURL=zellij-theme.js.map
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
export function resolveZellijUiConfig(args = [], env = process.env) {
|
|
2
|
+
return {
|
|
3
|
+
mode: resolveZellijUiMode(args, env),
|
|
4
|
+
color: env.SKS_ZELLIJ_COLOR !== '0' && env.NO_COLOR !== '1',
|
|
5
|
+
visiblePanes: Number(env.SKS_ZELLIJ_VISIBLE_PANES) || null,
|
|
6
|
+
viewports: boundedInt(env.SKS_ZELLIJ_VIEWPORTS, 4, 0, 6),
|
|
7
|
+
monitorRows: Math.max(4, Number(env.SKS_ZELLIJ_MONITOR_ROWS || 12)),
|
|
8
|
+
monitor: env.SKS_ZELLIJ_MONITOR_PANE !== '0',
|
|
9
|
+
intervalMs: Math.max(500, Number(env.SKS_ZELLIJ_REFRESH_MS) || 1000)
|
|
10
|
+
};
|
|
11
|
+
}
|
|
1
12
|
export function resolveZellijUiMode(args = [], env = process.env) {
|
|
2
13
|
return resolveExplicitZellijUiMode(args, env) || 'compact-slots';
|
|
3
14
|
}
|
|
@@ -30,4 +41,9 @@ function resolveExplicitZellijUiMode(args = [], env = process.env) {
|
|
|
30
41
|
export function zellijUiModeCreatesDashboard(mode) {
|
|
31
42
|
return mode === 'dashboard-plus-slots';
|
|
32
43
|
}
|
|
44
|
+
function boundedInt(value, fallback, min, max) {
|
|
45
|
+
const parsed = Math.floor(Number(value ?? fallback));
|
|
46
|
+
const n = Number.isFinite(parsed) ? parsed : fallback;
|
|
47
|
+
return Math.max(min, Math.min(n, max));
|
|
48
|
+
}
|
|
33
49
|
//# sourceMappingURL=zellij-ui-mode.js.map
|