sneakoscope 2.0.5 → 2.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/README.md +7 -4
  2. package/crates/sks-core/Cargo.lock +1 -1
  3. package/crates/sks-core/Cargo.toml +1 -1
  4. package/crates/sks-core/src/main.rs +1 -1
  5. package/dist/.sks-build-stamp.json +4 -4
  6. package/dist/bin/sks.js +1 -1
  7. package/dist/build-manifest.json +13 -8
  8. package/dist/cli/install-helpers.js +23 -0
  9. package/dist/commands/codex-app.js +25 -3
  10. package/dist/commands/doctor.js +19 -4
  11. package/dist/commands/mad-sks.js +2 -2
  12. package/dist/core/agents/agent-orchestrator.js +22 -3
  13. package/dist/core/agents/agent-proof-evidence.js +24 -2
  14. package/dist/core/agents/agent-worker-pipeline.js +9 -1
  15. package/dist/core/agents/native-worker-backend-router.js +19 -1
  16. package/dist/core/codex-app.js +124 -2
  17. package/dist/core/commands/naruto-command.js +9 -4
  18. package/dist/core/fsx.js +1 -1
  19. package/dist/core/hooks-runtime.js +2 -233
  20. package/dist/core/init.js +8 -8
  21. package/dist/core/naruto/naruto-active-pool.js +20 -4
  22. package/dist/core/pipeline-internals/runtime-core.js +1 -1
  23. package/dist/core/ppt.js +31 -8
  24. package/dist/core/product-design-app-server.js +410 -0
  25. package/dist/core/product-design-plugin.js +139 -0
  26. package/dist/core/routes.js +8 -8
  27. package/dist/core/version.js +1 -1
  28. package/dist/scripts/naruto-active-pool-check.js +13 -1
  29. package/dist/scripts/naruto-readonly-routing-check.js +116 -0
  30. package/dist/scripts/naruto-shadow-clone-swarm-check.js +7 -0
  31. package/dist/scripts/product-design-auto-install-check.js +119 -0
  32. package/dist/scripts/product-design-plugin-routing-check.js +101 -0
  33. package/dist/scripts/release-parallel-check.js +15 -1
  34. package/dist/scripts/release-provenance-check.js +21 -0
  35. package/package.json +5 -2
@@ -0,0 +1,116 @@
1
+ #!/usr/bin/env node
2
+ // @ts-nocheck
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
5
+ import { spawnSync } from 'node:child_process';
6
+ import { assertGate, emitGate, exists, importDist, root } from './sks-1-18-gate-lib.js';
7
+ const worker = await importDist('core/agents/agent-worker-pipeline.js');
8
+ const cli = path.join(root, 'dist', 'bin', 'sks.js');
9
+ assertGate(exists('dist/bin/sks.js'), 'dist/bin/sks.js missing (build first)');
10
+ const readOnlyWorker = worker.validateAgentWorkerResult({
11
+ mission_id: 'M-readonly-routing',
12
+ agent_id: 'readonly-agent',
13
+ session_id: 'readonly-session',
14
+ persona_id: 'verifier',
15
+ task_slice_id: 'readonly-slice',
16
+ status: 'done',
17
+ backend: 'codex-sdk',
18
+ summary: 'Read-only worker inspected files without proposing a patch.',
19
+ findings: ['read-only inspection completed'],
20
+ proposed_changes: [],
21
+ changed_files: ['src/core/agents/agent-proof-evidence.ts'],
22
+ lease_compliance: { ok: true, violations: [] },
23
+ artifacts: [],
24
+ blockers: [],
25
+ confidence: 'fixture',
26
+ handoff_notes: '',
27
+ unverified: [],
28
+ writes: [],
29
+ no_patch_reason: {
30
+ ok: true,
31
+ reason: 'read_only_or_no_write_paths',
32
+ read_only_or_noop_evidence: true
33
+ },
34
+ verification: { status: 'passed', checks: ['readonly-no-patch-routing'] }
35
+ });
36
+ assertGate(readOnlyWorker.status === 'done' && !readOnlyWorker.blockers.includes('no_patch_generated'), 'read-only/no-write worker changed_files must not require patch envelopes', readOnlyWorker);
37
+ const writeWorker = worker.validateAgentWorkerResult({
38
+ ...readOnlyWorker,
39
+ agent_id: 'write-agent',
40
+ session_id: 'write-session',
41
+ task_slice_id: 'write-slice',
42
+ changed_files: ['src/core/agents/agent-proof-evidence.ts'],
43
+ no_patch_reason: undefined
44
+ });
45
+ assertGate(writeWorker.status === 'blocked' && writeWorker.blockers.includes('no_patch_generated'), 'write-capable changed_files without patch envelope must still block', writeWorker);
46
+ const readonlyRun = spawnSync(process.execPath, [
47
+ cli,
48
+ 'naruto',
49
+ 'run',
50
+ 'readonly routing must inspect `src/core/agents/agent-proof-evidence.ts` and `package.json` without writes',
51
+ '--clones',
52
+ '4',
53
+ '--work-items',
54
+ '4',
55
+ '--backend',
56
+ 'fake',
57
+ '--readonly',
58
+ '--json'
59
+ ], { cwd: root, encoding: 'utf8', timeout: 120000, maxBuffer: 6 * 1024 * 1024 });
60
+ const readonlyJson = parseJson(readonlyRun.stdout);
61
+ assertGate(readonlyRun.status === 0 && readonlyJson?.ok === true, 'readonly Naruto fake blackbox must exit ok', { status: readonlyRun.status, stdout: tail(readonlyRun.stdout), stderr: tail(readonlyRun.stderr) });
62
+ assertGate(readonlyJson.proof === 'passed', 'readonly Naruto proof must pass', { proof: readonlyJson.proof, blockers: readonlyJson.run?.proof?.blockers });
63
+ assertGate(readonlyJson.work_graph?.write_allowed_count === 0, 'readonly Naruto work graph must have zero write-allowed items', readonlyJson.work_graph);
64
+ assertGate(Number(readonlyJson.role_distribution?.implementation_like_workers || 0) === 0, 'readonly Naruto role distribution must have zero implementation-like workers', readonlyJson.role_distribution);
65
+ assertGate((readonlyJson.role_distribution?.entries || []).every((entry) => entry.write_allowed === false), 'readonly Naruto role distribution must deny writes for every role', readonlyJson.role_distribution);
66
+ const readonlyRoot = path.join(root, '.sneakoscope', 'missions', readonlyJson.mission_id, 'agents');
67
+ const readonlyProof = readJson(path.join(readonlyRoot, 'agent-proof-evidence.json'));
68
+ const readonlyStrategy = readJson(path.join(readonlyRoot, 'user-request-strategy.json'));
69
+ const readonlyPolicy = readJson(path.join(readonlyRoot, 'agent-parallel-write-policy.json'));
70
+ assertGate(readonlyPolicy.write_mode === 'off' && readonlyPolicy.readonly === true, 'readonly run must force native write policy off', readonlyPolicy);
71
+ assertGate(readonlyStrategy.gate?.write_task_count === 0, 'readonly strategy must not infer write targets from file mentions', readonlyStrategy.gate);
72
+ assertGate(readonlyProof.changed_files_lease_checked === false, 'readonly no-write proof must skip changed_files write-lease checks', readonlyProof);
73
+ assertGate(!(readonlyProof.blockers || []).some((blocker) => /no_patch_generated|lease_changed_file_violation/.test(String(blocker))), 'readonly proof must not contain patch/lease write blockers', readonlyProof.blockers || []);
74
+ const writeRun = spawnSync(process.execPath, [
75
+ cli,
76
+ 'naruto',
77
+ 'run',
78
+ 'write-capable routing must patch `README.md` through leased envelopes',
79
+ '--clones',
80
+ '3',
81
+ '--work-items',
82
+ '3',
83
+ '--backend',
84
+ 'fake',
85
+ '--parallel-write',
86
+ '--json'
87
+ ], { cwd: root, encoding: 'utf8', timeout: 120000, maxBuffer: 6 * 1024 * 1024 });
88
+ const writeJson = parseJson(writeRun.stdout);
89
+ assertGate(writeRun.status === 0 && writeJson?.ok === true, 'write-capable Naruto fake blackbox must exit ok', { status: writeRun.status, stdout: tail(writeRun.stdout), stderr: tail(writeRun.stderr) });
90
+ const writeRoot = path.join(root, '.sneakoscope', 'missions', writeJson.mission_id, 'agents');
91
+ const writeStrategy = readJson(path.join(writeRoot, 'user-request-strategy.json'));
92
+ const writePolicy = readJson(path.join(writeRoot, 'agent-parallel-write-policy.json'));
93
+ assertGate(writePolicy.write_mode === 'parallel' && writePolicy.readonly === false, 'write-capable Naruto run must carry parallel write policy', writePolicy);
94
+ assertGate(writeStrategy.gate?.write_task_count >= 1, 'write-capable strategy must retain explicit write target inference', writeStrategy.gate);
95
+ emitGate('naruto:readonly-routing', {
96
+ readonly_mission_id: readonlyJson.mission_id,
97
+ write_mission_id: writeJson.mission_id,
98
+ readonly_write_tasks: readonlyStrategy.gate?.write_task_count,
99
+ write_write_tasks: writeStrategy.gate?.write_task_count
100
+ });
101
+ function readJson(file) {
102
+ return JSON.parse(fs.readFileSync(file, 'utf8'));
103
+ }
104
+ function parseJson(text) {
105
+ try {
106
+ return JSON.parse(text);
107
+ }
108
+ catch {
109
+ return null;
110
+ }
111
+ }
112
+ function tail(value, limit = 2000) {
113
+ const text = String(value || '');
114
+ return text.length <= limit ? text : text.slice(-limit);
115
+ }
116
+ //# sourceMappingURL=naruto-readonly-routing-check.js.map
@@ -5,6 +5,7 @@
5
5
  // changing it for any other route, and that an end-to-end `sks naruto run` actually
6
6
  // schedules >20 concurrent clone sessions to completion with proof.
7
7
  import { spawnSync } from 'node:child_process';
8
+ import fs from 'node:fs';
8
9
  import path from 'node:path';
9
10
  import { assertGate, emitGate, importDist, root, exists } from './sks-1-18-gate-lib.js';
10
11
  const schema = await importDist('core/agents/agent-schema.js');
@@ -98,8 +99,14 @@ assertGate(typeof parsed.concurrency_capped === 'boolean', 'naruto run must repo
98
99
  assertGate(parsed.concurrency_capped === (parsed.clones > parsed.target_active_slots), 'concurrency_capped must reflect clones > live slots', { clones: parsed.clones, target_active_slots: parsed.target_active_slots, concurrency_capped: parsed.concurrency_capped });
99
100
  assertGate(parsed.system && Number(parsed.system.safe_concurrency) >= 1, 'naruto run must report system safe_concurrency (host-derived cap)', { system: parsed.system });
100
101
  assertGate(parsed.work_graph?.write_allowed_count > 0 && parsed.work_graph?.mixed_work_kinds?.length > 1, 'naruto run must report a mixed work graph with write-capable items', { work_graph: parsed.work_graph });
102
+ assertGate(Number(parsed.work_graph?.parallel_write_wave_count || 0) > 0, 'naruto run must expose at least one parallel write-capable wave with non-overlapping leases', { work_graph: parsed.work_graph });
101
103
  assertGate(parsed.role_distribution?.verifier_only === false, 'naruto run proof/status must distinguish active worker roles beyond verifier-only', { role_distribution: parsed.role_distribution });
102
104
  assertGate(Number(parsed.role_distribution?.implementation_like_ratio || 0) >= 0.4, 'naruto run must include implementation-like role distribution', { role_distribution: parsed.role_distribution });
105
+ const commandGraphPath = path.join(root, '.sneakoscope', 'missions', parsed.mission_id, 'agents', 'naruto-work-graph.json');
106
+ const commandGraph = JSON.parse(fs.readFileSync(commandGraphPath, 'utf8'));
107
+ const writePaths = commandGraph.work_items.filter((row) => row.write_allowed).flatMap((row) => row.write_paths);
108
+ assertGate(new Set(writePaths).size > 1, 'naruto command default patch-envelope leases must be per work item, not one shared write path', { sample: writePaths.slice(0, 8), unique: new Set(writePaths).size });
109
+ assertGate(commandGraph.active_waves.some((wave) => wave.write_paths.length > 1), 'naruto command graph must contain a parallel write wave when route-local patch envelopes do not overlap', { waves: commandGraph.active_waves.slice(0, 3) });
103
110
  const state = parsed.run?.scheduler?.state || parsed.run?.scheduler || {};
104
111
  assertGate(Number(state.completed_count) === proofClones, 'all clone work items must complete despite throttling', { completed_count: state.completed_count });
105
112
  const explicitConcurrency = spawnSync(process.execPath, [cli, 'naruto', 'run', 'explicit concurrency', '--clones', '6', '--backend', 'fake', '--work-items', '6', '--concurrency', '6', '--json'], { cwd: root, encoding: 'utf8', timeout: 120000, maxBuffer: 4 * 1024 * 1024 });
@@ -0,0 +1,119 @@
1
+ #!/usr/bin/env node
2
+ // @ts-nocheck
3
+ import { ensureProductDesignPluginInstalledWithRequest, findProductDesignPluginSummaryFromMarketplaces, productDesignAutoInstallRequested } from '../core/product-design-app-server.js';
4
+ import { PRODUCT_DESIGN_PLUGIN, PRODUCT_DESIGN_REQUIRED_SKILLS } from '../core/product-design-plugin.js';
5
+ import { assertGate, emitGate, readText } from './lib/codex-sdk-gate-lib.js';
6
+ function pluginReadResponse({ installed, enabled }) {
7
+ return {
8
+ plugin: {
9
+ marketplaceName: PRODUCT_DESIGN_PLUGIN.marketplace,
10
+ marketplacePath: null,
11
+ summary: {
12
+ id: PRODUCT_DESIGN_PLUGIN.id,
13
+ remotePluginId: PRODUCT_DESIGN_PLUGIN.remote_plugin_id,
14
+ name: PRODUCT_DESIGN_PLUGIN.name,
15
+ installed,
16
+ enabled,
17
+ interface: {
18
+ displayName: PRODUCT_DESIGN_PLUGIN.display_name
19
+ }
20
+ },
21
+ skills: PRODUCT_DESIGN_REQUIRED_SKILLS.map((name) => ({ name, enabled: true }))
22
+ }
23
+ };
24
+ }
25
+ let installed = false;
26
+ const installCalls = [];
27
+ const installResult = await ensureProductDesignPluginInstalledWithRequest(async (method, params) => {
28
+ installCalls.push({ method, params });
29
+ if (method === 'plugin/read')
30
+ return pluginReadResponse({ installed, enabled: installed });
31
+ if (method === 'plugin/install') {
32
+ assertGate(params.pluginName === PRODUCT_DESIGN_PLUGIN.remote_plugin_id, 'plugin/install must use Product Design remote plugin id', params);
33
+ installed = true;
34
+ return { authPolicy: 'ON_USE', appsNeedingAuth: [] };
35
+ }
36
+ if (method === 'plugin/installed')
37
+ return { marketplaces: [], marketplaceLoadErrors: [] };
38
+ throw new Error(`unexpected method: ${method}`);
39
+ }, { autoInstallProductDesign: true, env: {} });
40
+ assertGate(installResult.ok, 'Product Design ensure must pass after fake plugin/install', installResult);
41
+ assertGate(installResult.install_attempted === true, 'Product Design ensure must attempt install when read evidence is not ready', installResult);
42
+ assertGate(installCalls.some((call) => call.method === 'plugin/install'), 'Product Design ensure did not call plugin/install', installCalls);
43
+ assertGate(installResult.after_evidence.ok, 'Product Design after_evidence must be ready after install', installResult);
44
+ installed = false;
45
+ const dryCalls = [];
46
+ const dryResult = await ensureProductDesignPluginInstalledWithRequest(async (method, params) => {
47
+ dryCalls.push({ method, params });
48
+ if (method === 'plugin/read')
49
+ return pluginReadResponse({ installed: false, enabled: false });
50
+ throw new Error(`unexpected dry method: ${method}`);
51
+ }, { autoInstallProductDesign: false, env: {} });
52
+ assertGate(!dryResult.ok, 'Product Design dry ensure must not claim ready when read evidence is not ready', dryResult);
53
+ assertGate(dryResult.install_attempted === false, 'Product Design dry ensure must not attempt install', dryResult);
54
+ assertGate(!dryCalls.some((call) => call.method === 'plugin/install'), 'Product Design dry ensure must not call plugin/install', dryCalls);
55
+ const marketplaceList = {
56
+ marketplaces: [{
57
+ name: PRODUCT_DESIGN_PLUGIN.marketplace,
58
+ plugins: [{
59
+ id: PRODUCT_DESIGN_PLUGIN.id,
60
+ remotePluginId: PRODUCT_DESIGN_PLUGIN.remote_plugin_id,
61
+ name: PRODUCT_DESIGN_PLUGIN.name,
62
+ installed: true,
63
+ enabled: true,
64
+ interface: {
65
+ displayName: PRODUCT_DESIGN_PLUGIN.display_name
66
+ }
67
+ }]
68
+ }],
69
+ marketplaceLoadErrors: []
70
+ };
71
+ const discovered = findProductDesignPluginSummaryFromMarketplaces(marketplaceList);
72
+ assertGate(discovered?.remotePluginId === PRODUCT_DESIGN_PLUGIN.remote_plugin_id, 'Product Design vertical plugin/list discovery must return remote id', discovered);
73
+ let readCount = 0;
74
+ const listCalls = [];
75
+ const listFallbackResult = await ensureProductDesignPluginInstalledWithRequest(async (method, params) => {
76
+ listCalls.push({ method, params });
77
+ if (method === 'plugin/read') {
78
+ readCount += 1;
79
+ if (readCount === 1)
80
+ throw new Error('simulated stale read id');
81
+ return pluginReadResponse({ installed: true, enabled: true });
82
+ }
83
+ if (method === 'plugin/list')
84
+ return marketplaceList;
85
+ throw new Error(`unexpected list fallback method: ${method}`);
86
+ }, { autoInstallProductDesign: true, env: {} });
87
+ assertGate(listFallbackResult.ok, 'Product Design ensure must recover through vertical plugin/list discovery', listFallbackResult);
88
+ assertGate(listFallbackResult.install_attempted === false, 'Product Design ensure must not install when list-discovered read is already ready', listFallbackResult);
89
+ assertGate(listCalls.some((call) => call.method === 'plugin/list'), 'Product Design ensure must query vertical plugin/list when direct read fails', listCalls);
90
+ assertGate(productDesignAutoInstallRequested({ env: { SKS_PRODUCT_DESIGN_AUTO_INSTALL: '1' } }), 'Product Design auto-install env gate must be honored');
91
+ const codexAppSource = readText('src/core/codex-app.ts');
92
+ const commandSource = readText('src/commands/codex-app.ts');
93
+ const appServerSource = readText('src/core/product-design-app-server.ts');
94
+ const pkg = JSON.parse(readText('package.json'));
95
+ const releaseCheck = String(pkg.scripts?.['release:check'] || '');
96
+ for (const token of [
97
+ 'ensureProductDesignPluginInstalled',
98
+ 'PRODUCT_DESIGN_AUTO_INSTALL_ENV',
99
+ 'autoInstallProductDesign'
100
+ ]) {
101
+ assertGate(codexAppSource.includes(token) || appServerSource.includes(token), `Product Design auto-install source missing token: ${token}`);
102
+ }
103
+ for (const token of [
104
+ 'product-design',
105
+ 'ensure-product-design',
106
+ '--check-only',
107
+ '--install-product-design'
108
+ ]) {
109
+ assertGate(commandSource.includes(token), `sks codex-app command missing Product Design token: ${token}`);
110
+ }
111
+ assertGate(Boolean(pkg.scripts?.['codex:product-design-auto-install']), 'package script missing codex:product-design-auto-install');
112
+ assertGate(releaseCheck.includes('codex:product-design-auto-install'), 'release:check must include Product Design auto-install gate');
113
+ emitGate('codex:product-design-auto-install', {
114
+ install_calls: installCalls.map((call) => call.method),
115
+ dry_calls: dryCalls.map((call) => call.method),
116
+ list_fallback_calls: listCalls.map((call) => call.method),
117
+ env_gate: true
118
+ });
119
+ //# sourceMappingURL=product-design-auto-install-check.js.map
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/env node
2
+ // @ts-nocheck
3
+ import { PRODUCT_DESIGN_PIPELINE_STAGES, PRODUCT_DESIGN_PLUGIN, PRODUCT_DESIGN_REQUIRED_SKILLS, normalizeProductDesignPluginEvidence, productDesignPluginVisibilityFromCodexPluginList } from '../core/product-design-plugin.js';
4
+ import { assertGate, emitGate, readText } from './lib/codex-sdk-gate-lib.js';
5
+ const routesSource = readText('src/core/routes.ts');
6
+ const productDesignSource = readText('src/core/product-design-plugin.ts');
7
+ const runtimeSource = readText('src/core/pipeline-internals/runtime-core.ts');
8
+ const pptSource = readText('src/core/ppt.ts');
9
+ const codexAppSource = readText('src/core/codex-app.ts');
10
+ const initSource = readText('src/core/init.ts');
11
+ const pkg = JSON.parse(readText('package.json'));
12
+ const releaseCheck = String(pkg.scripts?.['release:check'] || '');
13
+ assertGate(PRODUCT_DESIGN_PLUGIN.id === 'product-design@openai-curated-remote', 'Product Design plugin id must use the remote marketplace');
14
+ assertGate(PRODUCT_DESIGN_PLUGIN.marketplace === 'openai-curated-remote', 'Product Design marketplace must be openai-curated-remote');
15
+ assertGate(PRODUCT_DESIGN_PLUGIN.marketplace_kind === 'vertical', 'Product Design marketplace kind must be vertical');
16
+ assertGate(PRODUCT_DESIGN_PLUGIN.remote_plugin_id === 'Plugin_fa77aec24fc08191bc6e57f377126d76', 'Product Design remote plugin id mismatch');
17
+ assertGate(PRODUCT_DESIGN_PLUGIN.app_server.read_params.remoteMarketplaceName === 'openai-curated-remote', 'plugin/read remote marketplace missing');
18
+ assertGate(PRODUCT_DESIGN_PLUGIN.app_server.install_params.remoteMarketplaceName === 'openai-curated-remote', 'plugin/install remote marketplace missing');
19
+ assertGate(PRODUCT_DESIGN_PLUGIN.app_server.read_params.pluginName === PRODUCT_DESIGN_PLUGIN.remote_plugin_id, 'plugin/read must use Product Design remote plugin id');
20
+ assertGate(PRODUCT_DESIGN_PLUGIN.app_server.install_params.pluginName === PRODUCT_DESIGN_PLUGIN.remote_plugin_id, 'plugin/install must use Product Design remote plugin id');
21
+ assertGate(PRODUCT_DESIGN_PLUGIN.app_server.list_params.marketplaceKinds.includes('vertical'), 'plugin/list must query vertical marketplaces');
22
+ for (const skill of ['audit', 'design-qa', 'get-context', 'ideate', 'image-to-code', 'prototype', 'research', 'share', 'url-to-code', 'user-context']) {
23
+ assertGate(PRODUCT_DESIGN_REQUIRED_SKILLS.includes(skill), `Product Design required skill missing: ${skill}`);
24
+ }
25
+ assertGate(PRODUCT_DESIGN_PIPELINE_STAGES.length >= 5, 'Product Design pipeline stage map too small');
26
+ const fakeReadResponse = {
27
+ plugin: {
28
+ marketplaceName: PRODUCT_DESIGN_PLUGIN.marketplace,
29
+ summary: {
30
+ id: PRODUCT_DESIGN_PLUGIN.id,
31
+ remotePluginId: PRODUCT_DESIGN_PLUGIN.remote_plugin_id,
32
+ name: PRODUCT_DESIGN_PLUGIN.name,
33
+ installed: true,
34
+ enabled: true
35
+ },
36
+ skills: PRODUCT_DESIGN_REQUIRED_SKILLS.map((name) => ({ name, enabled: true }))
37
+ }
38
+ };
39
+ const evidence = normalizeProductDesignPluginEvidence(fakeReadResponse);
40
+ assertGate(evidence.ok, 'app-server plugin/read evidence parser must accept ready Product Design response', evidence);
41
+ const hiddenFromLocalList = productDesignPluginVisibilityFromCodexPluginList({ installed: [{ id: 'browser@openai-bundled' }] });
42
+ assertGate(hiddenFromLocalList.requires_remote_vertical_lookup, 'missing local plugin-list entry must require remote vertical lookup');
43
+ for (const token of [
44
+ 'productDesignPluginPolicyText',
45
+ 'Product Design plugin tools are allowed and preferred',
46
+ 'project-local cache/compatibility authority',
47
+ 'PRODUCT_DESIGN_PLUGIN_TOOL_ALLOWLIST'
48
+ ]) {
49
+ assertGate(routesSource.includes(token), `routes.ts missing Product Design routing token: ${token}`);
50
+ }
51
+ const recommendedSkillsBlock = routesSource.match(/export const RECOMMENDED_SKILLS = \[([\s\S]*?)\];/)?.[1] || '';
52
+ for (const legacySkill of ['design-artifact-expert', 'design-system-builder', 'design-ui-editor']) {
53
+ assertGate(!recommendedSkillsBlock.includes(legacySkill), `legacy design skill should not stay in RECOMMENDED_SKILLS: ${legacySkill}`);
54
+ }
55
+ for (const token of [
56
+ 'Product Design plugin policy',
57
+ 'openai-curated-remote',
58
+ 'plugin/read',
59
+ 'plugin/install',
60
+ 'auto-install/ensure',
61
+ 'vertical',
62
+ 'compatibility fallback only',
63
+ 'PRODUCT_DESIGN_LEGACY_DESIGN_FALLBACK_SKILLS'
64
+ ]) {
65
+ assertGate(productDesignSource.includes(token), `product-design-plugin.ts missing policy token: ${token}`);
66
+ }
67
+ for (const token of [
68
+ 'Product Design plugin first',
69
+ 'design-system-builder',
70
+ 'design-ui-editor',
71
+ 'design-artifact-expert'
72
+ ]) {
73
+ assertGate(runtimeSource.includes(token) || initSource.includes(token), `runtime/init missing fallback token: ${token}`);
74
+ }
75
+ for (const token of [
76
+ 'product_design_plugin',
77
+ 'primary_design_plugin',
78
+ 'legacy_design_skills_fallback_only',
79
+ 'remote_plugin_id'
80
+ ]) {
81
+ assertGate(pptSource.includes(token), `ppt.ts missing Product Design evidence token: ${token}`);
82
+ }
83
+ for (const token of [
84
+ 'codexProductDesignPluginStatus',
85
+ 'design_product',
86
+ 'ensureProductDesignPluginInstalled',
87
+ 'product_design_remote_vertical_lookup_required',
88
+ 'remote vertical marketplace plugin'
89
+ ]) {
90
+ assertGate(codexAppSource.includes(token), `codex-app.ts missing Product Design readiness token: ${token}`);
91
+ }
92
+ assertGate(Boolean(pkg.scripts?.['codex:product-design-plugin-routing']), 'package script missing codex:product-design-plugin-routing');
93
+ assertGate(releaseCheck.includes('codex:product-design-plugin-routing'), 'release:check must include Product Design routing gate');
94
+ emitGate('codex:product-design-plugin-routing', {
95
+ plugin_id: PRODUCT_DESIGN_PLUGIN.id,
96
+ remote_plugin_id: PRODUCT_DESIGN_PLUGIN.remote_plugin_id,
97
+ required_skills: PRODUCT_DESIGN_REQUIRED_SKILLS.length,
98
+ stages: PRODUCT_DESIGN_PIPELINE_STAGES.length,
99
+ local_list_hidden_requires_remote_lookup: hiddenFromLocalList.requires_remote_vertical_lookup
100
+ });
101
+ //# sourceMappingURL=product-design-plugin-routing-check.js.map
@@ -304,8 +304,22 @@ if (result.ok) {
304
304
  };
305
305
  await writeParallelVerificationProof(reportDir, result);
306
306
  }
307
- console.log(JSON.stringify(result, null, 2));
307
+ console.log(JSON.stringify(releaseParallelStdoutSummary(result), null, 2));
308
308
  process.exit(result.ok ? 0 : 1);
309
+ function releaseParallelStdoutSummary(result) {
310
+ return {
311
+ schema: 'sks.release-parallel-check.stdout-summary.v1',
312
+ ok: result.ok,
313
+ tasks: result.task_count,
314
+ passed: result.passed,
315
+ failed: result.failed,
316
+ skipped: result.skipped,
317
+ dependency_count: result.dependency_count,
318
+ report_json: '.sneakoscope/reports/release-parallel-report.json',
319
+ report_md: '.sneakoscope/reports/release-parallel-report.md',
320
+ retention_cleanup: result.retention_cleanup ?? null
321
+ };
322
+ }
309
323
  function summarizeReleaseLogsForCleanup(result, logDir) {
310
324
  const prefix = `${path.resolve(logDir)}${path.sep}`;
311
325
  for (const row of result.results) {
@@ -17,6 +17,7 @@ const cargoVersion = readVersionFrom('crates/sks-core/Cargo.toml', /^version\s*=
17
17
  const latestChangelog = latestVersionedChangelogSection(readText('CHANGELOG.md'));
18
18
  const tag = tagStatus(version, currentCommit);
19
19
  const main = mainVersion();
20
+ const originMain = originMainVersion();
20
21
  const npm = npmVersion();
21
22
  const warnings = [];
22
23
  const blockers = [];
@@ -24,6 +25,8 @@ if (main.version && main.version !== version)
24
25
  warnings.push('main_out_of_date');
25
26
  if (publish && main.version && main.version !== version)
26
27
  blockers.push('main_version_mismatch');
28
+ if (originMain.version && originMain.version !== version)
29
+ warnings.push('origin_main_out_of_date');
27
30
  if (publish && tag.exists && tag.commit !== currentCommit)
28
31
  blockers.push('tag_not_on_current_commit');
29
32
  if (publish && npm.version && semverCompare(npm.version, version) >= 0)
@@ -46,6 +49,10 @@ const report = {
46
49
  latest_changelog_section: latestChangelog,
47
50
  main_version: main.version,
48
51
  main_commit: main.commit,
52
+ main_status: main.status,
53
+ origin_main_version: originMain.version,
54
+ origin_main_commit: originMain.commit,
55
+ origin_main_status: originMain.status,
49
56
  npm_version: npm.version,
50
57
  npm_status: npm.version ? (semverCompare(npm.version, version) < 0 ? 'registry_behind_candidate' : npm.version === version ? 'candidate_already_published' : 'registry_ahead') : npm.status,
51
58
  tag_status: tag,
@@ -63,6 +70,20 @@ function git(argv) {
63
70
  return res.status === 0 ? res.stdout.trim() : null;
64
71
  }
65
72
  function mainVersion() {
73
+ const ref = git(['rev-parse', '--verify', 'HEAD']);
74
+ if (!ref)
75
+ return { version: null, commit: null, status: 'unavailable' };
76
+ const res = spawnSync('git', ['show', 'HEAD:package.json'], { cwd: root, encoding: 'utf8' });
77
+ if (res.status !== 0)
78
+ return { version: null, commit: ref, status: 'package_unavailable' };
79
+ try {
80
+ return { version: JSON.parse(res.stdout).version || null, commit: ref, status: 'local_head' };
81
+ }
82
+ catch {
83
+ return { version: null, commit: ref, status: 'unparseable' };
84
+ }
85
+ }
86
+ function originMainVersion() {
66
87
  const ref = git(['rev-parse', '--verify', 'origin/main']);
67
88
  if (!ref)
68
89
  return { version: null, commit: null, status: 'unavailable' };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sneakoscope",
3
3
  "displayName": "ㅅㅋㅅ",
4
- "version": "2.0.5",
4
+ "version": "2.0.6",
5
5
  "description": "Sneakoscope Codex: fast proof-first Codex trust layer with image-based Voxel TriWiki.",
6
6
  "type": "module",
7
7
  "homepage": "https://github.com/mandarange/Sneakoscope-Codex#readme",
@@ -305,12 +305,14 @@
305
305
  "codex:0.137-compat": "node ./dist/scripts/codex-0-137-compat-check.js",
306
306
  "codex:0.137-compat:require-real": "node ./dist/scripts/codex-0-137-compat-check.js --require-real",
307
307
  "codex:plugin-list-json": "node ./dist/scripts/codex-plugin-list-json-check.js",
308
+ "codex:product-design-plugin-routing": "node ./dist/scripts/product-design-plugin-routing-check.js",
309
+ "codex:product-design-auto-install": "node ./dist/scripts/product-design-auto-install-check.js",
308
310
  "codex:thread-runtime-choice": "node ./dist/scripts/codex-thread-runtime-choice-check.js",
309
311
  "codex:environment-scoped-approvals": "node ./dist/scripts/codex-environment-scoped-approvals-check.js",
310
312
  "ultra-router:classification": "node ./dist/scripts/ultra-router-classification-check.js",
311
313
  "ultra-router:auto-router": "node ./dist/scripts/ultra-router-auto-router-check.js",
312
314
  "coverage": "node --experimental-test-coverage --test \"test/**/*.test.mjs\"",
313
- "release:check": "npm run release:check:parallel && npm run mad-sks:app-ui-no-mutation && npm run codex-app:fast-ui-preservation && npm run codex-app:ui-clobber-guard && npm run doctor:fixes-codex-app-fast-ui && npm run provider:badge-context && npm run provider:context-config-toml && npm run codex-app:provider-badge && npm run zellij:spawn-on-demand-layout && npm run zellij:worker-pane-manager && npm run zellij:worker-pane-manager-single-owner && npm run agent:worker-pane-communication-contract && npm run runtime:no-mjs-scripts && npm run runtime:ts-python-boundary && npm run codex-sdk:capability && npm run codex-sdk:no-legacy-fallback && npm run codex-sdk:backend-router && npm run codex-sdk:structured-output && npm run codex-sdk:event-stream-ledger && npm run codex-sdk:thread-registry && npm run codex-sdk:sandbox-policy && npm run codex-sdk:zellij-pane-binding && npm run codex-sdk:all-pipelines && npm run codex-sdk:dfix-pipeline && npm run codex-sdk:qa-pipeline && npm run codex-sdk:research-pipeline && npm run codex-sdk:team-naruto-agent-pipeline && npm run codex-sdk:release-review-pipeline && npm run codex-sdk:ux-ppt-review-pipeline && npm run codex-sdk:core-skill-pipeline && npm run codex-control:capability && npm run codex-control:no-legacy-fallback && npm run codex-control:structured-output && npm run codex-control:event-stream-ledger && npm run codex-control:thread-registry && npm run codex-control:side-effect-scope && npm run codex-control:all-pipelines && npm run codex-control:empty-result-retry && npm run codex-control:stream-idle-watchdog && npm run codex-control:tool-call-sequence-repair && npm run codex-control:keepalive-no-cot-leak && npm run local-collab:policy && npm run local-collab:gpt-final-arbiter && npm run local-collab:no-local-only-final && npm run local-collab:gpt-final-availability && npm run local-llm:capability && npm run local-llm:structured-output && npm run local-llm:tool-call-repair && npm run local-llm:all-pipelines && npm run local-collab:all-pipelines-final-gpt && npm run python-sdk:capability && npm run python-sdk:stream-bridge && npm run python-sdk:sandbox-policy && npm run python-sdk:all-pipelines && npm run codex:plugin-list-json && npm run codex:thread-runtime-choice && npm run codex:environment-scoped-approvals && npm run ultra-router:classification && npm run ultra-router:auto-router && npm run release:version-truth && npm run codex:0.137-compat && npm run codex:0.136-compat && npm run codex:0.135-compat && npm run doctor:codex-doctor-parity && npm run codex:permission-profiles && npm run codex:legacy-profile-consumers-removed && npm run terminal:keyboard-enhancement-safety && npm run terminal:tui-output-stability && npm run codex:resume-cwd-truth && npm run mcp:tool-naming-parity && npm run responses:retry-policy-centralized && npm run runtime:no-tmux && npm run zellij:layout-valid && npm run agent:zellij-dynamic-backfill-panes && npm run agent:worker-pane-communication-contract && npm run agent:slot-pane-binding-proof && npm run zellij:worker-pane-manager && npm run zellij:spawn-on-demand-layout && npm run zellij:lane-renderer && npm run mad-sks:zellij-launch && npm run mad-sks:zellij-default-pane-worker && npm run agent:zellij-runtime && npm run codex:config-eperm-fixture && npm run doctor:fix-proves-codex-read && npm run mad:preflight-blocks-unreadable-config && npm run fast:codex-service-tier-proof && npm run codex:project-config-policy-splitter && npm run test:no-orphan-dist-imports && npm run agent:patch-envelope-extraction && npm run agent:patch-queue-runtime && npm run agent:strategy-to-lease-wiring && npm run agent:patch-swarm-runtime && npm run agent:patch-transaction-journal && npm run agent:patch-conflict-rebase && npm run agent:strategy-to-patch-strict && npm run agent:patch-swarm-runtime-truth && npm run agent:rollback-command && npm run agent:patch-verification-dag && npm run agent:patch-rollback-dag && npm run agent:patch-proof-runtime && npm run agent:patch-swarm-route-blackbox && npm run team:patch-swarm-route-blackbox && npm run dfix:patch-swarm-route-blackbox && npm run appshots:thread-attachment-discovery && npm run mcp:readonly-runtime-scheduler && npm run naruto:work-graph && npm run naruto:concurrency-governor && npm run naruto:active-pool && npm run naruto:role-distribution && npm run naruto:parallel-patch-apply && npm run naruto:verification-pool && npm run naruto:zellij-massive-ui && npm run naruto:gpt-final-pack && npm run prompt:placeholder-guard && npm run codex:0.134-runner-truth && npm run agent:native-cli-session-swarm && npm run naruto:shadow-clone-swarm && npm run agent:native-cli-session-swarm-10 && npm run agent:native-cli-session-swarm-20 && npm run agent:no-subagent-scaling && npm run agent:native-cli-session-proof && npm run agent:worker-backend-router && npm run agent:codex-child-overlap && npm run agent:model-authored-patch-envelope && npm run agent:fast-mode-default && npm run agent:fast-mode-worker-propagation && npm run codex:fast-mode-profile-propagation && npm run mad-sks:fast-mode-propagation && npm run zellij:launch-command-truth && npm run zellij:real-session-heartbeat && npm run zellij:ui-design && npm run zellij:doctor-readiness && npm run legacy:upgrade-zero-break && npm run publish:packlist-performance && npm run postinstall:safe-side-effects && npm run runtime:ts-rust-boundary && npm run core-skill:card-schema && npm run core-skill:rollout-scoring && npm run core-skill:patch && npm run core-skill:heldout-validation && npm run core-skill:deployment-snapshot && npm run core-skill:no-inference-optimizer && npm run core-skill:route-runtime-integration && npm run core-skill:promotion-side-effect-ledger && npm run core-skill:legacy-promotion-api-audit && npm run safety:side-effect-zero && npm run safety:mutation-callsite-coverage && npm run safety:mutation-callsite-coverage:repo-wide && npm run side-effect:runtime-report && npm run release:gate-planner && npm run release:dynamic-performance && npm run release:provenance && npm run release:gate-budget && npm run agent:wiki-context-proof && npm run shared-memory:check && npm run wrongness:check && npm run wrongness:fixtures && npm run trust:check && npm run git-collaboration:e2e && node ./dist/scripts/release-check-stamp.js write && npm run release:readiness --silent && node ./dist/scripts/release-check-stamp.js write",
315
+ "release:check": "npm run release:check:parallel && npm run mad-sks:app-ui-no-mutation && npm run codex-app:fast-ui-preservation && npm run codex-app:ui-clobber-guard && npm run doctor:fixes-codex-app-fast-ui && npm run provider:badge-context && npm run provider:context-config-toml && npm run codex-app:provider-badge && npm run zellij:spawn-on-demand-layout && npm run zellij:worker-pane-manager && npm run zellij:worker-pane-manager-single-owner && npm run agent:worker-pane-communication-contract && npm run runtime:no-mjs-scripts && npm run runtime:ts-python-boundary && npm run codex-sdk:capability && npm run codex-sdk:no-legacy-fallback && npm run codex-sdk:backend-router && npm run codex-sdk:structured-output && npm run codex-sdk:event-stream-ledger && npm run codex-sdk:thread-registry && npm run codex-sdk:sandbox-policy && npm run codex-sdk:zellij-pane-binding && npm run codex-sdk:all-pipelines && npm run codex-sdk:dfix-pipeline && npm run codex-sdk:qa-pipeline && npm run codex-sdk:research-pipeline && npm run codex-sdk:team-naruto-agent-pipeline && npm run codex-sdk:release-review-pipeline && npm run codex-sdk:ux-ppt-review-pipeline && npm run codex-sdk:core-skill-pipeline && npm run codex-control:capability && npm run codex-control:no-legacy-fallback && npm run codex-control:structured-output && npm run codex-control:event-stream-ledger && npm run codex-control:thread-registry && npm run codex-control:side-effect-scope && npm run codex-control:all-pipelines && npm run codex-control:empty-result-retry && npm run codex-control:stream-idle-watchdog && npm run codex-control:tool-call-sequence-repair && npm run codex-control:keepalive-no-cot-leak && npm run local-collab:policy && npm run local-collab:gpt-final-arbiter && npm run local-collab:no-local-only-final && npm run local-collab:gpt-final-availability && npm run local-llm:capability && npm run local-llm:structured-output && npm run local-llm:tool-call-repair && npm run local-llm:all-pipelines && npm run local-collab:all-pipelines-final-gpt && npm run python-sdk:capability && npm run python-sdk:stream-bridge && npm run python-sdk:sandbox-policy && npm run python-sdk:all-pipelines && npm run codex:plugin-list-json && npm run codex:product-design-plugin-routing && npm run codex:product-design-auto-install && npm run codex:thread-runtime-choice && npm run codex:environment-scoped-approvals && npm run ultra-router:classification && npm run ultra-router:auto-router && npm run release:version-truth && npm run codex:0.137-compat && npm run codex:0.136-compat && npm run codex:0.135-compat && npm run doctor:codex-doctor-parity && npm run codex:permission-profiles && npm run codex:legacy-profile-consumers-removed && npm run terminal:keyboard-enhancement-safety && npm run terminal:tui-output-stability && npm run codex:resume-cwd-truth && npm run mcp:tool-naming-parity && npm run responses:retry-policy-centralized && npm run runtime:no-tmux && npm run zellij:layout-valid && npm run agent:zellij-dynamic-backfill-panes && npm run agent:worker-pane-communication-contract && npm run agent:slot-pane-binding-proof && npm run zellij:worker-pane-manager && npm run zellij:spawn-on-demand-layout && npm run zellij:lane-renderer && npm run mad-sks:zellij-launch && npm run mad-sks:zellij-default-pane-worker && npm run agent:zellij-runtime && npm run codex:config-eperm-fixture && npm run doctor:fix-proves-codex-read && npm run mad:preflight-blocks-unreadable-config && npm run fast:codex-service-tier-proof && npm run codex:project-config-policy-splitter && npm run test:no-orphan-dist-imports && npm run agent:patch-envelope-extraction && npm run agent:patch-queue-runtime && npm run agent:strategy-to-lease-wiring && npm run agent:patch-swarm-runtime && npm run agent:patch-transaction-journal && npm run agent:patch-conflict-rebase && npm run agent:strategy-to-patch-strict && npm run agent:patch-swarm-runtime-truth && npm run agent:rollback-command && npm run agent:patch-verification-dag && npm run agent:patch-rollback-dag && npm run agent:patch-proof-runtime && npm run agent:patch-swarm-route-blackbox && npm run team:patch-swarm-route-blackbox && npm run dfix:patch-swarm-route-blackbox && npm run appshots:thread-attachment-discovery && npm run mcp:readonly-runtime-scheduler && npm run naruto:work-graph && npm run naruto:readonly-routing && npm run naruto:concurrency-governor && npm run naruto:active-pool && npm run naruto:role-distribution && npm run naruto:parallel-patch-apply && npm run naruto:verification-pool && npm run naruto:zellij-massive-ui && npm run naruto:gpt-final-pack && npm run prompt:placeholder-guard && npm run codex:0.134-runner-truth && npm run agent:native-cli-session-swarm && npm run naruto:shadow-clone-swarm && npm run agent:native-cli-session-swarm-10 && npm run agent:native-cli-session-swarm-20 && npm run agent:no-subagent-scaling && npm run agent:native-cli-session-proof && npm run agent:worker-backend-router && npm run agent:codex-child-overlap && npm run agent:model-authored-patch-envelope && npm run agent:fast-mode-default && npm run agent:fast-mode-worker-propagation && npm run codex:fast-mode-profile-propagation && npm run mad-sks:fast-mode-propagation && npm run zellij:launch-command-truth && npm run zellij:real-session-heartbeat && npm run zellij:ui-design && npm run zellij:doctor-readiness && npm run legacy:upgrade-zero-break && npm run publish:packlist-performance && npm run postinstall:safe-side-effects && npm run runtime:ts-rust-boundary && npm run core-skill:card-schema && npm run core-skill:rollout-scoring && npm run core-skill:patch && npm run core-skill:heldout-validation && npm run core-skill:deployment-snapshot && npm run core-skill:no-inference-optimizer && npm run core-skill:route-runtime-integration && npm run core-skill:promotion-side-effect-ledger && npm run core-skill:legacy-promotion-api-audit && npm run safety:side-effect-zero && npm run safety:mutation-callsite-coverage && npm run safety:mutation-callsite-coverage:repo-wide && npm run side-effect:runtime-report && npm run release:gate-planner && npm run release:dynamic-performance && npm run release:provenance && npm run release:gate-budget && npm run agent:wiki-context-proof && npm run shared-memory:check && npm run wrongness:check && npm run wrongness:fixtures && npm run trust:check && npm run git-collaboration:e2e && node ./dist/scripts/release-check-stamp.js write && npm run release:readiness --silent && node ./dist/scripts/release-check-stamp.js write",
314
316
  "release:real-check": "node ./dist/scripts/release-real-check.js && npm run codex-control:real-smoke -- --require-real && npm run codex-sdk:real-smoke -- --require-real && SKS_REQUIRE_LOCAL_LLM=1 npm run local-llm:smoke && SKS_REQUIRE_LOCAL_LLM=1 npm run local-llm:throughput && SKS_REQUIRE_LOCAL_LLM=1 npm run local-llm:cache-performance && SKS_REQUIRE_PYTHON_CODEX_SDK=1 npm run python-sdk:real-smoke && SKS_REQUIRE_CODEX_0137=1 npm run codex:0.137-compat:require-real && npm run zellij:real-session-launch -- --require-real --main-only --mission M-release-real-zellij-extra --session sks-rrz-extra && npm run zellij:pane-proof -- --require-real --mission M-release-real-zellij-extra --session sks-rrz-extra --expected-lanes 0 && npm run zellij:screen-proof -- --require-real --main-only --mission M-release-real-zellij-extra && npm run zellij:real-session-cleanup -- --mission M-release-real-zellij-extra --session sks-rrz-extra && npm run agent:real-codex-in-zellij-worker-pane -- --require-real && SKS_REQUIRE_ZELLIJ=1 npm run naruto:zellij-massive-ui -- --require-real && SKS_REQUIRE_LOCAL_LLM=1 SKS_REQUIRE_GPT_FINAL=1 npm run naruto:real-local-gpt-final-smoke && SKS_REQUIRE_LOCAL_LLM=1 SKS_REQUIRE_GPT_FINAL=1 npm run local-collab:gpt-final-performance",
315
317
  "release:publish": "npm run publish:npm",
316
318
  "publish:dry": "npm run release:metadata && npm run release:version-truth && npm run publish:packlist-performance && npm run prepublish:release-check-or-fast && node ./dist/scripts/release-check-stamp.js verify && npm run release:provenance -- --publish && npm run release:dist-freshness && npm --cache /tmp/sks-npm-cache publish --dry-run --registry https://registry.npmjs.org/ --access public",
@@ -453,6 +455,7 @@
453
455
  "agent:native-cli-session-swarm": "node ./dist/scripts/agent-native-cli-session-swarm-check.js",
454
456
  "naruto:shadow-clone-swarm": "node ./dist/scripts/naruto-shadow-clone-swarm-check.js",
455
457
  "naruto:work-graph": "node ./dist/scripts/naruto-work-graph-check.js",
458
+ "naruto:readonly-routing": "node ./dist/scripts/naruto-readonly-routing-check.js",
456
459
  "naruto:concurrency-governor": "node ./dist/scripts/naruto-concurrency-governor-check.js",
457
460
  "naruto:active-pool": "node ./dist/scripts/naruto-active-pool-check.js",
458
461
  "naruto:role-distribution": "node ./dist/scripts/naruto-role-distribution-check.js",