sneakoscope 6.0.2 → 6.1.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 +5 -3
- package/config/codex-releases/{rust-v0.142.0.json → rust-v0.144.1.json} +6 -6
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/dist/cli/install-helpers.js +255 -440
- package/dist/cli/router.js +53 -4
- package/dist/commands/codex-app.js +8 -3
- package/dist/commands/codex-lb.js +169 -40
- package/dist/commands/codex.js +6 -5
- package/dist/commands/doctor.js +60 -26
- package/dist/commands/versioning.js +7 -0
- package/dist/config/skills-manifest.json +57 -57
- package/dist/core/agents/agent-central-ledger.js +9 -0
- package/dist/core/agents/agent-cleanup-executor.js +334 -41
- package/dist/core/agents/agent-cleanup.js +20 -1
- package/dist/core/agents/agent-command-surface.js +2 -1
- package/dist/core/agents/agent-effort-policy.js +46 -33
- package/dist/core/agents/agent-janitor.js +9 -10
- package/dist/core/agents/agent-namespace-safety.js +56 -0
- package/dist/core/agents/agent-orchestrator.js +26 -4
- package/dist/core/agents/agent-output-validator.js +1 -1
- package/dist/core/agents/agent-proof-evidence.js +16 -2
- package/dist/core/agents/agent-role-config.js +3 -6
- package/dist/core/agents/agent-roster.js +2 -2
- package/dist/core/agents/agent-runner-codex-exec.js +2 -0
- package/dist/core/agents/agent-runner-process.js +1 -0
- package/dist/core/agents/fast-mode-policy.js +3 -5
- package/dist/core/agents/native-cli-session-swarm.js +18 -1
- package/dist/core/agents/native-worker-backend-router.js +180 -108
- package/dist/core/agents/parallel-write-fixture.js +15 -10
- package/dist/core/agents/runtime-proof-summary.js +21 -3
- package/dist/core/agents/work-partition/repo-inventory.js +68 -7
- package/dist/core/code-structure.js +5 -4
- package/dist/core/codex/codex-config-guard.js +31 -9
- package/dist/core/codex-app/codex-app-fast-ui-repair.js +51 -20
- package/dist/core/codex-app/codex-app-restart.js +38 -8
- package/dist/core/codex-app/codex-app-ui-state-snapshot.js +11 -3
- package/dist/core/codex-app/sks-menubar.js +100 -40
- package/dist/core/codex-app.js +60 -17
- package/dist/core/codex-compat/codex-hook-warning-detector.js +10 -1
- package/dist/core/codex-compat/codex-release-manifest.js +6 -6
- package/dist/core/codex-control/codex-0139-doctor-real-probe.js +7 -1
- package/dist/core/codex-control/codex-0139-image-path-real-probe.js +14 -8
- package/dist/core/codex-control/codex-0139-probe-runner.js +103 -28
- package/dist/core/codex-control/codex-0139-real-probe-summary.js +7 -3
- package/dist/core/codex-control/codex-0139-real-probes.js +21 -6
- package/dist/core/codex-control/codex-0139-sandbox-real-probe.js +39 -13
- package/dist/core/codex-control/codex-0139-web-search-probe.js +11 -8
- package/dist/core/codex-control/{codex-0142-capability.js → codex-0144-capability.js} +22 -22
- package/dist/core/codex-control/codex-0144-collab-agent-real-probe.js +63 -0
- package/dist/core/codex-control/codex-model-metadata.js +8 -4
- package/dist/core/codex-control/codex-multi-agent-event-normalizer.js +5 -1
- package/dist/core/codex-control/codex-reliability-shield.js +4 -1
- package/dist/core/codex-control/codex-sdk-adapter.js +53 -6
- package/dist/core/codex-control/codex-sdk-config-policy.js +2 -1
- package/dist/core/codex-control/codex-sdk-sandbox-policy.js +6 -3
- package/dist/core/codex-lb/codex-lb-env.js +107 -0
- package/dist/core/codex-lb/codex-lb-tool-catalog.js +478 -0
- package/dist/core/codex-native/codex-native-feature-broker.js +22 -22
- package/dist/core/codex-native/codex-native-feature-matrix.js +2 -2
- package/dist/core/codex-native/native-capability-postcheck.js +16 -8
- package/dist/core/codex-native/native-capability-repair-matrix.js +76 -27
- package/dist/core/codex-plugins/codex-plugin-json.js +67 -21
- package/dist/core/codex-plugins/codex-plugin-repair.js +118 -0
- package/dist/core/codex-runtime/codex-desktop-config-policy.js +306 -0
- package/dist/core/commands/agent-command.js +19 -0
- package/dist/core/commands/basic-cli.js +45 -24
- package/dist/core/commands/gc-command.js +27 -4
- package/dist/core/commands/image-ux-review-command.js +55 -24
- package/dist/core/commands/mad-sks-command.js +152 -132
- package/dist/core/commands/naruto-command.js +41 -10
- package/dist/core/commands/pipeline-command.js +1 -0
- package/dist/core/commands/wiki-command.js +179 -83
- package/dist/core/computer-use-live-evidence.js +166 -3
- package/dist/core/computer-use-status.js +5 -2
- package/dist/core/daemon/sksd-hook-daemon-entrypoint.js +2 -2
- package/dist/core/daemon/sksd-hook-daemon.js +171 -28
- package/dist/core/daemon/sksd-hook-dispatch.js +2 -2
- package/dist/core/dfix/verification-selector.js +6 -4
- package/dist/core/doctor/browser-use-repair.js +54 -13
- package/dist/core/doctor/codex-0139-doctor.js +3 -2
- package/dist/core/doctor/computer-use-repair.js +28 -39
- package/dist/core/doctor/doctor-codex-startup-repair.js +19 -9
- package/dist/core/doctor/doctor-context7-repair.js +1 -1
- package/dist/core/doctor/doctor-dirty-planner.js +1 -1
- package/dist/core/doctor/doctor-native-capability-repair.js +74 -3
- package/dist/core/doctor/imagegen-repair.js +47 -12
- package/dist/core/doctor/legacy-global-hook-cleanup.js +179 -0
- package/dist/core/feature-registry.js +25 -31
- package/dist/core/fsx.js +54 -6
- package/dist/core/harness-conflicts.js +1 -1
- package/dist/core/hooks-runtime/code-pack-freshness-preflight.js +5 -4
- package/dist/core/hooks-runtime/hook-invocation-dedupe.js +147 -0
- package/dist/core/hooks-runtime/hook-io.js +6 -0
- package/dist/core/hooks-runtime.js +17 -2
- package/dist/core/image/image-artifact-path-contract.js +8 -6
- package/dist/core/image/image-artifact-registry.js +5 -1
- package/dist/core/image-ux-review/imagegen-adapter.js +5 -2
- package/dist/core/imagegen/imagegen-capability.js +10 -13
- package/dist/core/imagegen/require-imagegen.js +37 -11
- package/dist/core/managed-assets/managed-assets-manifest.js +1 -5
- package/dist/core/naruto/naruto-work-graph.js +70 -4
- package/dist/core/naruto/naruto-write-e2e.js +3 -4
- package/dist/core/ops/reporting.js +3 -0
- package/dist/core/pipeline-internals/runtime-core.js +12 -7
- package/dist/core/pipeline-internals/runtime-gates.js +17 -1
- package/dist/core/ppt/style-tokens.js +1 -1
- package/dist/core/ppt-review/index.js +1 -1
- package/dist/core/ppt-review/slide-exporter.js +23 -17
- package/dist/core/ppt-review/slide-imagegen-review.js +1 -1
- package/dist/core/ppt-review/slide-issue-extraction.js +4 -2
- package/dist/core/product-design-plugin.js +2 -2
- package/dist/core/proof/route-finalizer.js +1 -1
- package/dist/core/proof-field.js +3 -3
- package/dist/core/provider/model-router.js +68 -3
- package/dist/core/release/gate-manifest.js +18 -12
- package/dist/core/release/gate-pack-manifest.js +1 -1
- package/dist/core/release/package-size-budget.js +2 -0
- package/dist/core/release/release-gate-affected-selector.js +1 -1
- package/dist/core/release/release-gate-dag.js +43 -3
- package/dist/core/release/release-gate-hermetic-env.js +28 -17
- package/dist/core/release/release-real-contract.js +416 -0
- package/dist/core/retention/retention-budget.js +25 -6
- package/dist/core/retention.js +980 -101
- package/dist/core/routes/constants.js +1 -1
- package/dist/core/routes/evidence.js +4 -4
- package/dist/core/routes/model-mode-router.js +3 -0
- package/dist/core/routes/ppt-policy.js +1 -1
- package/dist/core/routes.js +11 -12
- package/dist/core/secret-redaction.js +4 -0
- package/dist/core/triwiki/code-pack.js +8 -2
- package/dist/core/triwiki/triwiki-cache-key.js +108 -29
- package/dist/core/triwiki-attention.js +13 -6
- package/dist/core/triwiki-provenance.js +274 -0
- package/dist/core/triwiki-runtime.js +21 -7
- package/dist/core/triwiki-wrongness/wrongness-ledger.js +178 -59
- package/dist/core/triwiki-wrongness/wrongness-retrieval.js +11 -2
- package/dist/core/triwiki-wrongness/wrongness-trust-policy.js +2 -0
- package/dist/core/update/update-migration-state.js +1 -1
- package/dist/core/update/update-notice.js +23 -0
- package/dist/core/update-check.js +69 -25
- package/dist/core/version.js +1 -1
- package/dist/core/wiki-coordinate.js +128 -12
- package/dist/core/work-order-ledger.js +168 -9
- package/dist/core/zellij/zellij-command.js +12 -1
- package/dist/core/zellij/zellij-dashboard-pane.js +3 -3
- package/dist/core/zellij/zellij-launcher.js +15 -14
- package/dist/core/zellij/zellij-pane-proof.js +32 -6
- package/dist/core/zellij/zellij-worker-pane-manager.js +5 -3
- package/dist/scripts/agent-fast-mode-default-check.js +48 -29
- package/dist/scripts/agent-role-config-repair-check.js +25 -4
- package/dist/scripts/agent-wiki-context-proof-check.js +16 -2
- package/dist/scripts/all-feature-deep-completion-check.js +14 -4
- package/dist/scripts/build-dist.js +17 -5
- package/dist/scripts/canonical-test-runner.js +188 -0
- package/dist/scripts/check-command-module-budget.js +38 -16
- package/dist/scripts/check-legacy-free.js +1 -1
- package/dist/scripts/codex-0139-interrupt-agent-check.js +5 -1
- package/dist/scripts/{codex-0142-app-server-v2-check.js → codex-0144-app-server-v2-check.js} +11 -10
- package/dist/scripts/{codex-0142-binary-identity-check.js → codex-0144-binary-identity-check.js} +4 -4
- package/dist/scripts/codex-0144-capability-check.js +21 -0
- package/dist/scripts/{codex-0139-real-probes-check.js → codex-0144-core-real-probes-check.js} +19 -5
- package/dist/scripts/{codex-0142-doctor-wiring-check.js → codex-0144-doctor-wiring-check.js} +6 -6
- package/dist/scripts/{codex-0142-manifest-check.js → codex-0144-manifest-check.js} +11 -3
- package/dist/scripts/{codex-0142-policy-check.js → codex-0144-policy-check.js} +2 -2
- package/dist/scripts/{codex-0142-thread-store-check.js → codex-0144-thread-store-check.js} +3 -3
- package/dist/scripts/codex-app-provider-model-ui-check.js +57 -8
- package/dist/scripts/codex-app-ui-preservation-check.js +35 -4
- package/dist/scripts/codex-control-side-effect-scope-check.js +2 -2
- package/dist/scripts/codex-effort-auto-discovery-check.js +1 -1
- package/dist/scripts/codex-lb-fast-mode-truth-check.js +1 -0
- package/dist/scripts/{codex-lb-gpt55-fast-profile-check.js → codex-lb-gpt56-fast-profile-check.js} +56 -5
- package/dist/scripts/codex-model-metadata-check.js +1 -1
- package/dist/scripts/codex-sdk-sandbox-policy-check.js +5 -1
- package/dist/scripts/codex-sdk-version-compat-check.js +2 -1
- package/dist/scripts/dfix-fixture-check.js +1 -1
- package/dist/scripts/docs-truthfulness-check.js +1 -1
- package/dist/scripts/doctor-codex-startup-repair-check.js +35 -10
- package/dist/scripts/doctor-context7-repair-check.js +2 -1
- package/dist/scripts/doctor-fix-proves-codex-read-check.js +1 -1
- package/dist/scripts/doctor-fixes-codex-app-fast-ui-check.js +34 -7
- package/dist/scripts/doctor-imagegen-repair-check.js +14 -4
- package/dist/scripts/doctor-startup-config-repair-blackbox.js +1 -1
- package/dist/scripts/doctor-startup-config-repair-check.js +1 -1
- package/dist/scripts/gate-policy-audit-check.js +2 -2
- package/dist/scripts/install-update-preserves-config-check.js +1 -1
- package/dist/scripts/legacy-gate-inventory-check.js +7 -5
- package/dist/scripts/legacy-strong-inventory-check.js +7 -5
- package/dist/scripts/legacy-upgrade-matrix-check.js +5 -5
- package/dist/scripts/lib/native-cli-session-swarm-check-lib.js +175 -14
- package/dist/scripts/mad-sks-app-ui-no-mutation-check.js +166 -6
- package/dist/scripts/mutation-callsite-coverage-check.js +0 -11
- package/dist/scripts/naruto-shadow-clone-swarm-check.js +88 -50
- package/dist/scripts/npm-publish-performance-check.js +2 -1
- package/dist/scripts/package-published-contract-check.js +9 -0
- package/dist/scripts/packlist-performance-check.js +5 -2
- package/dist/scripts/postinstall-safe-side-effects-check.js +8 -3
- package/dist/scripts/ppt-no-mock-as-real-check.js +3 -1
- package/dist/scripts/product-design-plugin-routing-check.js +1 -1
- package/dist/scripts/release-check-stamp.js +182 -2
- package/dist/scripts/release-dag-full-coverage-check.js +7 -7
- package/dist/scripts/release-dynamic-presets-check.js +8 -0
- package/dist/scripts/release-gate-dag-runner-check.js +3 -2
- package/dist/scripts/release-gate-dag-runner.js +24 -11
- package/dist/scripts/release-gate-existence-audit.js +8 -9
- package/dist/scripts/release-gate-script-parity-check.js +1 -1
- package/dist/scripts/release-real-check.js +368 -157
- package/dist/scripts/release-runtime-truth-matrix-check.js +22 -0
- package/dist/scripts/route-proof-artifact-structure-check.js +1 -0
- package/dist/scripts/scheduler-batch-dispatch-check.js +1 -1
- package/dist/scripts/search-visibility-gate-lib.js +1 -1
- package/dist/scripts/seo-geo-route-identity-check.js +30 -4
- package/dist/scripts/sizecheck.js +7 -2
- package/dist/scripts/sks-1-11-gate-lib.js +53 -6
- package/dist/scripts/sks-menubar-install-check.js +7 -0
- package/dist/scripts/sks-uninstall-regression-check.js +1 -1
- package/dist/scripts/sksd-daemon-check.js +16 -6
- package/dist/scripts/update-default-command-check.js +4 -2
- package/dist/scripts/write-build-manifest.js +2 -1
- package/dist/scripts/zellij-layout-valid-check.js +31 -6
- package/dist/scripts/zellij-pane-proof-check.js +33 -2
- package/dist/scripts/zellij-real-session-cleanup-check.js +122 -2
- package/dist/scripts/zellij-real-session-launch-check.js +76 -5
- package/dist/scripts/zellij-slot-pane-renderer-check.js +4 -4
- package/package.json +27 -30
- package/schemas/codex/{app-server-0.142 → app-server-0.144}/codex_app_server_protocol.v2.schemas.json +1146 -781
- package/schemas/codex/codex-0139-real-probe-result.schema.json +39 -5
- package/schemas/codex/ppt-slide-issue-ledger.schema.json +2 -1
- package/dist/core/codex-control/codex-0139-multi-agent-real-probe.js +0 -107
- package/dist/scripts/agent-native-release-gate.js +0 -274
- package/dist/scripts/codex-0142-capability-check.js +0 -21
- package/dist/scripts/command-performance-scorecard-check.js +0 -204
- package/dist/scripts/config-managed-merge-callsite-coverage-check.js +0 -212
- package/dist/scripts/dollar-performance-scorecard-check.js +0 -257
- package/dist/scripts/gate-timing-check.js +0 -16
- package/dist/scripts/ops-maturity-scorecard-check.js +0 -12
- package/dist/scripts/performance-baseline-check.js +0 -12
- package/dist/scripts/performance-improvement-report-check.js +0 -58
- package/dist/scripts/release-parallel-check.js +0 -389
- package/dist/scripts/release-runner-efficiency-check.js +0 -15
- package/dist/scripts/retention-long-run-smoke-check.js +0 -299
- package/docs/assets/sneakoscope-architecture-pipeline.jpg +0 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { buildRuntimeTruthMatrix, writeRuntimeTruthMatrix } from '../core/proof/runtime-truth-matrix.js';
|
|
6
|
+
import { assertGate, emitGate, root } from './sks-1-18-gate-lib.js';
|
|
7
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8'));
|
|
8
|
+
const matrix = await buildRuntimeTruthMatrix({
|
|
9
|
+
root,
|
|
10
|
+
releaseVersion: String(pkg.version || '')
|
|
11
|
+
});
|
|
12
|
+
await writeRuntimeTruthMatrix(root, matrix);
|
|
13
|
+
assertGate(matrix.ok === true, 'runtime truth matrix contains blocking evidence', {
|
|
14
|
+
blockers: matrix.blockers,
|
|
15
|
+
required_rows: matrix.rows.filter((row) => row.required_mode)
|
|
16
|
+
});
|
|
17
|
+
emitGate('release:runtime-truth-matrix', {
|
|
18
|
+
report: `.sneakoscope/reports/runtime-truth-matrix-${pkg.version}.json`,
|
|
19
|
+
rows: matrix.rows.length,
|
|
20
|
+
priorities: matrix.priorities
|
|
21
|
+
});
|
|
22
|
+
//# sourceMappingURL=release-runtime-truth-matrix-check.js.map
|
|
@@ -69,6 +69,7 @@ async function runNegativeFixture() {
|
|
|
69
69
|
mission_id: mission,
|
|
70
70
|
status: 'verified',
|
|
71
71
|
route: '$Team',
|
|
72
|
+
execution_class: 'real',
|
|
72
73
|
summary: { files_changed: 0, commands_run: 0, tests_passed: 0, tests_failed: 0, manual_review_required: false },
|
|
73
74
|
evidence: {
|
|
74
75
|
agents: {
|
|
@@ -12,6 +12,6 @@ const count = 6;
|
|
|
12
12
|
const roster = { agent_count: count, roster: Array.from({ length: count }, (_, i) => ({ id: `a${i + 1}`, persona_id: `p${i + 1}`, role: 'verifier' })) };
|
|
13
13
|
const partition = { slices: Array.from({ length: count }, (_, i) => ({ id: `w${i + 1}`, description: 'batch', write_paths: [], readonly_paths: [] })) };
|
|
14
14
|
const result = await runAgentScheduler({ root: ledgerRoot, missionId, rootHash: 'fixture', roster, partition, targetActiveSlots: count, maxActiveSlots: count, launchSession: async ({ generation, agent, workItem }) => ({ schema: 'sks.agent-result.v1', mission_id: missionId, agent_id: agent.id, session_id: generation.session_id, persona_id: agent.persona_id, task_slice_id: workItem.id, status: 'done', backend: 'fake', summary: 'ok', findings: [], proposed_changes: [], changed_files: [], lease_compliance: { ok: true, violations: [] }, artifacts: [], blockers: [], confidence: 'high', handoff_notes: '', unverified: [], writes: [], recursion_guard: { ok: true, violations: [] }, verification: { status: 'passed', checks: [] } }) });
|
|
15
|
-
assertGate(result.state.batch_dispatch_count >= 1 && result.state.largest_batch_size >=
|
|
15
|
+
assertGate(result.state.batch_dispatch_count >= 1 && result.state.largest_batch_size >= result.state.target_active_slots, 'scheduler did not dispatch a full effective launch batch', result.state);
|
|
16
16
|
emitGate('scheduler:batch-dispatch', result.state);
|
|
17
17
|
//# sourceMappingURL=scheduler-batch-dispatch-check.js.map
|
|
@@ -36,7 +36,7 @@ export function makeSearchVisibilityFixture(name = 'search-visibility', options
|
|
|
36
36
|
}
|
|
37
37
|
export function runSks(args, options = {}) {
|
|
38
38
|
const result = spawnSync(process.execPath, [path.join(root, 'dist', 'bin', 'sks.js'), ...args], {
|
|
39
|
-
cwd: root,
|
|
39
|
+
cwd: options.cwd || root,
|
|
40
40
|
encoding: 'utf8',
|
|
41
41
|
stdio: 'pipe',
|
|
42
42
|
env: {
|
|
@@ -1,12 +1,38 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// @ts-nocheck
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { assertGate, emitGate, makeSearchVisibilityFixture, runSksJson } from './search-visibility-gate-lib.js';
|
|
6
|
+
const fixture = makeSearchVisibilityFixture('seo-geo-route-identity');
|
|
7
|
+
fs.mkdirSync(path.join(fixture, '.sneakoscope'), { recursive: true });
|
|
8
|
+
let seo;
|
|
9
|
+
let geo;
|
|
10
|
+
let seoMissionIsolated = false;
|
|
11
|
+
let geoMissionIsolated = false;
|
|
12
|
+
const cleanupFixture = () => fs.rmSync(fixture, { recursive: true, force: true });
|
|
13
|
+
process.once('exit', cleanupFixture);
|
|
14
|
+
try {
|
|
15
|
+
seo = runSksJson(['run', '$SEO-GEO-OPTIMIZER SEO audit this fixture', '--execute', '--json'], { cwd: fixture }).json;
|
|
16
|
+
seoMissionIsolated = fs.existsSync(path.join(fixture, '.sneakoscope', 'missions', seo.mission_id));
|
|
17
|
+
geo = runSksJson(['run', '$SEO-GEO-OPTIMIZER Generative Engine Optimization audit AI search visibility', '--execute', '--json'], { cwd: fixture }).json;
|
|
18
|
+
geoMissionIsolated = fs.existsSync(path.join(fixture, '.sneakoscope', 'missions', geo.mission_id));
|
|
19
|
+
}
|
|
20
|
+
finally {
|
|
21
|
+
cleanupFixture();
|
|
22
|
+
process.removeListener('exit', cleanupFixture);
|
|
23
|
+
}
|
|
6
24
|
const seoText = JSON.stringify(seo);
|
|
7
25
|
const geoText = JSON.stringify(geo);
|
|
26
|
+
assertGate(seoMissionIsolated && geoMissionIsolated, 'SEO/GEO route identity missions must stay inside the hermetic fixture', {
|
|
27
|
+
fixture,
|
|
28
|
+
seo_mission_id: seo.mission_id,
|
|
29
|
+
geo_mission_id: geo.mission_id,
|
|
30
|
+
seo_mission_isolated: seoMissionIsolated,
|
|
31
|
+
geo_mission_isolated: geoMissionIsolated
|
|
32
|
+
});
|
|
8
33
|
assertGate(/\$SEO-GEO-OPTIMIZER/.test(seoText) && /sks seo-geo-optimizer/.test(seoText) && /--mode seo/.test(seoText), 'sks run --execute must preserve unified optimizer route and execute seo mode path', seo);
|
|
9
34
|
assertGate(/\$SEO-GEO-OPTIMIZER/.test(geoText) && /sks seo-geo-optimizer/.test(geoText) && /--mode geo/.test(geoText), 'sks run --execute must preserve unified optimizer route and execute geo mode path', geo);
|
|
10
35
|
assertGate(!/\$AutoResearch/.test(seoText) && !/\$AutoResearch/.test(geoText), 'SEO/GEO route identity must not collapse into AutoResearch', { seo, geo });
|
|
11
|
-
|
|
36
|
+
assertGate(!fs.existsSync(fixture), 'SEO/GEO route identity fixture must be removed after the check', { fixture });
|
|
37
|
+
emitGate('seo-geo:route-identity', { seo_status: seo.status, geo_status: geo.status, hermetic_fixture_removed: true });
|
|
12
38
|
//# sourceMappingURL=seo-geo-route-identity-check.js.map
|
|
@@ -5,9 +5,10 @@ import fs from 'node:fs';
|
|
|
5
5
|
import os from 'node:os';
|
|
6
6
|
import path from 'node:path';
|
|
7
7
|
import { fileURLToPath } from 'node:url';
|
|
8
|
+
import { DEFAULT_MAX_PACK_BYTES } from '../core/release/package-size-budget.js';
|
|
8
9
|
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..');
|
|
9
10
|
const limits = {
|
|
10
|
-
packedBytes: Number(process.env.SKS_MAX_PACK_BYTES ||
|
|
11
|
+
packedBytes: Number(process.env.SKS_MAX_PACK_BYTES || DEFAULT_MAX_PACK_BYTES),
|
|
11
12
|
unpackedBytes: Number(process.env.SKS_MAX_UNPACKED_BYTES || 10 * 1024 * 1024),
|
|
12
13
|
packFiles: Number(process.env.SKS_MAX_PACK_FILES || 2100),
|
|
13
14
|
trackedFileBytes: Number(process.env.SKS_MAX_TRACKED_FILE_BYTES || 384 * 1024)
|
|
@@ -16,7 +17,11 @@ const trackedFileSizeAllowlist = new Set([
|
|
|
16
17
|
// Historical source documentation export; not included in the npm package payload.
|
|
17
18
|
'docs/sks-local-llm-mode/exports/sks-local-llm-mode-deck.pdf',
|
|
18
19
|
// Central release DAG manifest; package footprint limits still apply below.
|
|
19
|
-
'release-gates.v2.json'
|
|
20
|
+
'release-gates.v2.json',
|
|
21
|
+
// Generated Codex App Server protocol schemas; handwritten sources remain
|
|
22
|
+
// subject to the 384 KiB split-review limit.
|
|
23
|
+
'schemas/codex/app-server-0.144/codex_app_server_protocol.schemas.json',
|
|
24
|
+
'schemas/codex/app-server-0.144/codex_app_server_protocol.v2.schemas.json'
|
|
20
25
|
]);
|
|
21
26
|
const npmBin = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
22
27
|
function fail(message, detail = '') {
|
|
@@ -4,7 +4,11 @@ import fs from 'node:fs';
|
|
|
4
4
|
import path from 'node:path';
|
|
5
5
|
import { spawnSync } from 'node:child_process';
|
|
6
6
|
import { fileURLToPath } from 'node:url';
|
|
7
|
+
import { tmpdir } from '../core/fsx.js';
|
|
7
8
|
export const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..');
|
|
9
|
+
const fixtureMissionRoots = new Map();
|
|
10
|
+
const fixtureRoots = new Set();
|
|
11
|
+
let fixtureCleanupRegistered = false;
|
|
8
12
|
export function assertGate(condition, message, detail = {}) {
|
|
9
13
|
if (condition)
|
|
10
14
|
return;
|
|
@@ -14,14 +18,15 @@ export function assertGate(condition, message, detail = {}) {
|
|
|
14
18
|
export function emitGate(name, detail = {}) {
|
|
15
19
|
console.log(JSON.stringify({ schema: 'sks.release-gate.v1', ok: true, gate: name, ...detail }, null, 2));
|
|
16
20
|
}
|
|
17
|
-
export function runSksJson(args) {
|
|
21
|
+
export function runSksJson(args, options = {}) {
|
|
18
22
|
const entrypoint = path.join(root, 'dist', 'bin', 'sks.js');
|
|
19
23
|
assertGate(fs.existsSync(entrypoint), 'dist entrypoint missing; run npm run build first', { entrypoint });
|
|
24
|
+
const mappedMissionRoot = args.map((arg) => fixtureMissionRoots.get(String(arg))).find(Boolean);
|
|
20
25
|
const result = spawnSync(process.execPath, [entrypoint, ...args], {
|
|
21
|
-
cwd: root,
|
|
26
|
+
cwd: options.cwd || mappedMissionRoot || root,
|
|
22
27
|
encoding: 'utf8',
|
|
23
28
|
timeout: Number(process.env.SKS_GATE_TIMEOUT_MS || 120_000),
|
|
24
|
-
env: { ...process.env, SKS_SKIP_NPM_FRESHNESS_CHECK: '1', CI: 'true' }
|
|
29
|
+
env: { ...process.env, SKS_SKIP_NPM_FRESHNESS_CHECK: '1', CI: 'true', ...(options.env || {}) }
|
|
25
30
|
});
|
|
26
31
|
let parsed = null;
|
|
27
32
|
try {
|
|
@@ -36,7 +41,10 @@ export function runSksJson(args) {
|
|
|
36
41
|
return { ...parsed, _process_status: result.status, _stderr_tail: String(result.stderr || '').slice(-600) };
|
|
37
42
|
}
|
|
38
43
|
export function runPptReview(action = 'review') {
|
|
39
|
-
const json =
|
|
44
|
+
const json = runHermeticRouteFixture('ppt', ['ppt', 'fixture', '--mock', '--json'], {
|
|
45
|
+
SKS_TEST_FAKE_IMAGEGEN: '1',
|
|
46
|
+
SKS_TEST_FAKE_EXTRACTOR: '1'
|
|
47
|
+
});
|
|
40
48
|
const proof = readMissionJson(json.mission_id, 'completion-proof.json');
|
|
41
49
|
const review = json.artifacts || json.imagegen_review || {};
|
|
42
50
|
json.proof_evidence = proof.evidence?.ppt_review || json.artifacts?.proof_evidence || {};
|
|
@@ -54,7 +62,7 @@ export function runPptReview(action = 'review') {
|
|
|
54
62
|
return json;
|
|
55
63
|
}
|
|
56
64
|
export function runDfixFixture() {
|
|
57
|
-
const json =
|
|
65
|
+
const json = runHermeticRouteFixture('dfix', ['dfix', 'fixture', '--json']);
|
|
58
66
|
json.gate = json.gate || json.artifacts?.gate;
|
|
59
67
|
assertGate(json.ok === true, 'dfix fixture blocked', json);
|
|
60
68
|
assertGate(json.gate?.passed === true, 'dfix gate did not pass', json.gate);
|
|
@@ -66,7 +74,8 @@ export function runUxFixture() {
|
|
|
66
74
|
return json;
|
|
67
75
|
}
|
|
68
76
|
export function missionFile(missionId, file) {
|
|
69
|
-
|
|
77
|
+
const missionRoot = fixtureMissionRoots.get(missionId) || root;
|
|
78
|
+
return path.join(missionRoot, '.sneakoscope', 'missions', missionId, file);
|
|
70
79
|
}
|
|
71
80
|
export function readMissionJson(missionId, file) {
|
|
72
81
|
const absolute = missionFile(missionId, file);
|
|
@@ -77,4 +86,42 @@ export function hasRelationType(missionId, type) {
|
|
|
77
86
|
const ledger = readMissionJson(missionId, 'image-voxel-ledger.json');
|
|
78
87
|
return (ledger.relations || []).some((relation) => relation.type === type);
|
|
79
88
|
}
|
|
89
|
+
function createHermeticRouteFixtureRoot(label) {
|
|
90
|
+
const fixtureRoot = tmpdir(`${label}-release-fixture-`);
|
|
91
|
+
fs.writeFileSync(path.join(fixtureRoot, 'package.json'), `${JSON.stringify({ name: `sks-${label}-release-fixture`, private: true })}\n`);
|
|
92
|
+
fixtureRoots.add(fixtureRoot);
|
|
93
|
+
if (!fixtureCleanupRegistered) {
|
|
94
|
+
fixtureCleanupRegistered = true;
|
|
95
|
+
process.once('exit', () => {
|
|
96
|
+
for (const candidate of fixtureRoots)
|
|
97
|
+
fs.rmSync(candidate, { recursive: true, force: true });
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
return fixtureRoot;
|
|
101
|
+
}
|
|
102
|
+
function runHermeticRouteFixture(label, args, env = {}) {
|
|
103
|
+
const fixtureRoot = createHermeticRouteFixtureRoot(label);
|
|
104
|
+
const fixtureHome = path.join(fixtureRoot, 'home');
|
|
105
|
+
const json = runSksJson(args, {
|
|
106
|
+
cwd: fixtureRoot,
|
|
107
|
+
env: {
|
|
108
|
+
HOME: fixtureHome,
|
|
109
|
+
CODEX_HOME: path.join(fixtureHome, '.codex'),
|
|
110
|
+
SKS_GLOBAL_ROOT: path.join(fixtureHome, '.sneakoscope-global'),
|
|
111
|
+
TMPDIR: fixtureRoot,
|
|
112
|
+
TMP: fixtureRoot,
|
|
113
|
+
TEMP: fixtureRoot,
|
|
114
|
+
PWD: fixtureRoot,
|
|
115
|
+
SKS_TEST_ISOLATION: '1',
|
|
116
|
+
SKS_UPDATE_MIGRATION_GATE_DISABLED: '1',
|
|
117
|
+
NODE_ENV: 'test',
|
|
118
|
+
CI: 'true',
|
|
119
|
+
...env
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
if (json.mission_id)
|
|
123
|
+
fixtureMissionRoots.set(json.mission_id, fixtureRoot);
|
|
124
|
+
json.fixture_root = fixtureRoot;
|
|
125
|
+
return json;
|
|
126
|
+
}
|
|
80
127
|
//# sourceMappingURL=sks-1-11-gate-lib.js.map
|
|
@@ -126,6 +126,11 @@ const hasActionFallbacks = actionScript.includes('command -v sks')
|
|
|
126
126
|
&& actionScript.includes('/bin/zsh -lc')
|
|
127
127
|
&& actionScript.includes('exit 127')
|
|
128
128
|
&& actionScript.includes('display notification');
|
|
129
|
+
const pinnedEntryIndex = actionScript.indexOf('run_node_entry "$SKS_ENTRY" "$@"');
|
|
130
|
+
const hasPinnedEntryPriority = pinnedEntryIndex >= 0
|
|
131
|
+
&& pinnedEntryIndex < actionScript.indexOf('command -v sks')
|
|
132
|
+
&& pinnedEntryIndex < actionScript.indexOf('npm root -g')
|
|
133
|
+
&& actionScript.lastIndexOf('run_node_entry "$SKS_ENTRY" "$@"') === pinnedEntryIndex;
|
|
129
134
|
const hasEntryWarning = result.warnings.includes('sks_entry_project_local');
|
|
130
135
|
const hasBuildStamp = buildStampExists
|
|
131
136
|
&& result.build_stamp?.package_version === PACKAGE_VERSION
|
|
@@ -203,6 +208,7 @@ const darwinOk = cltMissing
|
|
|
203
208
|
&& hasInteractiveProcessType
|
|
204
209
|
&& hasPackagePlistVersion
|
|
205
210
|
&& hasActionFallbacks
|
|
211
|
+
&& hasPinnedEntryPriority
|
|
206
212
|
&& hasEntryWarning
|
|
207
213
|
&& hasBuildStamp
|
|
208
214
|
&& swiftParse.ok === true
|
|
@@ -249,6 +255,7 @@ const report = {
|
|
|
249
255
|
has_interactive_process_type: hasInteractiveProcessType,
|
|
250
256
|
has_package_plist_version: hasPackagePlistVersion,
|
|
251
257
|
has_action_fallbacks: hasActionFallbacks,
|
|
258
|
+
has_pinned_entry_priority: hasPinnedEntryPriority,
|
|
252
259
|
has_entry_warning: hasEntryWarning,
|
|
253
260
|
has_build_stamp: hasBuildStamp,
|
|
254
261
|
swift_parse: swiftParse,
|
|
@@ -17,7 +17,7 @@ await writeText(path.join(home, '.codex', 'config.toml'), [
|
|
|
17
17
|
'default_profile = "sks-fast-high"',
|
|
18
18
|
'service_tier = "fast"',
|
|
19
19
|
'[profiles.sks-fast-high]',
|
|
20
|
-
'model = "gpt-5.
|
|
20
|
+
'model = "gpt-5.6-terra"',
|
|
21
21
|
'[user.fast_mode]',
|
|
22
22
|
'enabled = true',
|
|
23
23
|
'[mcp_servers.user]',
|
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
|
-
import
|
|
2
|
+
import fs from 'node:fs/promises';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { assertGate, emitGate, importDist } from './sks-1-18-gate-lib.js';
|
|
3
6
|
const mod = await importDist('core/daemon/sksd-client.js');
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
const fixtureRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'sks-sksd-daemon-check-'));
|
|
8
|
+
try {
|
|
9
|
+
const state = mod.runSksdClient(fixtureRoot, 'status');
|
|
10
|
+
const start = mod.runSksdClient(fixtureRoot, 'start');
|
|
11
|
+
assertGate(state.schema === 'sks.sksd-state.v1', 'sksd status schema mismatch', state);
|
|
12
|
+
assertGate(start.protocol_ok === true && start.status === 'running', 'sksd start must record protocol-ready state', start);
|
|
13
|
+
assertGate(start.build_proof_ready === false, 'hermetic sksd protocol fixture must not build or mutate the source checkout', start);
|
|
14
|
+
emitGate('sksd:daemon', { status: start.status, hermetic_fixture: true, build_started: false });
|
|
15
|
+
}
|
|
16
|
+
finally {
|
|
17
|
+
await fs.rm(fixtureRoot, { recursive: true, force: true });
|
|
18
|
+
}
|
|
9
19
|
//# sourceMappingURL=sksd-daemon-check.js.map
|
|
@@ -12,7 +12,9 @@ const routes = fs.readFileSync('src/core/routes.ts', 'utf8');
|
|
|
12
12
|
assertGate(registry.includes("subcommand(() => import(basicModule), 'updateCommand', 'dist/core/commands/basic-cli.js', 'now')"), 'bare sks update must default to update now');
|
|
13
13
|
assertGate(basicCli.includes("export async function updateCommand(sub: any = 'now'"), 'updateCommand default must be now');
|
|
14
14
|
assertGate(basicCli.includes("action.startsWith('-')") && basicCli.includes('effectiveArgs = [String(sub), ...args]'), 'sks update --json/--dry-run must be treated as update now with flags');
|
|
15
|
-
assertGate(update.includes('
|
|
15
|
+
assertGate(update.includes("[entrypoint, 'menubar', 'install', '--json']")
|
|
16
|
+
&& update.includes('entrypoint: newBinary')
|
|
17
|
+
&& update.includes('sks_menubar'), 'update now must refresh the SKS menu bar through the updated package-local entrypoint');
|
|
16
18
|
assertGate(routes.includes('sks update [check|now]'), 'command catalog must document bare sks update as the default update path');
|
|
17
19
|
console.log(JSON.stringify({
|
|
18
20
|
schema: 'sks.update-default-command-check.v1',
|
|
@@ -21,7 +23,7 @@ console.log(JSON.stringify({
|
|
|
21
23
|
'registry_default_now',
|
|
22
24
|
'basic_cli_default_now',
|
|
23
25
|
'flag_first_default_now',
|
|
24
|
-
'
|
|
26
|
+
'updated_package_local_menubar_stage',
|
|
25
27
|
'command_catalog_usage'
|
|
26
28
|
]
|
|
27
29
|
}, null, 2));
|
|
@@ -5,6 +5,7 @@ import fsp from 'node:fs/promises';
|
|
|
5
5
|
import path from 'node:path';
|
|
6
6
|
import crypto from 'node:crypto';
|
|
7
7
|
import { fileURLToPath } from 'node:url';
|
|
8
|
+
import { writeTextAtomic } from '../core/fsx.js';
|
|
8
9
|
import { writeDistFreshStamp, sourceSnapshot } from './lib/ensure-dist-fresh.js';
|
|
9
10
|
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..');
|
|
10
11
|
const pkg = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8'));
|
|
@@ -22,7 +23,7 @@ const compiledDtsCount = sorted.filter((f) => f.endsWith('.d.ts')).length;
|
|
|
22
23
|
const source = sourceSnapshot();
|
|
23
24
|
const distStamp = writeDistFreshStamp();
|
|
24
25
|
const srcMjsRuntimeFiles = await collectSrcMjsRuntimeFiles();
|
|
25
|
-
await
|
|
26
|
+
await writeTextAtomic(path.join(distRoot, 'build-manifest.json'), `${JSON.stringify({
|
|
26
27
|
schema: 'sks.dist-build.v2',
|
|
27
28
|
version: pkg.version,
|
|
28
29
|
package_version: pkg.version,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// @ts-nocheck
|
|
3
3
|
import fs from 'node:fs/promises';
|
|
4
|
+
import { randomBytes } from 'node:crypto';
|
|
4
5
|
import os from 'node:os';
|
|
5
6
|
import path from 'node:path';
|
|
6
7
|
import { pathToFileURL } from 'node:url';
|
|
@@ -55,19 +56,27 @@ const layoutPath = path.join(tmp, 'layout.kdl');
|
|
|
55
56
|
await fs.writeFile(layoutPath, built.layout_kdl, 'utf8');
|
|
56
57
|
const requireReal = process.env.SKS_REQUIRE_ZELLIJ === '1' || process.argv.includes('--require-real');
|
|
57
58
|
const capability = await capabilityMod.checkZellijCapability({ root, require: requireReal, writeReport: true });
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
const runId = `${process.pid}-${Date.now().toString(36)}-${randomBytes(3).toString('hex')}`;
|
|
60
|
+
const sessionName = `sks-layout-check-${runId}`;
|
|
61
|
+
const socketDir = path.join('/tmp', `sks-zj-layout-${runId}`);
|
|
62
|
+
const zellijEnv = { ZELLIJ_SOCKET_DIR: socketDir };
|
|
61
63
|
const realRun = capability.status === 'ok'
|
|
62
64
|
? {
|
|
63
|
-
create_background: await commandMod.runZellij(['attach', '--create-background', sessionName, 'options', '--default-layout', layoutPath], { cwd: root, timeoutMs: 5000, optional: !requireReal }),
|
|
65
|
+
create_background: await commandMod.runZellij(['attach', '--create-background', sessionName, 'options', '--default-layout', layoutPath], { cwd: root, env: zellijEnv, timeoutMs: 5000, optional: !requireReal }),
|
|
64
66
|
cleanup: null,
|
|
67
|
+
session_removed: false,
|
|
68
|
+
socket_dir_removed: false,
|
|
65
69
|
ok: false
|
|
66
70
|
}
|
|
67
71
|
: null;
|
|
68
72
|
if (realRun) {
|
|
69
|
-
realRun.cleanup = await commandMod.runZellij(['kill-session', sessionName], { cwd: root, timeoutMs: 5000, optional: true });
|
|
70
|
-
|
|
73
|
+
realRun.cleanup = await commandMod.runZellij(['kill-session', sessionName], { cwd: root, env: zellijEnv, timeoutMs: 5000, optional: true });
|
|
74
|
+
const remaining = await waitForSocketEntriesToClear(socketDir, 2000);
|
|
75
|
+
realRun.session_removed = !remaining.includes(sessionName);
|
|
76
|
+
if (remaining.length === 0)
|
|
77
|
+
await fs.rm(socketDir, { recursive: true, force: true });
|
|
78
|
+
realRun.socket_dir_removed = !(await exists(socketDir));
|
|
79
|
+
realRun.ok = realRun.create_background.ok === true && realRun.session_removed && realRun.socket_dir_removed;
|
|
71
80
|
}
|
|
72
81
|
const ok = staticValidation.ok
|
|
73
82
|
&& viewportLayoutOk
|
|
@@ -77,6 +86,7 @@ const ok = staticValidation.ok
|
|
|
77
86
|
&& invalidValidation.ok === false
|
|
78
87
|
&& capability.ok
|
|
79
88
|
&& (requireReal ? realRun?.ok === true : true);
|
|
89
|
+
await fs.rm(tmp, { recursive: true, force: true });
|
|
80
90
|
emit({
|
|
81
91
|
schema: 'sks.zellij-layout-valid-check.v1',
|
|
82
92
|
ok,
|
|
@@ -88,10 +98,25 @@ emit({
|
|
|
88
98
|
invalid_fixture: invalidValidation,
|
|
89
99
|
capability,
|
|
90
100
|
real_run: realRun,
|
|
101
|
+
isolated_session: true,
|
|
102
|
+
socket_dir: socketDir,
|
|
103
|
+
temporary_layout_removed: !(await exists(tmp)),
|
|
91
104
|
integration_optional: !requireReal,
|
|
92
105
|
blockers: ok ? [] : ['zellij_layout_valid_check_failed']
|
|
93
106
|
});
|
|
94
107
|
function emit(report) { console.log(JSON.stringify(report, null, 2)); if (!report.ok)
|
|
95
108
|
process.exitCode = 1; }
|
|
96
109
|
function fail(blocker, detail) { emit({ schema: 'sks.zellij-layout-valid-check.v1', ok: false, blockers: [blocker], detail }); process.exit(1); }
|
|
110
|
+
async function waitForSocketEntriesToClear(socketDir, timeoutMs) {
|
|
111
|
+
const deadline = Date.now() + timeoutMs;
|
|
112
|
+
for (;;) {
|
|
113
|
+
const entries = await fs.readdir(path.join(socketDir, 'contract_version_1')).catch(() => []);
|
|
114
|
+
if (entries.length === 0 || Date.now() >= deadline)
|
|
115
|
+
return entries;
|
|
116
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
async function exists(value) {
|
|
120
|
+
return fs.access(value).then(() => true).catch(() => false);
|
|
121
|
+
}
|
|
97
122
|
//# sourceMappingURL=zellij-layout-valid-check.js.map
|
|
@@ -42,13 +42,44 @@ const codexLbOnlyMain = mod.evaluateZellijPaneProofRows(mod.normalizeZellijPaneR
|
|
|
42
42
|
{ pane_id: '1', name: 'orchestrator', command: 'sh -lc model_provider="codex-lb"', cwd: root, exited: false },
|
|
43
43
|
{ pane_id: '2', name: 'slot-001', command: 'sks zellij-lane --mission M --slot slot-001', cwd: root, exited: false }
|
|
44
44
|
]), { expectedLaneCount: 1, expectedCwd: root, expectedMainCommandIncludes: 'codex' });
|
|
45
|
+
const zellij044Rows = [
|
|
46
|
+
...Array.from({ length: 120 }, (_, index) => ({
|
|
47
|
+
id: index + 10,
|
|
48
|
+
is_plugin: true,
|
|
49
|
+
title: `zellij:fixture-${String(index).padStart(3, '0')}`,
|
|
50
|
+
terminal_command: null,
|
|
51
|
+
plugin_url: 'zellij:fixture',
|
|
52
|
+
tab_name: 'SKS fixture'
|
|
53
|
+
})),
|
|
54
|
+
{
|
|
55
|
+
id: 0,
|
|
56
|
+
is_plugin: false,
|
|
57
|
+
title: 'orchestrator',
|
|
58
|
+
exited: false,
|
|
59
|
+
exit_status: null,
|
|
60
|
+
pane_x: 0,
|
|
61
|
+
pane_y: 1,
|
|
62
|
+
pane_columns: 80,
|
|
63
|
+
pane_rows: 24,
|
|
64
|
+
terminal_command: "sh -lc exec 'codex' '--no-alt-screen'",
|
|
65
|
+
pane_command: `${path.join(root, 'node_modules', '.bin', 'codex')} --no-alt-screen`,
|
|
66
|
+
pane_cwd: root,
|
|
67
|
+
tab_name: 'SKS fixture'
|
|
68
|
+
}
|
|
69
|
+
];
|
|
70
|
+
const zellij044Json = JSON.stringify(zellij044Rows);
|
|
71
|
+
const zellij044Parsed = mod.parseZellijPaneRows(zellij044Json);
|
|
72
|
+
const zellij044Evaluation = mod.evaluateZellijPaneProofRows(mod.normalizeZellijPaneRows(zellij044Parsed), { expectedLaneCount: 0, expectedCwd: root, expectedMainCommandIncludes: 'codex' });
|
|
45
73
|
const fixtureOk = positive.blockers.length === 0
|
|
46
74
|
&& missingLane.blockers.includes('zellij_lane_pane_missing')
|
|
47
75
|
&& exitedLane.blockers.some((blocker) => blocker.startsWith('zellij_lane_pane_exited'))
|
|
48
76
|
&& madCodexMain.blockers.length === 0
|
|
49
77
|
&& madShellMain.blockers.includes('zellij_main_pane_unexpected_command:codex')
|
|
50
|
-
&& codexLbOnlyMain.blockers.includes('zellij_main_pane_unexpected_command:codex')
|
|
51
|
-
|
|
78
|
+
&& codexLbOnlyMain.blockers.includes('zellij_main_pane_unexpected_command:codex')
|
|
79
|
+
&& zellij044Json.length > 8192
|
|
80
|
+
&& zellij044Parsed.length === zellij044Rows.length
|
|
81
|
+
&& zellij044Evaluation.blockers.length === 0;
|
|
82
|
+
emit({ ...report, fixture_ok: fixtureOk, fixture_results: { positive, missingLane, exitedLane, madCodexMain, madShellMain, codexLbOnlyMain, zellij044: { json_bytes: Buffer.byteLength(zellij044Json), parsed_rows: zellij044Parsed.length, evaluation: zellij044Evaluation } }, ok: report.ok && fixtureOk });
|
|
52
83
|
function emit(report) { console.log(JSON.stringify(report, null, 2)); if (!report.ok)
|
|
53
84
|
process.exitCode = 1; }
|
|
54
85
|
function fail(blocker, detail) { emit({ schema: 'sks.zellij-pane-proof-check.v1', ok: false, blockers: [blocker], detail }); process.exit(1); }
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// @ts-nocheck
|
|
3
|
+
import fs from 'node:fs/promises';
|
|
4
|
+
import { createHash } from 'node:crypto';
|
|
3
5
|
import path from 'node:path';
|
|
4
6
|
import { pathToFileURL } from 'node:url';
|
|
5
7
|
import { ensureDistFresh, root } from './lib/ensure-dist-fresh.js';
|
|
@@ -7,10 +9,96 @@ const freshness = ensureDistFresh({ rebuild: false });
|
|
|
7
9
|
if (!freshness.ok)
|
|
8
10
|
fail('dist_not_fresh', { freshness });
|
|
9
11
|
const args = process.argv.slice(2);
|
|
12
|
+
const missionId = readArg(args, '--mission');
|
|
10
13
|
const sessionName = readArg(args, '--session') || 'sks-real';
|
|
14
|
+
const socketDir = readArg(args, '--owned-socket-dir');
|
|
15
|
+
const ownerToken = String(process.env.SKS_ZELLIJ_CHECK_OWNER_TOKEN || '');
|
|
11
16
|
const command = await import(pathToFileURL(path.join(root, 'dist', 'core', 'zellij', 'zellij-command.js')).href);
|
|
12
|
-
const
|
|
13
|
-
|
|
17
|
+
const ownershipPath = missionId ? path.join(root, '.sneakoscope', 'missions', missionId, 'zellij-real-session-ownership.json') : null;
|
|
18
|
+
const expectedLayoutPath = missionId ? path.join(root, '.sneakoscope', 'layouts', `mad-${missionId}.kdl`) : null;
|
|
19
|
+
const ownership = ownershipPath ? await readJson(ownershipPath) : null;
|
|
20
|
+
const ownershipBlockers = [
|
|
21
|
+
...(!missionId ? ['zellij_cleanup_mission_missing'] : []),
|
|
22
|
+
...(!isSafeOwnedSocketDir(socketDir) ? ['zellij_cleanup_owned_socket_dir_invalid'] : []),
|
|
23
|
+
...(ownerToken.length < 32 ? ['zellij_cleanup_owner_token_missing'] : []),
|
|
24
|
+
...(!ownership ? ['zellij_cleanup_ownership_marker_missing'] : []),
|
|
25
|
+
...(ownership && ownership.schema !== 'sks.zellij-real-session-ownership.v1' ? ['zellij_cleanup_ownership_schema_invalid'] : []),
|
|
26
|
+
...(ownership && ownership.mission_id !== missionId ? ['zellij_cleanup_mission_mismatch'] : []),
|
|
27
|
+
...(ownership && ownership.session_name !== sessionName ? ['zellij_cleanup_session_mismatch'] : []),
|
|
28
|
+
...(ownership && path.resolve(String(ownership.socket_dir || '')) !== path.resolve(String(socketDir || '')) ? ['zellij_cleanup_socket_dir_mismatch'] : []),
|
|
29
|
+
...(ownership && ownership.owner_token_sha256 !== hashOwnerToken(ownerToken) ? ['zellij_cleanup_owner_token_mismatch'] : []),
|
|
30
|
+
...(ownership && ownership.cleanup_authorized !== true ? ['zellij_cleanup_not_authorized'] : []),
|
|
31
|
+
...(ownership && ownership.layout_cleanup_authorized !== true ? ['zellij_cleanup_layout_not_authorized'] : []),
|
|
32
|
+
...(ownership && path.resolve(String(ownership.layout_path || '')) !== path.resolve(String(expectedLayoutPath || '')) ? ['zellij_cleanup_layout_path_mismatch'] : [])
|
|
33
|
+
];
|
|
34
|
+
if (ownershipBlockers.length > 0) {
|
|
35
|
+
emit({
|
|
36
|
+
schema: 'sks.zellij-real-session-cleanup-check.v1',
|
|
37
|
+
ok: false,
|
|
38
|
+
mutation_attempted: false,
|
|
39
|
+
mission_id: missionId,
|
|
40
|
+
session_name: sessionName,
|
|
41
|
+
socket_dir: socketDir,
|
|
42
|
+
ownership_path: ownershipPath,
|
|
43
|
+
blockers: ownershipBlockers
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
const beforeEntries = await socketEntries(socketDir);
|
|
48
|
+
const result = await command.runZellij(['kill-session', sessionName], {
|
|
49
|
+
cwd: root,
|
|
50
|
+
env: { ZELLIJ_SOCKET_DIR: socketDir },
|
|
51
|
+
timeoutMs: 5000,
|
|
52
|
+
optional: true
|
|
53
|
+
});
|
|
54
|
+
const remainingEntries = await waitForSocketEntriesToClear(socketDir, 2000);
|
|
55
|
+
const sessionRemoved = !remainingEntries.includes(sessionName);
|
|
56
|
+
const socketExclusive = remainingEntries.length === 0;
|
|
57
|
+
const layoutPresentBefore = await exists(expectedLayoutPath);
|
|
58
|
+
const layoutSha256Before = layoutPresentBefore ? await sha256File(expectedLayoutPath) : null;
|
|
59
|
+
const layoutHashMatches = !layoutPresentBefore || !ownership.layout_sha256 || layoutSha256Before === ownership.layout_sha256;
|
|
60
|
+
let socketDirRemoved = false;
|
|
61
|
+
let layoutRemoved = false;
|
|
62
|
+
if (sessionRemoved && socketExclusive) {
|
|
63
|
+
await fs.rm(socketDir, { recursive: true, force: true });
|
|
64
|
+
socketDirRemoved = !(await exists(socketDir));
|
|
65
|
+
if (socketDirRemoved && layoutHashMatches) {
|
|
66
|
+
await fs.rm(expectedLayoutPath, { force: true });
|
|
67
|
+
layoutRemoved = !(await exists(expectedLayoutPath));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const blockers = [
|
|
71
|
+
...(!sessionRemoved ? ['zellij_cleanup_session_still_present'] : []),
|
|
72
|
+
...(!socketExclusive ? ['zellij_cleanup_owned_socket_dir_not_empty'] : []),
|
|
73
|
+
...(!socketDirRemoved ? ['zellij_cleanup_socket_dir_not_removed'] : []),
|
|
74
|
+
...(!layoutHashMatches ? ['zellij_cleanup_layout_hash_mismatch'] : []),
|
|
75
|
+
...(!layoutRemoved ? ['zellij_cleanup_layout_not_removed'] : [])
|
|
76
|
+
];
|
|
77
|
+
const report = {
|
|
78
|
+
schema: 'sks.zellij-real-session-cleanup-check.v1',
|
|
79
|
+
ok: blockers.length === 0,
|
|
80
|
+
mutation_attempted: true,
|
|
81
|
+
mission_id: missionId,
|
|
82
|
+
session_name: sessionName,
|
|
83
|
+
socket_dir: socketDir,
|
|
84
|
+
ownership_path: ownershipPath,
|
|
85
|
+
session_present_before: beforeEntries.includes(sessionName),
|
|
86
|
+
session_removed: sessionRemoved,
|
|
87
|
+
socket_dir_exclusive: socketExclusive,
|
|
88
|
+
socket_dir_removed: socketDirRemoved,
|
|
89
|
+
layout_path: expectedLayoutPath,
|
|
90
|
+
layout_sha256: ownership.layout_sha256 || null,
|
|
91
|
+
layout_sha256_before_cleanup: layoutSha256Before,
|
|
92
|
+
layout_hash_matches: layoutHashMatches,
|
|
93
|
+
layout_removed: layoutRemoved,
|
|
94
|
+
remaining_socket_entries: remainingEntries,
|
|
95
|
+
result,
|
|
96
|
+
blockers,
|
|
97
|
+
warnings: result.ok ? [] : ['zellij_kill_session_nonzero_but_absence_verified']
|
|
98
|
+
};
|
|
99
|
+
await fs.writeFile(path.join(root, '.sneakoscope', 'missions', missionId, 'zellij-real-session-cleanup.json'), `${JSON.stringify(report, null, 2)}\n`);
|
|
100
|
+
emit(report);
|
|
101
|
+
}
|
|
14
102
|
function emit(report) { console.log(JSON.stringify(report, null, 2)); if (!report.ok)
|
|
15
103
|
process.exitCode = 1; }
|
|
16
104
|
function fail(blocker, detail) { emit({ schema: 'sks.zellij-real-session-cleanup-check.v1', ok: false, blockers: [blocker], detail }); process.exit(1); }
|
|
@@ -18,4 +106,36 @@ function readArg(args, name) {
|
|
|
18
106
|
const index = args.indexOf(name);
|
|
19
107
|
return index >= 0 ? args[index + 1] || null : null;
|
|
20
108
|
}
|
|
109
|
+
function hashOwnerToken(value) {
|
|
110
|
+
return createHash('sha256').update(String(value)).digest('hex');
|
|
111
|
+
}
|
|
112
|
+
async function sha256File(file) {
|
|
113
|
+
return fs.readFile(file).then((data) => createHash('sha256').update(data).digest('hex')).catch(() => null);
|
|
114
|
+
}
|
|
115
|
+
function isSafeOwnedSocketDir(value) {
|
|
116
|
+
if (!value)
|
|
117
|
+
return false;
|
|
118
|
+
const resolved = path.resolve(String(value));
|
|
119
|
+
return path.dirname(resolved) === '/tmp' && /^sks-zj-rr-[A-Za-z0-9-]+$/.test(path.basename(resolved));
|
|
120
|
+
}
|
|
121
|
+
async function readJson(file) {
|
|
122
|
+
return fs.readFile(file, 'utf8').then((text) => JSON.parse(text)).catch(() => null);
|
|
123
|
+
}
|
|
124
|
+
async function socketEntries(socketDir) {
|
|
125
|
+
if (!socketDir)
|
|
126
|
+
return [];
|
|
127
|
+
return fs.readdir(path.join(socketDir, 'contract_version_1')).catch(() => []);
|
|
128
|
+
}
|
|
129
|
+
async function waitForSocketEntriesToClear(socketDir, timeoutMs) {
|
|
130
|
+
const deadline = Date.now() + timeoutMs;
|
|
131
|
+
for (;;) {
|
|
132
|
+
const entries = await socketEntries(socketDir);
|
|
133
|
+
if (entries.length === 0 || Date.now() >= deadline)
|
|
134
|
+
return entries;
|
|
135
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
async function exists(value) {
|
|
139
|
+
return fs.access(value).then(() => true).catch(() => false);
|
|
140
|
+
}
|
|
21
141
|
//# sourceMappingURL=zellij-real-session-cleanup-check.js.map
|