sneakoscope 4.8.7 → 5.3.0
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/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 +15 -4
- package/dist/cli/help-fast.js +18 -8
- package/dist/cli/insane-search-command.js +36 -8
- package/dist/cli/install-helpers.js +32 -0
- package/dist/commands/codex-lb.js +2 -0
- package/dist/commands/doctor.js +94 -9
- package/dist/commands/proof.js +6 -3
- package/dist/config/skills-manifest.json +82 -54
- 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 +5 -3
- package/dist/core/agents/agent-orchestrator.js +268 -62
- package/dist/core/agents/agent-output-validator.js +14 -3
- package/dist/core/agents/agent-patch-queue-store.js +95 -2
- package/dist/core/agents/agent-patch-queue.js +6 -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-worker-pipeline.js +36 -2
- package/dist/core/agents/codex-exec-worker-adapter.js +2 -0
- package/dist/core/agents/native-cli-worker.js +0 -1
- package/dist/core/agents/native-worker-backend-router.js +58 -1
- package/dist/core/codex-app/sks-menubar.js +477 -132
- package/dist/core/codex-app.js +1 -0
- 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/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/commands/basic-cli.js +18 -1
- package/dist/core/commands/check-command.js +37 -5
- 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 +3 -0
- 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 +230 -29
- package/dist/core/commands/menubar-command.js +24 -2
- package/dist/core/commands/naruto-command.js +64 -10
- 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-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/ui-command.js +161 -0
- package/dist/core/commands/uninstall-command.js +15 -1
- package/dist/core/db-safety.js +2 -2
- package/dist/core/doctor/doctor-dirty-planner.js +51 -7
- package/dist/core/doctor/doctor-transaction.js +8 -0
- package/dist/core/doctor/doctor-zellij-repair.js +1 -0
- package/dist/core/doctor/imagegen-repair.js +161 -0
- package/dist/core/feature-fixture-runner.js +2 -2
- package/dist/core/feature-fixtures.js +58 -37
- package/dist/core/feature-registry.js +102 -2
- package/dist/core/fsx.js +39 -6
- 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 +10 -5
- package/dist/core/mad-db/mad-db-coordinator.js +94 -18
- 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/naruto/naruto-active-pool.js +15 -4
- package/dist/core/naruto/naruto-real-worker-child.js +11 -1
- 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/solution-tournament.js +101 -0
- package/dist/core/permission-gates.js +30 -0
- package/dist/core/pipeline-internals/runtime-core.js +11 -3
- package/dist/core/pipeline-internals/runtime-gates.js +27 -0
- 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/release/release-gate-node.js +3 -0
- package/dist/core/release/release-gate-resource-governor.js +1 -0
- package/dist/core/routes/constants.js +1 -1
- package/dist/core/routes.js +65 -18
- package/dist/core/safety/mutation-guard.js +5 -1
- package/dist/core/stop-gate/gate-evaluator.js +102 -0
- package/dist/core/stop-gate/stop-gate-check.js +16 -1
- package/dist/core/stop-gate/stop-gate-writer.js +4 -0
- 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 +386 -15
- package/dist/core/update-check.js +178 -81
- 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-self-heal.js +9 -6
- package/dist/core/zellij/zellij-slot-telemetry.js +1 -1
- package/dist/scripts/check-feature-quality.js +2 -2
- package/dist/scripts/cli-output-consistency-check.js +57 -0
- package/dist/scripts/coding-bench-check.js +136 -0
- package/dist/scripts/doctor-imagegen-repair-check.js +62 -0
- package/dist/scripts/ensure-bin-executable.js +11 -3
- package/dist/scripts/harness-benchmark-check.js +104 -0
- package/dist/scripts/legacy-update-e2e-check.js +228 -0
- package/dist/scripts/mad-db-command-check.js +11 -8
- 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/naruto-real-active-pool-runtime-check.js +26 -1
- package/dist/scripts/ppt-real-imagegen-wiring-check.js +5 -1
- package/dist/scripts/proof-root-cause-policy-check.js +2 -0
- package/dist/scripts/release-dag-full-coverage-check.js +13 -4
- package/dist/scripts/release-gate-dag-runner.js +14 -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 +45 -17
- package/dist/scripts/release-metadata-1-19-check.js +2 -1
- package/dist/scripts/seo-geo-feature-fixture-quality-check.js +1 -1
- package/dist/scripts/sks-1-11-gate-lib.js +8 -6
- package/dist/scripts/sks-menubar-install-check.js +57 -20
- 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-slot-telemetry-runtime-check.js +1 -0
- package/docs/assets/sneakoscope-architecture-pipeline.jpg +0 -0
- package/docs/demo.tape +28 -0
- package/package.json +31 -24
- 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 -32
- 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-dirty-repair-blackbox.js +0 -22
- package/dist/scripts/doctor-dirty-semantic-blackbox.js +0 -8
- package/dist/scripts/doctor-native-capability-repair-blackbox.js +0 -39
- 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/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/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/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,4 +1,5 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
+
import { ui as cliUi } from '../../cli/cli-theme.js';
|
|
2
3
|
import { createMission, findLatestMission, loadMission, setCurrent } from '../mission.js';
|
|
3
4
|
import { nowIso, readJson, sksRoot, writeJsonAtomic } from '../fsx.js';
|
|
4
5
|
import { runNativeAgentOrchestrator } from '../agents/agent-orchestrator.js';
|
|
@@ -41,6 +42,10 @@ export async function narutoCommand(commandOrArgs = 'naruto', maybeArgs = []) {
|
|
|
41
42
|
return glmNarutoCommand(args.filter((arg) => arg !== '--glm'));
|
|
42
43
|
}
|
|
43
44
|
const parsed = parseNarutoArgs(args);
|
|
45
|
+
if (!parsed.json)
|
|
46
|
+
cliUi.banner(parsed.action === 'run' ? 'swarm' : `naruto ${parsed.action}`);
|
|
47
|
+
if (!parsed.json && parsed.action !== 'run')
|
|
48
|
+
cliUi.ok('naruto command surface ready');
|
|
44
49
|
if (parsed.action === 'help')
|
|
45
50
|
return narutoHelp(parsed);
|
|
46
51
|
if (parsed.action === 'status')
|
|
@@ -125,7 +130,8 @@ async function narutoRun(parsed) {
|
|
|
125
130
|
writeCapable,
|
|
126
131
|
leaseBasePath: patchEnvelopeBasePath,
|
|
127
132
|
maxActiveWorkers: parsed.concurrency || safe.cap,
|
|
128
|
-
worktreePolicy
|
|
133
|
+
worktreePolicy,
|
|
134
|
+
tournament: parsed.tournament
|
|
129
135
|
});
|
|
130
136
|
const baseRoleDistribution = buildNarutoRoleDistribution(baseWorkGraph.work_items, { readonly: parsed.readonly });
|
|
131
137
|
const allocationWorkers = buildNarutoAllocationWorkers(baseWorkGraph, baseRoleDistribution, roster);
|
|
@@ -140,7 +146,8 @@ async function narutoRun(parsed) {
|
|
|
140
146
|
leaseBasePath: patchEnvelopeBasePath,
|
|
141
147
|
maxActiveWorkers: parsed.concurrency || safe.cap,
|
|
142
148
|
worktreePolicy,
|
|
143
|
-
allocationAssignments
|
|
149
|
+
allocationAssignments,
|
|
150
|
+
tournament: parsed.tournament
|
|
144
151
|
});
|
|
145
152
|
const roleDistribution = buildNarutoRoleDistribution(workGraph.work_items, { readonly: parsed.readonly });
|
|
146
153
|
const allocationPolicy = {
|
|
@@ -407,9 +414,12 @@ async function narutoRun(parsed) {
|
|
|
407
414
|
const finalAccepted = result.proof?.status === 'passed' || result.proof?.gpt_final_status === 'approved';
|
|
408
415
|
const parallelRuntimeOk = !parsed.mock || roster.agent_count < 16 || (parallelRuntime?.passed === true
|
|
409
416
|
&& Number(parallelRuntime.max_observed_active_workers || 0) >= Math.min(16, activeSlots));
|
|
417
|
+
const regressionProof = summarizeRegressionProof(workGraph, result);
|
|
418
|
+
await writeJsonAtomic(path.join(mission.dir, 'regression-proof-summary.json'), regressionProof);
|
|
419
|
+
const tddOk = !regressionProof.required || (regressionProof.regression_test_added && regressionProof.regression_test_failed_before_fix && regressionProof.regression_test_passed_after_fix);
|
|
410
420
|
await writeJsonAtomic(path.join(mission.dir, 'naruto-gate.json'), {
|
|
411
421
|
schema: 'sks.naruto-gate.v1',
|
|
412
|
-
passed: result.ok === true && nativeProofOk && finalAccepted && parallelRuntimeOk,
|
|
422
|
+
passed: result.ok === true && nativeProofOk && finalAccepted && parallelRuntimeOk && tddOk,
|
|
413
423
|
mission_id: mission.id,
|
|
414
424
|
clone_roster_built: true,
|
|
415
425
|
clone_count: roster.agent_count,
|
|
@@ -424,9 +434,13 @@ async function narutoRun(parsed) {
|
|
|
424
434
|
zellij_dashboard_ready: zellijDashboard.ok === true,
|
|
425
435
|
native_agent_proof: nativeProofOk,
|
|
426
436
|
parallel_runtime_proof: parallelRuntimeOk,
|
|
437
|
+
regression_test_added: regressionProof.regression_test_added,
|
|
438
|
+
regression_test_failed_before_fix: regressionProof.regression_test_failed_before_fix,
|
|
439
|
+
regression_test_passed_after_fix: regressionProof.regression_test_passed_after_fix,
|
|
440
|
+
regression_proof: 'regression-proof-summary.json',
|
|
427
441
|
final_arbiter_accepted: finalAccepted,
|
|
428
442
|
session_cleanup: result.proof?.all_sessions_closed === true || nativeProofOk,
|
|
429
|
-
blockers: [...(result.proof?.blockers || []), ...(parallelRuntimeOk ? [] : ['naruto_parallel_runtime_proof_below_gate'])],
|
|
443
|
+
blockers: [...(result.proof?.blockers || []), ...(parallelRuntimeOk ? [] : ['naruto_parallel_runtime_proof_below_gate']), ...(tddOk ? [] : ['tdd_evidence_missing'])],
|
|
430
444
|
updated_at: nowIso()
|
|
431
445
|
});
|
|
432
446
|
const clones = result.roster?.agent_count ?? roster.agent_count;
|
|
@@ -443,7 +457,7 @@ async function narutoRun(parsed) {
|
|
|
443
457
|
generated_at: nowIso(),
|
|
444
458
|
mission_id: mission.id
|
|
445
459
|
});
|
|
446
|
-
const summaryOk = result.ok === true && (parsed.applyPatches === true ? finalizer.ok === true : finalizer.run_ok === true);
|
|
460
|
+
const summaryOk = result.ok === true && tddOk && (parsed.applyPatches === true ? finalizer.ok === true : finalizer.run_ok === true);
|
|
447
461
|
await setCurrent(root, {
|
|
448
462
|
mission_id: mission.id,
|
|
449
463
|
route: 'Naruto',
|
|
@@ -457,7 +471,7 @@ async function narutoRun(parsed) {
|
|
|
457
471
|
prompt: parsed.prompt
|
|
458
472
|
});
|
|
459
473
|
// 4.0.9: Write canonical stop-gate artifacts for hook resolution.
|
|
460
|
-
const narutoGatePassed = result.ok === true && nativeProofOk && finalAccepted && parallelRuntimeOk;
|
|
474
|
+
const narutoGatePassed = result.ok === true && nativeProofOk && finalAccepted && parallelRuntimeOk && tddOk;
|
|
461
475
|
await writeFinalStopGate({
|
|
462
476
|
root,
|
|
463
477
|
missionId: mission.id,
|
|
@@ -471,8 +485,14 @@ async function narutoRun(parsed) {
|
|
|
471
485
|
tests_passed: summaryOk,
|
|
472
486
|
route_evidence_passed: nativeProofOk && finalAccepted,
|
|
473
487
|
native_session_split_evidence: nativeProofOk ? 'native_agent_proof' : null,
|
|
488
|
+
...(regressionProof.required ? {
|
|
489
|
+
regression_test_added: regressionProof.regression_test_added,
|
|
490
|
+
regression_test_failed_before_fix: regressionProof.regression_test_failed_before_fix,
|
|
491
|
+
regression_test_passed_after_fix: regressionProof.regression_test_passed_after_fix,
|
|
492
|
+
regression_proof_path: 'regression-proof-summary.json'
|
|
493
|
+
} : { regression_proof_path: null }),
|
|
474
494
|
},
|
|
475
|
-
blockers: summaryOk ? [] : [...(result.proof?.blockers || []), ...(parallelRuntimeOk ? [] : ['naruto_parallel_runtime_proof_below_gate'])],
|
|
495
|
+
blockers: summaryOk ? [] : [...(result.proof?.blockers || []), ...(parallelRuntimeOk ? [] : ['naruto_parallel_runtime_proof_below_gate']), ...(tddOk ? [] : ['tdd_evidence_missing'])],
|
|
476
496
|
nativeGateFile: 'naruto-gate.json',
|
|
477
497
|
}).catch(() => null);
|
|
478
498
|
const summary = {
|
|
@@ -544,6 +564,7 @@ async function narutoRun(parsed) {
|
|
|
544
564
|
blockers: result.fast_mode_propagation.blockers || []
|
|
545
565
|
} : null,
|
|
546
566
|
finalizer,
|
|
567
|
+
regression_proof: regressionProof,
|
|
547
568
|
proof: result.proof?.status || 'missing',
|
|
548
569
|
run: compactNarutoRunResult(result),
|
|
549
570
|
zellij: null
|
|
@@ -687,6 +708,32 @@ function summarizeNarutoLocalWorkerResult(localWorker, result) {
|
|
|
687
708
|
backend_counts: backendCounts
|
|
688
709
|
};
|
|
689
710
|
}
|
|
711
|
+
function summarizeRegressionProof(workGraph, result) {
|
|
712
|
+
const bugfixItems = (Array.isArray(workGraph?.work_items) ? workGraph.work_items : []).filter((item) => String(item?.kind || '') === 'bugfix');
|
|
713
|
+
const proofs = collectRegressionProofs(result).filter(validRegressionProof);
|
|
714
|
+
return {
|
|
715
|
+
schema: 'sks.regression-proof-summary.v1',
|
|
716
|
+
generated_at: nowIso(),
|
|
717
|
+
required: bugfixItems.length > 0,
|
|
718
|
+
bugfix_work_item_count: bugfixItems.length,
|
|
719
|
+
proof_count: proofs.length,
|
|
720
|
+
regression_test_added: bugfixItems.length === 0 ? true : proofs.some((proof) => String(proof.test_file || '').trim().length > 0),
|
|
721
|
+
regression_test_failed_before_fix: bugfixItems.length === 0 ? true : proofs.some((proof) => proof.failed_before === true),
|
|
722
|
+
regression_test_passed_after_fix: bugfixItems.length === 0 ? true : proofs.some((proof) => proof.passed_after === true),
|
|
723
|
+
test_files: [...new Set(proofs.map((proof) => String(proof.test_file || '')).filter(Boolean))],
|
|
724
|
+
blockers: bugfixItems.length === 0 || proofs.length > 0 ? [] : ['tdd_evidence_missing']
|
|
725
|
+
};
|
|
726
|
+
}
|
|
727
|
+
function collectRegressionProofs(result) {
|
|
728
|
+
const rows = Array.isArray(result?.results) ? result.results : [];
|
|
729
|
+
return rows.flatMap((row) => [
|
|
730
|
+
row?.regression_proof,
|
|
731
|
+
...(Array.isArray(row?.patch_envelopes) ? row.patch_envelopes.map((envelope) => envelope?.regression_proof) : [])
|
|
732
|
+
]).filter(Boolean);
|
|
733
|
+
}
|
|
734
|
+
function validRegressionProof(proof) {
|
|
735
|
+
return Boolean(proof && proof.failed_before === true && proof.passed_after === true && String(proof.test_file || '').trim());
|
|
736
|
+
}
|
|
690
737
|
async function narutoStatus(parsed) {
|
|
691
738
|
const root = await sksRoot();
|
|
692
739
|
const id = parsed.missionId && parsed.missionId !== 'latest' ? parsed.missionId : await findLatestMission(root);
|
|
@@ -795,7 +842,7 @@ async function narutoHelp(parsed) {
|
|
|
795
842
|
mode: 'NARUTO',
|
|
796
843
|
description: 'Shadow Clone Swarm: fan out up to ' + MAX_NARUTO_AGENT_COUNT + ' parallel clone sessions.',
|
|
797
844
|
usage: [
|
|
798
|
-
'sks naruto run "<task>" [--clones N] [--backend codex-sdk|fake|ollama|local-llm] [--local-model|--ollama|--no-ollama] [--work-items N] [--write-mode parallel|serial|off] [--apply-patches] [--dry-run-patches] [--real] [--readonly] [--json]',
|
|
845
|
+
'sks naruto run "<task>" [--clones N] [--backend codex-sdk|fake|ollama|local-llm] [--local-model|--ollama|--no-ollama] [--work-items N] [--tournament 2-4] [--write-mode parallel|serial|off] [--apply-patches] [--dry-run-patches] [--real] [--readonly] [--json]',
|
|
799
846
|
'sks naruto status [--mission <id>] [--json]',
|
|
800
847
|
'sks naruto proof latest [--messages 20] [--json]'
|
|
801
848
|
],
|
|
@@ -866,9 +913,10 @@ function parseNarutoArgs(args = []) {
|
|
|
866
913
|
const smoke = hasFlag(args, '--smoke');
|
|
867
914
|
const parallelism = normalizeParallelism(readOption(args, '--parallelism', 'extreme'));
|
|
868
915
|
const messages = normalizeMessages(readOption(args, '--messages', '8'));
|
|
869
|
-
const
|
|
916
|
+
const tournament = normalizeTournament(readOption(args, '--tournament', '0'));
|
|
917
|
+
const valueFlags = new Set(['--clones', '--agents', '--work-items', '--concurrency', '--target-active-slots', '--backend', '--write-mode', '--max-write-agents', '--service-tier', '--mission', '--mission-id', '--ollama-model', '--local-model-model', '--ollama-base-url', '--local-model-base-url', '--parallelism', '--messages', '--tournament']);
|
|
870
918
|
const prompt = positionalArgs(rest, valueFlags).join(' ').trim() || 'Naruto shadow clone swarm run';
|
|
871
|
-
return { action, prompt, clones, workItems, workItemsExplicit, concurrency, backend, backendExplicit, mock, real, readonly, ollamaEnabled: useOllama && !noOllama, noOllama, ollamaModel, ollamaBaseUrl, writeMode, applyPatches, dryRunPatches, maxWriteAgents, fastMode, serviceTier, noFast, json, missionId, noOpenZellij, attach, smoke, parallelism, messages };
|
|
919
|
+
return { action, prompt, clones, workItems, workItemsExplicit, concurrency, backend, backendExplicit, mock, real, readonly, ollamaEnabled: useOllama && !noOllama, noOllama, ollamaModel, ollamaBaseUrl, writeMode, applyPatches, dryRunPatches, maxWriteAgents, fastMode, serviceTier, noFast, json, missionId, noOpenZellij, attach, smoke, parallelism, messages, tournament };
|
|
872
920
|
}
|
|
873
921
|
function normalizeParallelism(value) {
|
|
874
922
|
const text = String(value || 'extreme').toLowerCase();
|
|
@@ -880,6 +928,12 @@ function normalizeMessages(value) {
|
|
|
880
928
|
const parsed = Number(value);
|
|
881
929
|
return Math.max(0, Math.min(100, Math.floor(Number.isFinite(parsed) ? parsed : 8)));
|
|
882
930
|
}
|
|
931
|
+
function normalizeTournament(value) {
|
|
932
|
+
const parsed = Number(value);
|
|
933
|
+
if (!Number.isFinite(parsed) || parsed < 2)
|
|
934
|
+
return 0;
|
|
935
|
+
return Math.max(2, Math.min(4, Math.floor(parsed)));
|
|
936
|
+
}
|
|
883
937
|
async function writeNarutoArtifacts(ledgerRoot, artifacts) {
|
|
884
938
|
await writeJsonAtomic(path.join(ledgerRoot, 'naruto-work-graph.json'), artifacts.workGraph);
|
|
885
939
|
await writeJsonAtomic(path.join(ledgerRoot, 'naruto-role-distribution.json'), artifacts.roleDistribution);
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { flag } from '../../cli/args.js';
|
|
3
|
+
import { printJson } from '../../cli/output.js';
|
|
4
|
+
import { ui } from '../../cli/cli-theme.js';
|
|
5
|
+
import { ensureDir, nowIso, projectRoot, writeTextAtomic } from '../fsx.js';
|
|
6
|
+
export async function planCommand(args = []) {
|
|
7
|
+
const root = path.resolve(String(readOption(args, '--root', '') || await projectRoot()));
|
|
8
|
+
const prompt = positional(args).join(' ').trim() || String(readOption(args, '--task', '') || '').trim();
|
|
9
|
+
if (!prompt) {
|
|
10
|
+
console.error('Usage: sks plan "task" [--json]');
|
|
11
|
+
process.exitCode = 2;
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
const slug = slugify(prompt);
|
|
15
|
+
const file = path.join(root, '.sneakoscope', 'plans', `${slug}.md`);
|
|
16
|
+
await ensureDir(path.dirname(file));
|
|
17
|
+
const text = [
|
|
18
|
+
`# SKS Plan: ${prompt}`,
|
|
19
|
+
``,
|
|
20
|
+
`Generated: ${nowIso()}`,
|
|
21
|
+
`Implementation Allowed: false`,
|
|
22
|
+
``,
|
|
23
|
+
`## Goal`,
|
|
24
|
+
`- ${prompt}`,
|
|
25
|
+
``,
|
|
26
|
+
`## Scope`,
|
|
27
|
+
`- Inspect the smallest relevant code and docs surface before editing.`,
|
|
28
|
+
`- Preserve existing SKS proof-first gates and lean-engineering policy.`,
|
|
29
|
+
``,
|
|
30
|
+
`## Implementation Steps`,
|
|
31
|
+
`- Identify exact files and ownership boundaries.`,
|
|
32
|
+
`- Apply the smallest working change.`,
|
|
33
|
+
`- Update focused tests or release checks for changed behavior.`,
|
|
34
|
+
``,
|
|
35
|
+
`## Acceptance Checks`,
|
|
36
|
+
`- Typecheck or targeted build passes.`,
|
|
37
|
+
`- Relevant SKS gate/report is written and current.`,
|
|
38
|
+
`- Final summary separates verified from unverified work.`,
|
|
39
|
+
``,
|
|
40
|
+
`## Rollback Plan`,
|
|
41
|
+
`- Revert only files changed for this plan if verification fails.`
|
|
42
|
+
].join('\n');
|
|
43
|
+
await writeTextAtomic(file, `${text}\n`);
|
|
44
|
+
const result = { schema: 'sks.plan-artifact.v1', ok: true, prompt, file: path.relative(root, file), implementation_allowed: false };
|
|
45
|
+
if (flag(args, '--json'))
|
|
46
|
+
return printJson(result);
|
|
47
|
+
ui.banner('plan');
|
|
48
|
+
ui.ok(result.file);
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
51
|
+
function positional(args) {
|
|
52
|
+
const out = [];
|
|
53
|
+
const optionsWithValue = new Set(['--root', '--task']);
|
|
54
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
55
|
+
const arg = args[index] || '';
|
|
56
|
+
if (optionsWithValue.has(arg)) {
|
|
57
|
+
index += 1;
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (!arg.startsWith('--'))
|
|
61
|
+
out.push(arg);
|
|
62
|
+
}
|
|
63
|
+
return out;
|
|
64
|
+
}
|
|
65
|
+
function slugify(value) {
|
|
66
|
+
const base = value.toLowerCase().replace(/[^a-z0-9가-힣]+/gi, '-').replace(/^-+|-+$/g, '').slice(0, 60);
|
|
67
|
+
return base || `plan-${Date.now().toString(36)}`;
|
|
68
|
+
}
|
|
69
|
+
function readOption(args = [], name, fallback = null) {
|
|
70
|
+
const index = args.indexOf(name);
|
|
71
|
+
if (index >= 0 && args[index + 1] && !String(args[index + 1]).startsWith('--'))
|
|
72
|
+
return args[index + 1];
|
|
73
|
+
const prefixed = args.find((arg) => String(arg).startsWith(`${name}=`));
|
|
74
|
+
return prefixed ? prefixed.slice(name.length + 1) : fallback;
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=plan-command.js.map
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
import { projectRoot, readJson, writeJsonAtomic } from '../fsx.js';
|
|
2
|
+
import { exists, projectRoot, readJson, writeJsonAtomic } from '../fsx.js';
|
|
3
3
|
import { createMission, findLatestMission, loadMission } from '../mission.js';
|
|
4
4
|
import { flag, readOption } from './command-utils.js';
|
|
5
5
|
import { printJson } from '../../cli/output.js';
|
|
6
|
-
import { writePptBuildArtifacts, writePptRouteArtifacts } from '../ppt.js';
|
|
6
|
+
import { PPT_AUDIENCE_STRATEGY_ARTIFACT, PPT_CLEANUP_REPORT_ARTIFACT, PPT_FACT_LEDGER_ARTIFACT, PPT_GATE_ARTIFACT, PPT_HTML_ARTIFACT, PPT_IMAGE_ASSET_LEDGER_ARTIFACT, PPT_ITERATION_REPORT_ARTIFACT, PPT_PARALLEL_REPORT_ARTIFACT, PPT_PDF_ARTIFACT, PPT_RENDER_REPORT_ARTIFACT, PPT_REVIEW_LEDGER_ARTIFACT, PPT_REVIEW_POLICY_ARTIFACT, PPT_SOURCE_LEDGER_ARTIFACT, PPT_STORYBOARD_ARTIFACT, PPT_STYLE_TOKENS_ARTIFACT, writePptBuildArtifacts, writePptRouteArtifacts } from '../ppt.js';
|
|
7
7
|
import { maybeFinalizeRoute } from '../proof/auto-finalize.js';
|
|
8
8
|
import { writePptImagegenReviewFixture } from '../ppt-imagegen-review.js';
|
|
9
9
|
import { PPT_IMAGEGEN_REVIEW_GATE_ARTIFACT, PPT_REVIEW_ARTIFACT_PATHS, pptReviewProofEvidence, writePptImagegenReviewArtifacts } from '../ppt-review/index.js';
|
|
10
10
|
import { writeRouteCollaborationArtifacts } from '../agents/route-collaboration-ledger.js';
|
|
11
|
+
import { requireCodexImagegen } from '../imagegen/require-imagegen.js';
|
|
11
12
|
export async function pptCommand(command, args = []) {
|
|
12
13
|
const root = await projectRoot();
|
|
13
14
|
const action = args[0] || 'status';
|
|
@@ -25,14 +26,46 @@ export async function pptCommand(command, args = []) {
|
|
|
25
26
|
const { dir, mission } = await loadMission(root, missionId);
|
|
26
27
|
const contract = await readJson(path.join(dir, 'decision-contract.json'), { prompt: mission.prompt, answers: fixtureAnswers(), sealed_hash: 'ppt-fixture-contract' });
|
|
27
28
|
if (action === 'build') {
|
|
29
|
+
if (!flag(args, '--mock')) {
|
|
30
|
+
const imagegenRequired = await requireCodexImagegen(root, { autoRepair: true, applyRepair: true });
|
|
31
|
+
if (!imagegenRequired.ok) {
|
|
32
|
+
const result = {
|
|
33
|
+
schema: 'sks.ppt-build.v1',
|
|
34
|
+
ok: false,
|
|
35
|
+
status: 'blocked',
|
|
36
|
+
mission_id: missionId,
|
|
37
|
+
blocker: 'codex_imagegen_unavailable',
|
|
38
|
+
imagegen_required: imagegenRequired,
|
|
39
|
+
gate: {
|
|
40
|
+
schema: 'sks.ppt-gate.v1',
|
|
41
|
+
passed: false,
|
|
42
|
+
status: 'blocked',
|
|
43
|
+
blockers: ['codex_imagegen_unavailable'],
|
|
44
|
+
imagegen_evidence: { passed: false, generated_image_evidence: false }
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
process.exitCode = 1;
|
|
48
|
+
if (flag(args, '--json'))
|
|
49
|
+
return printJson(result);
|
|
50
|
+
console.error('PPT build blocked: Codex App imagegen/gpt-image-2 is unavailable.');
|
|
51
|
+
for (const action of imagegenRequired.blocker?.next_actions || [])
|
|
52
|
+
console.error(`- ${action}`);
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
28
56
|
await writePptRouteArtifacts(dir, contract);
|
|
29
57
|
const build = await writePptBuildArtifacts(dir, contract);
|
|
30
|
-
const
|
|
31
|
-
|
|
58
|
+
const gate = await evaluatePptGateArtifacts(dir, build.gate);
|
|
59
|
+
await writeJsonAtomic(path.join(dir, 'ppt-gate.json'), gate);
|
|
60
|
+
const proof = await maybeFinalizeRoute(root, { missionId, route: '$PPT', gateFile: 'ppt-gate.json', gate, mock: flag(args, '--mock'), visual: true, artifacts: Object.keys(build.files || {}), claims: [{ id: 'ppt-build-fixture', status: gate.passed ? 'verified_partial' : 'blocked' }], blockers: gate.blockers || [], command: { cmd: `sks ppt build ${missionId}`, status: gate.passed ? 0 : 1 } });
|
|
61
|
+
const ok = proof.ok === true && gate.passed === true;
|
|
62
|
+
const result = { schema: 'sks.ppt-build.v1', ok, mission_id: missionId, build: { ...build, gate }, proof: proof.validation, blockers: gate.blockers || [] };
|
|
32
63
|
if (flag(args, '--json'))
|
|
33
64
|
return printJson(result);
|
|
34
|
-
console.log(`PPT build: ${
|
|
35
|
-
if (!
|
|
65
|
+
console.log(`PPT build: ${ok ? 'ok' : 'blocked'} ${missionId}`);
|
|
66
|
+
if (!ok && gate.blockers?.length)
|
|
67
|
+
console.log(`Blockers: ${gate.blockers.join(', ')}`);
|
|
68
|
+
if (!ok)
|
|
36
69
|
process.exitCode = 1;
|
|
37
70
|
return result;
|
|
38
71
|
}
|
|
@@ -105,6 +138,33 @@ async function pptImagegenReview(root, command, action, args = []) {
|
|
|
105
138
|
console.log(`PPT imagegen review: ${result.ok ? 'ok' : 'blocked'} ${id}`);
|
|
106
139
|
return result;
|
|
107
140
|
}
|
|
141
|
+
if (!mockMode) {
|
|
142
|
+
const imagegenRequired = await requireCodexImagegen(root, { autoRepair: true, applyRepair: true });
|
|
143
|
+
if (!imagegenRequired.ok) {
|
|
144
|
+
const result = {
|
|
145
|
+
schema: 'sks.ppt-imagegen-review.v1',
|
|
146
|
+
ok: false,
|
|
147
|
+
status: 'blocked',
|
|
148
|
+
mission_id: id,
|
|
149
|
+
blocker: 'codex_imagegen_unavailable',
|
|
150
|
+
imagegen_required: imagegenRequired,
|
|
151
|
+
gate: {
|
|
152
|
+
schema: 'sks.ppt-imagegen-review-gate.v1',
|
|
153
|
+
passed: false,
|
|
154
|
+
status: 'blocked',
|
|
155
|
+
blockers: ['codex_imagegen_unavailable'],
|
|
156
|
+
imagegen_evidence: { passed: false, generated_image_evidence: false }
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
process.exitCode = 1;
|
|
160
|
+
if (flag(args, '--json'))
|
|
161
|
+
return printJson(result);
|
|
162
|
+
console.error('PPT imagegen review blocked: Codex App imagegen/gpt-image-2 is unavailable.');
|
|
163
|
+
for (const action of imagegenRequired.blocker?.next_actions || [])
|
|
164
|
+
console.error(`- ${action}`);
|
|
165
|
+
return result;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
108
168
|
const artifacts = await writePptImagegenReviewArtifacts({
|
|
109
169
|
root,
|
|
110
170
|
dir,
|
|
@@ -168,12 +228,17 @@ async function pptFixture(root, command, args) {
|
|
|
168
228
|
visualEvidence: { ppt_review: pptReviewProofEvidence(review.gate, review) },
|
|
169
229
|
artifacts: [...Object.keys(build.files || {}), ...Object.values(PPT_REVIEW_ARTIFACT_PATHS), ...Object.values(native.artifacts || {})],
|
|
170
230
|
claims: [{ id: 'ppt-fixture', status: 'verified_partial' }],
|
|
171
|
-
|
|
231
|
+
blockers: gate.blockers || [],
|
|
232
|
+
statusHint: 'blocked',
|
|
233
|
+
command: { cmd: `sks ${command} fixture --mock`, status: 1 }
|
|
172
234
|
});
|
|
173
|
-
const result = { schema: 'sks.ppt-fixture.v2', ok:
|
|
174
|
-
if (flag(args, '--json'))
|
|
235
|
+
const result = { schema: 'sks.ppt-fixture.v2', ok: false, mission_id: id, build: { ...build, ok: false, gate }, imagegen_review: review, native_agent_collaboration: native, proof: proof.validation };
|
|
236
|
+
if (flag(args, '--json')) {
|
|
237
|
+
process.exitCode = 1;
|
|
175
238
|
return printJson(result);
|
|
176
|
-
|
|
239
|
+
}
|
|
240
|
+
console.log(`PPT fixture: blocked ${id}`);
|
|
241
|
+
process.exitCode = 1;
|
|
177
242
|
return result;
|
|
178
243
|
}
|
|
179
244
|
async function pptExplain(root, args = []) {
|
|
@@ -252,21 +317,91 @@ function missingMission(args) {
|
|
|
252
317
|
function mockPptFixtureGate(gate = {}) {
|
|
253
318
|
return {
|
|
254
319
|
...gate,
|
|
255
|
-
passed:
|
|
320
|
+
passed: false,
|
|
321
|
+
ok: false,
|
|
322
|
+
status: 'blocked',
|
|
323
|
+
execution_class: 'mock_fixture',
|
|
256
324
|
mock_fixture: true,
|
|
257
|
-
unsupported_critical_claims_zero:
|
|
258
|
-
image_asset_policy_satisfied:
|
|
259
|
-
bounded_iteration_complete:
|
|
260
|
-
critical_review_issues_zero:
|
|
261
|
-
render_report_passed:
|
|
262
|
-
fact_ledger_passed:
|
|
263
|
-
image_asset_ledger_passed:
|
|
264
|
-
review_ledger_passed:
|
|
265
|
-
iteration_report_passed:
|
|
266
|
-
cleanup_report_passed:
|
|
267
|
-
parallel_report_passed:
|
|
268
|
-
honest_mode_complete:
|
|
269
|
-
blockers: []
|
|
325
|
+
unsupported_critical_claims_zero: false,
|
|
326
|
+
image_asset_policy_satisfied: false,
|
|
327
|
+
bounded_iteration_complete: false,
|
|
328
|
+
critical_review_issues_zero: false,
|
|
329
|
+
render_report_passed: false,
|
|
330
|
+
fact_ledger_passed: false,
|
|
331
|
+
image_asset_ledger_passed: false,
|
|
332
|
+
review_ledger_passed: false,
|
|
333
|
+
iteration_report_passed: false,
|
|
334
|
+
cleanup_report_passed: false,
|
|
335
|
+
parallel_report_passed: false,
|
|
336
|
+
honest_mode_complete: false,
|
|
337
|
+
blockers: ['ppt_fixture_mode_cannot_claim_real']
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
export async function evaluatePptGateArtifacts(dir, baseGate = {}) {
|
|
341
|
+
const factLedger = await readJson(path.join(dir, PPT_FACT_LEDGER_ARTIFACT), null);
|
|
342
|
+
const imageAssetLedger = await readJson(path.join(dir, PPT_IMAGE_ASSET_LEDGER_ARTIFACT), null);
|
|
343
|
+
const reviewLedger = await readJson(path.join(dir, PPT_REVIEW_LEDGER_ARTIFACT), null);
|
|
344
|
+
const iterationReport = await readJson(path.join(dir, PPT_ITERATION_REPORT_ARTIFACT), null);
|
|
345
|
+
const renderReport = await readJson(path.join(dir, PPT_RENDER_REPORT_ARTIFACT), null);
|
|
346
|
+
const cleanupReport = await readJson(path.join(dir, PPT_CLEANUP_REPORT_ARTIFACT), null);
|
|
347
|
+
const parallelReport = await readJson(path.join(dir, PPT_PARALLEL_REPORT_ARTIFACT), null);
|
|
348
|
+
const requiredArtifacts = [
|
|
349
|
+
'decision-contract.json',
|
|
350
|
+
PPT_AUDIENCE_STRATEGY_ARTIFACT,
|
|
351
|
+
PPT_SOURCE_LEDGER_ARTIFACT,
|
|
352
|
+
PPT_FACT_LEDGER_ARTIFACT,
|
|
353
|
+
PPT_IMAGE_ASSET_LEDGER_ARTIFACT,
|
|
354
|
+
PPT_STORYBOARD_ARTIFACT,
|
|
355
|
+
PPT_STYLE_TOKENS_ARTIFACT,
|
|
356
|
+
PPT_REVIEW_POLICY_ARTIFACT,
|
|
357
|
+
PPT_REVIEW_LEDGER_ARTIFACT,
|
|
358
|
+
PPT_ITERATION_REPORT_ARTIFACT,
|
|
359
|
+
PPT_HTML_ARTIFACT,
|
|
360
|
+
PPT_PDF_ARTIFACT,
|
|
361
|
+
PPT_RENDER_REPORT_ARTIFACT,
|
|
362
|
+
PPT_CLEANUP_REPORT_ARTIFACT,
|
|
363
|
+
PPT_PARALLEL_REPORT_ARTIFACT
|
|
364
|
+
];
|
|
365
|
+
const missing = [];
|
|
366
|
+
for (const artifact of requiredArtifacts) {
|
|
367
|
+
if (!(await exists(path.join(dir, artifact))))
|
|
368
|
+
missing.push(artifact);
|
|
369
|
+
}
|
|
370
|
+
const renderReportPassed = renderReport?.passed === true;
|
|
371
|
+
const factLedgerPassed = factLedger?.passed === true && Number(factLedger.unsupported_critical_claims_count || 0) === 0;
|
|
372
|
+
const imageAssetLedgerPassed = imageAssetLedger?.passed === true;
|
|
373
|
+
const imagegenEvidence = imageAssetLedger?.imagegen_evidence || { schema: 'sks.ppt-imagegen-evidence.v1', required: false, passed: true, blockers: [] };
|
|
374
|
+
const imagegenEvidencePassed = imagegenEvidence?.required === true ? imagegenEvidence?.passed === true : true;
|
|
375
|
+
const reviewLedgerPassed = reviewLedger?.passed === true;
|
|
376
|
+
const iterationReportPassed = iterationReport?.passed === true;
|
|
377
|
+
const cleanupReportPassed = cleanupReport?.source_html_preserved === true && cleanupReport?.temp_cleanup_completed === true;
|
|
378
|
+
const parallelReportPassed = parallelReport?.passed === true;
|
|
379
|
+
const blockers = [
|
|
380
|
+
...missing.map((artifact) => `missing_artifact:${artifact}`),
|
|
381
|
+
...(renderReportPassed ? [] : ['render_report_not_passed']),
|
|
382
|
+
...(factLedgerPassed ? [] : ['fact_ledger_not_passed']),
|
|
383
|
+
...(imageAssetLedgerPassed ? [] : ['image_asset_ledger_not_passed']),
|
|
384
|
+
...(imagegenEvidencePassed ? [] : ['ppt_imagegen_evidence_not_passed']),
|
|
385
|
+
...(reviewLedgerPassed ? [] : ['review_ledger_not_passed']),
|
|
386
|
+
...(iterationReportPassed ? [] : ['iteration_report_not_passed']),
|
|
387
|
+
...(cleanupReportPassed ? [] : ['cleanup_report_not_passed']),
|
|
388
|
+
...(parallelReportPassed ? [] : ['parallel_report_not_passed'])
|
|
389
|
+
];
|
|
390
|
+
const passed = blockers.length === 0;
|
|
391
|
+
return {
|
|
392
|
+
...baseGate,
|
|
393
|
+
passed,
|
|
394
|
+
ok: passed,
|
|
395
|
+
status: passed ? 'pass' : 'blocked',
|
|
396
|
+
render_report_passed: renderReportPassed,
|
|
397
|
+
fact_ledger_passed: factLedgerPassed,
|
|
398
|
+
image_asset_ledger_passed: imageAssetLedgerPassed,
|
|
399
|
+
imagegen_evidence: imagegenEvidence,
|
|
400
|
+
review_ledger_passed: reviewLedgerPassed,
|
|
401
|
+
iteration_report_passed: iterationReportPassed,
|
|
402
|
+
cleanup_report_passed: cleanupReportPassed,
|
|
403
|
+
parallel_report_passed: parallelReportPassed,
|
|
404
|
+
blockers
|
|
270
405
|
};
|
|
271
406
|
}
|
|
272
407
|
function fixtureAnswers() {
|
|
@@ -75,7 +75,9 @@ async function qaLoopPrepare(args) {
|
|
|
75
75
|
const artifactResult = await writeQaLoopArtifacts(dir, { id, prompt, mode: 'qaloop' }, result.contract);
|
|
76
76
|
const nativeAgentPlan = await writeQaNativeAgentLedger(dir, { id, prompt, reportFile: artifactResult.report_file });
|
|
77
77
|
await appendJsonlBounded(path.join(dir, 'events.jsonl'), { ts: nowIso(), type: 'qaloop.prepare.auto_sealed', slots: 0, hash: result.contract.sealed_hash, checklist_count: artifactResult.checklist_count });
|
|
78
|
-
|
|
78
|
+
const clarificationPassed = true;
|
|
79
|
+
const ambiguityGatePassed = true;
|
|
80
|
+
await setCurrent(root, { mission_id: id, route: 'QALoop', route_command: '$QA-LOOP', mode: 'QALOOP', phase: 'QALOOP_CLARIFICATION_CONTRACT_SEALED', questions_allowed: false, implementation_allowed: true, clarification_required: false, clarification_passed: clarificationPassed, ambiguity_gate_required: true, ambiguity_gate_passed: ambiguityGatePassed, stop_gate: 'qa-gate.json', qa_loop_artifacts_ready: true, qa_report_file: artifactResult.report_file, qa_checklist_count: artifactResult.checklist_count, reasoning_effort: 'high', reasoning_profile: 'sks-logic-high', reasoning_temporary: true });
|
|
79
81
|
if (flag(args, '--json'))
|
|
80
82
|
return console.log(JSON.stringify({ schema: 'sks.qa-loop-prepare.v1', ok: true, mission_id: id, report_file: artifactResult.report_file, checklist_count: artifactResult.checklist_count, native_agent_plan: nativeAgentPlan }, null, 2));
|
|
81
83
|
console.log(`QA-LOOP mission created: ${id}`);
|
|
@@ -111,7 +113,9 @@ async function qaLoopAnswer(args) {
|
|
|
111
113
|
}
|
|
112
114
|
const artifactResult = await writeQaLoopArtifacts(dir, mission, result.contract);
|
|
113
115
|
await appendJsonlBounded(path.join(dir, 'events.jsonl'), { ts: nowIso(), type: 'qaloop.contract.sealed', hash: result.contract.sealed_hash, checklist_count: artifactResult.checklist_count });
|
|
114
|
-
|
|
116
|
+
const clarificationPassed = true;
|
|
117
|
+
const ambiguityGatePassed = true;
|
|
118
|
+
await setCurrent(root, { mission_id: id, route: 'QALoop', route_command: '$QA-LOOP', mode: 'QALOOP', phase: 'QALOOP_CLARIFICATION_CONTRACT_SEALED', questions_allowed: false, implementation_allowed: true, clarification_required: false, clarification_passed: clarificationPassed, ambiguity_gate_passed: ambiguityGatePassed, stop_gate: 'qa-gate.json', reasoning_effort: 'high', reasoning_profile: 'sks-logic-high', reasoning_temporary: true });
|
|
115
119
|
console.log(`QA-LOOP contract sealed for ${id}`);
|
|
116
120
|
}
|
|
117
121
|
async function qaLoopRun(args) {
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import fsp from 'node:fs/promises';
|
|
2
4
|
import { flag } from '../../cli/args.js';
|
|
3
5
|
import { printJson } from '../../cli/output.js';
|
|
4
|
-
import { projectRoot } from '../fsx.js';
|
|
6
|
+
import { exists, projectRoot, readJson, writeJsonAtomic, writeTextAtomic } from '../fsx.js';
|
|
7
|
+
import { createMission } from '../mission.js';
|
|
5
8
|
export async function releaseCommand(args = []) {
|
|
6
9
|
const root = await projectRoot();
|
|
7
10
|
const sub = args[0] && !args[0].startsWith('-') ? args[0] : 'affected';
|
|
@@ -12,18 +15,41 @@ export async function releaseCommand(args = []) {
|
|
|
12
15
|
process.exitCode = 1;
|
|
13
16
|
return null;
|
|
14
17
|
}
|
|
18
|
+
const mission = await createMission(root, { mode: 'release-review', prompt: `Release review ${sub}` });
|
|
15
19
|
const result = spawnSync(process.execPath, command.args, {
|
|
16
20
|
cwd: root,
|
|
17
21
|
encoding: 'utf8',
|
|
18
22
|
maxBuffer: 1024 * 1024 * 20,
|
|
19
23
|
env: { ...process.env, CI: process.env.CI || 'true' }
|
|
20
24
|
});
|
|
25
|
+
const stdoutPath = path.join(mission.dir, 'release-command-stdout.log');
|
|
26
|
+
const stderrPath = path.join(mission.dir, 'release-command-stderr.log');
|
|
27
|
+
await writeTextAtomic(stdoutPath, String(result.stdout || ''));
|
|
28
|
+
await writeTextAtomic(stderrPath, String(result.stderr || ''));
|
|
29
|
+
const readiness = await findReleaseReadinessReport(root);
|
|
30
|
+
const requiredSections = ['five_lane_review', 'integration_evidence', 'session_cleanup'];
|
|
31
|
+
const missingSections = requiredSections.filter((section) => readiness.report?.[section] == null);
|
|
32
|
+
if (readiness.report)
|
|
33
|
+
await writeJsonAtomic(path.join(mission.dir, 'release-readiness-report.json'), readiness.report);
|
|
21
34
|
const report = {
|
|
22
35
|
schema: 'sks.release-command.v1',
|
|
23
|
-
ok: result.status === 0,
|
|
36
|
+
ok: result.status === 0 && readiness.valid === true && missingSections.length === 0,
|
|
24
37
|
subcommand: sub,
|
|
38
|
+
mission_id: mission.id,
|
|
25
39
|
command: [process.execPath, ...command.args],
|
|
26
40
|
status: result.status,
|
|
41
|
+
release_report: readiness.path,
|
|
42
|
+
release_report_valid: readiness.valid,
|
|
43
|
+
missing_sections: missingSections,
|
|
44
|
+
blockers: [
|
|
45
|
+
...(result.status === 0 ? [] : ['release_subprocess_failed']),
|
|
46
|
+
...(readiness.valid ? [] : ['release_report_missing_or_invalid']),
|
|
47
|
+
...missingSections.map((section) => `release_report_missing_section:${section}`)
|
|
48
|
+
],
|
|
49
|
+
logs: {
|
|
50
|
+
stdout: path.relative(root, stdoutPath),
|
|
51
|
+
stderr: path.relative(root, stderrPath)
|
|
52
|
+
},
|
|
27
53
|
stdout_tail: tail(String(result.stdout || '')),
|
|
28
54
|
stderr_tail: tail(String(result.stderr || ''))
|
|
29
55
|
};
|
|
@@ -37,6 +63,33 @@ export async function releaseCommand(args = []) {
|
|
|
37
63
|
process.exitCode = result.status || 1;
|
|
38
64
|
return report;
|
|
39
65
|
}
|
|
66
|
+
async function findReleaseReadinessReport(root) {
|
|
67
|
+
const candidates = [
|
|
68
|
+
path.join(root, 'release-readiness-report.json'),
|
|
69
|
+
path.join(root, '.sneakoscope', 'reports', 'release-readiness-report.json')
|
|
70
|
+
];
|
|
71
|
+
const reportsDir = path.join(root, '.sneakoscope', 'reports');
|
|
72
|
+
const entries = await fsp.readdir(reportsDir).catch(() => []);
|
|
73
|
+
for (const entry of entries) {
|
|
74
|
+
if (/^release-readiness.*\.json$/.test(entry))
|
|
75
|
+
candidates.push(path.join(reportsDir, entry));
|
|
76
|
+
}
|
|
77
|
+
const existing = [];
|
|
78
|
+
for (const candidate of candidates) {
|
|
79
|
+
if (await exists(candidate)) {
|
|
80
|
+
const stat = await fsp.stat(candidate).catch(() => null);
|
|
81
|
+
existing.push({ path: candidate, mtime: stat?.mtimeMs || 0 });
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
existing.sort((a, b) => b.mtime - a.mtime);
|
|
85
|
+
const selected = existing[0]?.path || null;
|
|
86
|
+
const report = selected ? await readJson(selected, null) : null;
|
|
87
|
+
return {
|
|
88
|
+
path: selected ? path.relative(root, selected) : null,
|
|
89
|
+
report,
|
|
90
|
+
valid: Boolean(report && typeof report.schema === 'string' && /release-readiness/.test(report.schema))
|
|
91
|
+
};
|
|
92
|
+
}
|
|
40
93
|
function commandForSubcommand(sub) {
|
|
41
94
|
if (sub === 'affected')
|
|
42
95
|
return { args: ['dist/scripts/release-gate-dag-runner.js', '--preset', 'affected', '--changed-since', 'auto', '--sla', '5m'] };
|
|
@@ -180,7 +180,7 @@ async function researchRun(args) {
|
|
|
180
180
|
await runResearchCycle(dir, researchWorkGraph, { cycle: 0, status: mock ? 'mock_native_orchestrator_planned' : 'native_orchestrator_planned' });
|
|
181
181
|
await setCurrent(root, { mission_id: id, mode: 'RESEARCH', phase: 'RESEARCH_RUNNING_NO_QUESTIONS', questions_allowed: false, implementation_allowed: false, research_real_run_required: !mock, research_cycle_timeout_minutes: cycleTimeoutMinutes });
|
|
182
182
|
await appendJsonlBounded(path.join(dir, 'events.jsonl'), { ts: nowIso(), type: 'research.run.started', maxCycles, mock, cycleTimeoutMinutes, real_run_required: !mock });
|
|
183
|
-
const nativeAgentRun = await runNativeAgentOrchestrator({ root, missionId: id, route: flag(args, '--autoresearch') ? '$AutoResearch' : '$Research', prompt: mission.prompt || plan.prompt || 'Research run', backend: mock ? 'fake' : 'codex-sdk', mock, agents: requestedAgents, targetActiveSlots, desiredWorkItemCount: effectiveDesiredWorkItemCount, minimumWorkItems: effectiveMinimumWorkItems, maxQueueExpansion, concurrency: Math.min(requestedAgents, 5), readonly:
|
|
183
|
+
const nativeAgentRun = await runNativeAgentOrchestrator({ root, missionId: id, route: flag(args, '--autoresearch') ? '$AutoResearch' : '$Research', prompt: mission.prompt || plan.prompt || 'Research run', backend: mock ? 'fake' : 'codex-sdk', mock, agents: requestedAgents, targetActiveSlots, desiredWorkItemCount: effectiveDesiredWorkItemCount, minimumWorkItems: effectiveMinimumWorkItems, maxQueueExpansion, concurrency: Math.min(requestedAgents, 5), readonly: !applyPatches, profile, writeMode: writeMode, applyPatches, dryRunPatches, maxWriteAgents, roster: plan.native_agent_plan, routeCommand: 'sks research run', routeBlackboxKind: 'actual_research_command', narutoWorkGraph: researchWorkGraph });
|
|
184
184
|
await writeJsonAtomic(path.join(dir, 'research-native-agent-run.json'), nativeAgentRun);
|
|
185
185
|
await appendJsonlBounded(path.join(dir, 'events.jsonl'), { ts: nowIso(), type: 'research.native_agents.completed', backend: nativeAgentRun.backend, ok: nativeAgentRun.ok, proof: nativeAgentRun.proof?.status });
|
|
186
186
|
if (!nativeAgentRun.ok) {
|