sneakoscope 3.0.2 → 3.0.3
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 +1 -1
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/crates/sks-core/src/main.rs +1 -1
- package/dist/.sks-build-stamp.json +4 -4
- package/dist/bin/sks.js +1 -1
- package/dist/core/agents/runtime-proof-summary.js +17 -1
- package/dist/core/codex/codex-cli-syntax-builder.js +4 -1
- package/dist/core/codex-control/codex-0139-capability.js +68 -12
- package/dist/core/codex-control/codex-multi-agent-event-normalizer.js +15 -0
- package/dist/core/codex-control/codex-tool-schema-fixtures.js +57 -0
- package/dist/core/fsx.js +1 -1
- package/dist/core/mcp/mcp-0-134-policy.js +3 -0
- package/dist/core/pipeline-internals/runtime-core.js +6 -1
- package/dist/core/version.js +1 -1
- package/dist/core/zellij/zellij-command.js +12 -1
- package/dist/core/zellij/zellij-fake-adapter.js +163 -0
- package/dist/core/zellij/zellij-worker-pane-summary.js +65 -0
- package/dist/scripts/github-release-body-helper.js +21 -1
- package/package.json +16 -2
package/README.md
CHANGED
|
@@ -35,7 +35,7 @@ Set up this agent project with Sneakoscope Codex. Use [[mandarange/Sneakoscope-C
|
|
|
35
35
|
|
|
36
36
|
## 🚀 Current Release
|
|
37
37
|
|
|
38
|
-
SKS **3.0.
|
|
38
|
+
SKS **3.0.3** is Codex 0.139-aware while it bundles @openai/codex-sdk 0.138.0 at this release boundary. It detects and uses 0.139 features from the external Codex CLI when that CLI supports them, with release gates that include hermetic fixtures and optional real probes for code-mode web search markers, preserved `oneOf`/`allOf` tool schemas, plugin marketplace `source`, the `-P` profile alias, the multi-agent v2 `interrupt_agent` rename, Zellij stacked/fallback pane proof, pane-lock openWorkerPane integration, release cache safety fixtures, runtime proof summaries, and release proof source-truth artifacts. See [docs/codex-0.139-compat.md](docs/codex-0.139-compat.md).
|
|
39
39
|
|
|
40
40
|
SKS 3.0.0 was the parallel-runtime stabilization release. The whole live-swarm experience — what you actually *see* while 5, 20, or 100 workers run — was rebuilt and proven end-to-end.
|
|
41
41
|
|
|
@@ -4,7 +4,7 @@ use std::io::{self, Read, Seek, SeekFrom};
|
|
|
4
4
|
fn main() {
|
|
5
5
|
let mut args = std::env::args().skip(1);
|
|
6
6
|
match args.next().as_deref() {
|
|
7
|
-
Some("--version") => println!("sks-rs 3.0.
|
|
7
|
+
Some("--version") => println!("sks-rs 3.0.3"),
|
|
8
8
|
Some("compact-info") => {
|
|
9
9
|
let mut input = String::new();
|
|
10
10
|
let _ = io::stdin().read_to_string(&mut input);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": "sks.dist-build-stamp.v1",
|
|
3
3
|
"package_name": "sneakoscope",
|
|
4
|
-
"package_version": "3.0.
|
|
5
|
-
"source_digest": "
|
|
6
|
-
"source_file_count":
|
|
7
|
-
"built_at_source_time":
|
|
4
|
+
"package_version": "3.0.3",
|
|
5
|
+
"source_digest": "4630d65c17e3297a1a79b5b96be0b849ee4ada4ac1ff010a4e024b06d8b7b750",
|
|
6
|
+
"source_file_count": 2304,
|
|
7
|
+
"built_at_source_time": 1781142991546
|
|
8
8
|
}
|
package/dist/bin/sks.js
CHANGED
|
@@ -2,6 +2,7 @@ import path from 'node:path';
|
|
|
2
2
|
import { findLatestMission, missionDir } from '../mission.js';
|
|
3
3
|
import { readJson, writeJsonAtomic } from '../fsx.js';
|
|
4
4
|
import { readAgentMessageBus } from './agent-message-bus.js';
|
|
5
|
+
import { buildZellijWorkerPaneSummary } from '../zellij/zellij-worker-pane-summary.js';
|
|
5
6
|
export const RUNTIME_PROOF_SUMMARY_SCHEMA = 'sks.runtime-proof-summary.v1';
|
|
6
7
|
export async function buildRuntimeProofSummary(root, missionIdInput = 'latest', opts = {}) {
|
|
7
8
|
const missionId = missionIdInput === 'latest' ? await findLatestMission(root) : missionIdInput;
|
|
@@ -16,6 +17,7 @@ export async function buildRuntimeProofSummary(root, missionIdInput = 'latest',
|
|
|
16
17
|
const governor = await readJson(path.join(agentsDir, 'naruto-concurrency-governor.json'), null);
|
|
17
18
|
const messagesAll = await readAgentMessageBus(root, missionId, { max: 500 });
|
|
18
19
|
const recentMessages = await readAgentMessageBus(root, missionId, { max: opts.maxMessages || 8 });
|
|
20
|
+
const zellijSummary = await buildZellijWorkerPaneSummary(root, missionId).catch(() => null);
|
|
19
21
|
const failedMessages = messagesAll.filter((row) => row.event_type === 'worker_failed');
|
|
20
22
|
const errorMessages = messagesAll.filter((row) => row.level === 'error');
|
|
21
23
|
const telemetryAgeMs = telemetry?.updated_at ? Math.max(0, Date.now() - Date.parse(telemetry.updated_at)) : Number.MAX_SAFE_INTEGER;
|
|
@@ -27,7 +29,8 @@ export async function buildRuntimeProofSummary(root, missionIdInput = 'latest',
|
|
|
27
29
|
...(!scheduler ? ['agent_scheduler_state_missing'] : []),
|
|
28
30
|
...(parallel?.passed === false ? parallel.blockers || ['parallel_runtime_proof_failed'] : []),
|
|
29
31
|
...(errorMessages.length ? ['agent_message_bus_error_blockers'] : []),
|
|
30
|
-
...(telemetryAgeMs > 3000 ? ['zellij_telemetry_stale'] : [])
|
|
32
|
+
...(telemetryAgeMs > 3000 ? ['zellij_telemetry_stale'] : []),
|
|
33
|
+
...(zellijSummary?.blockers || [])
|
|
31
34
|
].map(String);
|
|
32
35
|
const summary = {
|
|
33
36
|
schema: RUNTIME_PROOF_SUMMARY_SCHEMA,
|
|
@@ -61,6 +64,15 @@ export async function buildRuntimeProofSummary(root, missionIdInput = 'latest',
|
|
|
61
64
|
warning_count: messagesAll.filter((row) => row.level === 'warning').length,
|
|
62
65
|
error_count: errorMessages.length
|
|
63
66
|
},
|
|
67
|
+
zellij: {
|
|
68
|
+
stacked_requested_count: Number(zellijSummary?.stacked_requested_count || 0),
|
|
69
|
+
stacked_applied_count: Number(zellijSummary?.stacked_applied_count || 0),
|
|
70
|
+
stacked_fallback_count: Number(zellijSummary?.stacked_fallback_count || 0),
|
|
71
|
+
fallback_modes: zellijSummary?.fallback_modes || {},
|
|
72
|
+
pane_lock_wait_p95_ms: Number(zellijSummary?.pane_lock_wait_p95_ms || 0),
|
|
73
|
+
pane_lock_held_p95_ms: Number(zellijSummary?.pane_lock_held_p95_ms || 0),
|
|
74
|
+
duplicate_slot_anchor_count: Number(zellijSummary?.duplicate_slot_anchor_count || 0)
|
|
75
|
+
},
|
|
64
76
|
blockers
|
|
65
77
|
};
|
|
66
78
|
await writeJsonAtomic(path.join(agentsDir, 'runtime-proof-summary.json'), summary);
|
|
@@ -75,6 +87,10 @@ export function renderRuntimeProofSummary(summary) {
|
|
|
75
87
|
`Visible/headless: ${summary.ui.visible_panes} / ${summary.ui.headless_workers}`,
|
|
76
88
|
`Telemetry: ${summary.ui.stale ? `stale ${(summary.ui.telemetry_age_ms / 1000).toFixed(1)}s` : `fresh ${(summary.ui.telemetry_age_ms / 1000).toFixed(1)}s`}`,
|
|
77
89
|
`Model calls max: ${summary.model_calls.max_observed}`,
|
|
90
|
+
`Zellij stacked panes: ${summary.zellij.stacked_applied_count}/${summary.zellij.stacked_requested_count} applied`,
|
|
91
|
+
`Stack fallback: ${summary.zellij.stacked_fallback_count}`,
|
|
92
|
+
`Pane lock wait p95: ${summary.zellij.pane_lock_wait_p95_ms}ms`,
|
|
93
|
+
`SLOTS anchors: ${summary.zellij.duplicate_slot_anchor_count}`,
|
|
78
94
|
...(summary.messages.recent.length ? [
|
|
79
95
|
'Recent worker messages:',
|
|
80
96
|
...summary.messages.recent.map((row) => ` ${messageStatusLabel(row)} ${row.slot_id || row.worker_id}: ${row.message}`)
|
|
@@ -23,7 +23,7 @@ export function buildCodexExecArgs(opts) {
|
|
|
23
23
|
if (opts.skipGitRepoCheck)
|
|
24
24
|
args.push('--skip-git-repo-check');
|
|
25
25
|
if (opts.profile)
|
|
26
|
-
args.push(
|
|
26
|
+
args.push(...buildCodexProfileArgs(opts.profile, opts.profileAlias));
|
|
27
27
|
else if (opts.ignoreUserConfig)
|
|
28
28
|
args.push('--ignore-user-config');
|
|
29
29
|
if (opts.ignoreRules)
|
|
@@ -40,6 +40,9 @@ export function buildCodexExecArgs(opts) {
|
|
|
40
40
|
args.push(opts.prompt);
|
|
41
41
|
return args;
|
|
42
42
|
}
|
|
43
|
+
export function buildCodexProfileArgs(profile, alias = 'long') {
|
|
44
|
+
return alias === 'short' ? ['-P', profile] : ['--profile', profile];
|
|
45
|
+
}
|
|
43
46
|
function normalizeCodexServiceTier(value) {
|
|
44
47
|
const text = String(value || '').toLowerCase();
|
|
45
48
|
if (text === 'fast' || text === 'priority')
|
|
@@ -13,33 +13,52 @@ export async function detectCodex0139Capability(input = {}) {
|
|
|
13
13
|
const parsed = parseCodexVersionText(versionText);
|
|
14
14
|
const atLeast139 = Boolean(parsed && compareSemverLike(parsed, '0.139.0') >= 0);
|
|
15
15
|
const probeMode = process.env.SKS_CODEX_0139_PROBE === '1' ? 'feature-probe' : 'version-only';
|
|
16
|
+
const probeTimeoutMs = Math.max(1, Number(process.env.SKS_CODEX_0139_PROBE_TIMEOUT_MS || 3000) || 3000);
|
|
16
17
|
const featureProbeResults = probeMode === 'feature-probe'
|
|
17
|
-
? await probeCodex0139Features(codexBin, { fake })
|
|
18
|
+
? await probeCodex0139Features(codexBin, { fake, timeoutMs: probeTimeoutMs })
|
|
18
19
|
: {
|
|
19
20
|
marketplace_list_json: 'skipped',
|
|
20
|
-
sandbox_profile_alias: 'skipped'
|
|
21
|
+
sandbox_profile_alias: 'skipped',
|
|
22
|
+
interrupt_agent_event_mapping: 'skipped',
|
|
23
|
+
rich_tool_schema_preservation: 'skipped',
|
|
24
|
+
doctor_env_redaction: 'skipped',
|
|
25
|
+
code_mode_web_search: 'skipped'
|
|
21
26
|
};
|
|
22
27
|
const marketplaceOk = atLeast139 && (probeMode === 'version-only' || featureProbeResults.marketplace_list_json !== 'failed');
|
|
23
28
|
const profileAliasOk = atLeast139 && (probeMode === 'version-only' || featureProbeResults.sandbox_profile_alias !== 'failed');
|
|
29
|
+
const interruptAgentOk = atLeast139 && (probeMode === 'version-only' || featureProbeResults.interrupt_agent_event_mapping !== 'failed');
|
|
30
|
+
const richSchemaOk = atLeast139 && (probeMode === 'version-only' || featureProbeResults.rich_tool_schema_preservation !== 'failed');
|
|
31
|
+
const doctorEnvOk = atLeast139 && (probeMode === 'version-only' || featureProbeResults.doctor_env_redaction !== 'failed');
|
|
32
|
+
const codeSearchOk = atLeast139 && (probeMode === 'version-only' || featureProbeResults.code_mode_web_search !== 'failed');
|
|
33
|
+
const probeErrorSummary = Object.entries(featureProbeResults)
|
|
34
|
+
.filter(([, status]) => status === 'failed')
|
|
35
|
+
.map(([name]) => `${name}:failed`);
|
|
24
36
|
const blockers = [
|
|
25
37
|
...(!codexBin ? ['codex_cli_missing'] : []),
|
|
26
38
|
...(atLeast139 ? [] : ['codex_0_139_required_for_search_schema_marketplace_features']),
|
|
27
|
-
...(probeMode === 'feature-probe' && featureProbeResults.marketplace_list_json === 'failed' ? ['codex_marketplace_list_json_probe_failed'] : [])
|
|
39
|
+
...(probeMode === 'feature-probe' && featureProbeResults.marketplace_list_json === 'failed' ? ['codex_marketplace_list_json_probe_failed'] : []),
|
|
40
|
+
...(probeMode === 'feature-probe' && featureProbeResults.sandbox_profile_alias === 'failed' ? ['codex_sandbox_profile_alias_probe_failed'] : []),
|
|
41
|
+
...(probeMode === 'feature-probe' && featureProbeResults.interrupt_agent_event_mapping === 'failed' ? ['codex_interrupt_agent_probe_failed'] : []),
|
|
42
|
+
...(probeMode === 'feature-probe' && featureProbeResults.rich_tool_schema_preservation === 'failed' ? ['codex_rich_tool_schema_probe_failed'] : []),
|
|
43
|
+
...(probeMode === 'feature-probe' && featureProbeResults.doctor_env_redaction === 'failed' ? ['codex_doctor_env_redaction_probe_failed'] : []),
|
|
44
|
+
...(probeMode === 'feature-probe' && featureProbeResults.code_mode_web_search === 'failed' ? ['codex_code_mode_web_search_probe_failed'] : [])
|
|
28
45
|
];
|
|
29
46
|
return {
|
|
30
47
|
schema: 'sks.codex-0139-capability.v1',
|
|
31
48
|
ok: atLeast139 && blockers.length === 0,
|
|
32
49
|
probe_mode: probeMode,
|
|
50
|
+
probe_timeout_ms: probeTimeoutMs,
|
|
51
|
+
probe_error_summary: probeErrorSummary,
|
|
33
52
|
codex_bin: codexBin || null,
|
|
34
53
|
version_text: versionText || null,
|
|
35
54
|
parsed_version: parsed,
|
|
36
|
-
supports_code_mode_web_search:
|
|
37
|
-
supports_rich_tool_schemas:
|
|
38
|
-
supports_doctor_env_details:
|
|
55
|
+
supports_code_mode_web_search: codeSearchOk,
|
|
56
|
+
supports_rich_tool_schemas: richSchemaOk,
|
|
57
|
+
supports_doctor_env_details: doctorEnvOk,
|
|
39
58
|
supports_marketplace_source_field: marketplaceOk,
|
|
40
59
|
supports_plugin_catalog_cache: atLeast139,
|
|
41
60
|
supports_sandbox_profile_alias: profileAliasOk,
|
|
42
|
-
supports_interrupt_agent_rename:
|
|
61
|
+
supports_interrupt_agent_rename: interruptAgentOk,
|
|
43
62
|
feature_probe_results: featureProbeResults,
|
|
44
63
|
blockers
|
|
45
64
|
};
|
|
@@ -71,12 +90,23 @@ async function probeCodex0139Features(codexBin, opts = {}) {
|
|
|
71
90
|
if (opts.fake) {
|
|
72
91
|
return {
|
|
73
92
|
marketplace_list_json: process.env.SKS_CODEX_0139_FAKE_MARKETPLACE_FAIL === '1' ? 'failed' : 'passed',
|
|
74
|
-
sandbox_profile_alias: 'passed'
|
|
93
|
+
sandbox_profile_alias: process.env.SKS_CODEX_0139_FAKE_PROFILE_ALIAS_FAIL === '1' ? 'failed' : 'passed',
|
|
94
|
+
interrupt_agent_event_mapping: process.env.SKS_CODEX_0139_FAKE_INTERRUPT_FAIL === '1' ? 'failed' : 'passed',
|
|
95
|
+
rich_tool_schema_preservation: process.env.SKS_CODEX_0139_FAKE_RICH_SCHEMA_FAIL === '1' ? 'failed' : 'passed',
|
|
96
|
+
doctor_env_redaction: process.env.SKS_CODEX_0139_FAKE_DOCTOR_ENV_FAIL === '1' ? 'failed' : 'passed',
|
|
97
|
+
code_mode_web_search: process.env.SKS_CODEX_0139_FAKE_WEB_SEARCH_FAIL === '1' ? 'failed' : 'passed'
|
|
75
98
|
};
|
|
76
99
|
}
|
|
77
|
-
const timeoutMs = Math.max(1, Number(process.env.SKS_CODEX_0139_PROBE_TIMEOUT_MS || 3000) || 3000);
|
|
100
|
+
const timeoutMs = Math.max(1, Number(opts.timeoutMs || process.env.SKS_CODEX_0139_PROBE_TIMEOUT_MS || 3000) || 3000);
|
|
78
101
|
if (!codexBin) {
|
|
79
|
-
return {
|
|
102
|
+
return {
|
|
103
|
+
marketplace_list_json: 'failed',
|
|
104
|
+
sandbox_profile_alias: 'failed',
|
|
105
|
+
interrupt_agent_event_mapping: 'skipped',
|
|
106
|
+
rich_tool_schema_preservation: 'skipped',
|
|
107
|
+
doctor_env_redaction: 'skipped',
|
|
108
|
+
code_mode_web_search: 'skipped'
|
|
109
|
+
};
|
|
80
110
|
}
|
|
81
111
|
const marketplace = await runProcess(codexBin, ['plugin', 'marketplace', 'list', '--json'], { timeoutMs, maxOutputBytes: 256 * 1024 }).catch(() => ({ code: 1, stdout: '' }));
|
|
82
112
|
const marketplaceListJson = marketplace.code === 0 && marketplaceSourcesPresent(marketplace.stdout) ? 'passed' : 'failed';
|
|
@@ -84,7 +114,11 @@ async function probeCodex0139Features(codexBin, opts = {}) {
|
|
|
84
114
|
const aliasOk = help.code === 0 && /(^|\s)-P[,\s]/m.test(String(help.stdout || ''));
|
|
85
115
|
return {
|
|
86
116
|
marketplace_list_json: marketplaceListJson,
|
|
87
|
-
sandbox_profile_alias: aliasOk ? 'passed' : 'failed'
|
|
117
|
+
sandbox_profile_alias: aliasOk ? 'passed' : 'failed',
|
|
118
|
+
interrupt_agent_event_mapping: 'skipped',
|
|
119
|
+
rich_tool_schema_preservation: 'skipped',
|
|
120
|
+
doctor_env_redaction: 'skipped',
|
|
121
|
+
code_mode_web_search: 'skipped'
|
|
88
122
|
};
|
|
89
123
|
}
|
|
90
124
|
export function marketplaceSourcesPresent(stdout) {
|
|
@@ -93,10 +127,32 @@ export function marketplaceSourcesPresent(stdout) {
|
|
|
93
127
|
const rows = Array.isArray(parsed) ? parsed : Array.isArray(parsed?.marketplaces) ? parsed.marketplaces : Array.isArray(parsed?.items) ? parsed.items : [];
|
|
94
128
|
if (!rows.length)
|
|
95
129
|
return true;
|
|
96
|
-
return rows.
|
|
130
|
+
return rows.every((row) => typeof row?.source === 'string' && row.source.length > 0);
|
|
97
131
|
}
|
|
98
132
|
catch {
|
|
99
133
|
return false;
|
|
100
134
|
}
|
|
101
135
|
}
|
|
136
|
+
export function codexHelpSupportsSandboxProfileAlias(stdout) {
|
|
137
|
+
return /(^|\s)-P[,\s]+--profile\b|--profile[,\s]+-P\b|(^|\s)-P\b/m.test(String(stdout || ''));
|
|
138
|
+
}
|
|
139
|
+
export function redactCodexDoctorEnvDetails(value) {
|
|
140
|
+
if (Array.isArray(value))
|
|
141
|
+
return value.map((item) => redactCodexDoctorEnvDetails(item));
|
|
142
|
+
if (!value || typeof value !== 'object') {
|
|
143
|
+
return secretLikeValue(value) ? '<redacted>' : value;
|
|
144
|
+
}
|
|
145
|
+
return Object.fromEntries(Object.entries(value).map(([key, entry]) => {
|
|
146
|
+
if (secretLikeKey(key) || secretLikeValue(entry))
|
|
147
|
+
return [key, '<redacted>'];
|
|
148
|
+
return [key, redactCodexDoctorEnvDetails(entry)];
|
|
149
|
+
}));
|
|
150
|
+
}
|
|
151
|
+
function secretLikeKey(key) {
|
|
152
|
+
return /(?:api[_-]?key|auth[_-]?token|secret|password|credential|bearer|session[_-]?token)/i.test(key);
|
|
153
|
+
}
|
|
154
|
+
function secretLikeValue(value) {
|
|
155
|
+
const text = typeof value === 'string' ? value : '';
|
|
156
|
+
return /(?:sk-[A-Za-z0-9_-]{6,}|Bearer\s+[A-Za-z0-9._-]{8,}|[A-Za-z0-9._-]{12,}\.[A-Za-z0-9._-]{12,}\.[A-Za-z0-9._-]{12,})/.test(text);
|
|
157
|
+
}
|
|
102
158
|
//# sourceMappingURL=codex-0139-capability.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function normalizeCodexMultiAgentEventName(name) {
|
|
2
|
+
const sourceName = String(name || '');
|
|
3
|
+
const normalized = sourceName.trim().toLowerCase().replace(/[-.\s]+/g, '_');
|
|
4
|
+
if (normalized === 'start_agent' || normalized === 'spawn_agent' || normalized === 'subagent_start') {
|
|
5
|
+
return { canonical: 'start_agent', stage: 'start', source_name: sourceName };
|
|
6
|
+
}
|
|
7
|
+
if (normalized === 'interrupt_agent') {
|
|
8
|
+
return { canonical: 'interrupt_agent', stage: 'result', source_name: sourceName };
|
|
9
|
+
}
|
|
10
|
+
if (normalized === 'close_agent' || normalized === 'subagent_stop') {
|
|
11
|
+
return { canonical: 'close_agent', stage: 'result', source_name: sourceName };
|
|
12
|
+
}
|
|
13
|
+
return { canonical: 'unknown', stage: 'unknown', source_name: sourceName };
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=codex-multi-agent-event-normalizer.js.map
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { compactMcpToolSchema } from '../mcp/mcp-0-134-policy.js';
|
|
2
|
+
export function buildCodex0139RichToolSchemaFixture() {
|
|
3
|
+
return {
|
|
4
|
+
type: 'object',
|
|
5
|
+
description: 'Codex 0.139 rich tool schema preservation fixture',
|
|
6
|
+
oneOf: [
|
|
7
|
+
{ required: ['mode'], properties: { mode: { const: 'guided' } } },
|
|
8
|
+
{ required: ['query'], properties: { query: { type: 'string' } } }
|
|
9
|
+
],
|
|
10
|
+
allOf: [
|
|
11
|
+
{ required: ['kind'] },
|
|
12
|
+
{ properties: { kind: { enum: ['search', 'inspect'] } } }
|
|
13
|
+
],
|
|
14
|
+
required: ['kind', 'payload'],
|
|
15
|
+
properties: {
|
|
16
|
+
kind: { enum: ['search', 'inspect'] },
|
|
17
|
+
payload: {
|
|
18
|
+
type: 'object',
|
|
19
|
+
required: ['target'],
|
|
20
|
+
properties: {
|
|
21
|
+
target: { type: 'string' },
|
|
22
|
+
filters: {
|
|
23
|
+
type: 'object',
|
|
24
|
+
properties: {
|
|
25
|
+
depth: { enum: ['shallow', 'deep'] }
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export function passCodex0139RichToolSchemaThroughBridge(schema = buildCodex0139RichToolSchemaFixture()) {
|
|
34
|
+
return compactMcpToolSchema(schema, 128).schema;
|
|
35
|
+
}
|
|
36
|
+
export function evaluateCodex0139RichToolSchemaPreservation(schema = buildCodex0139RichToolSchemaFixture()) {
|
|
37
|
+
const bridged = passCodex0139RichToolSchemaThroughBridge(schema);
|
|
38
|
+
const required = Array.isArray(bridged?.required) ? bridged.required : [];
|
|
39
|
+
const result = {
|
|
40
|
+
schema: 'sks.codex-0139-rich-tool-schema-preservation.v1',
|
|
41
|
+
ok: Array.isArray(bridged?.oneOf)
|
|
42
|
+
&& Array.isArray(bridged?.allOf)
|
|
43
|
+
&& Boolean(bridged?.properties?.payload?.properties?.target)
|
|
44
|
+
&& required.includes('kind')
|
|
45
|
+
&& required.includes('payload'),
|
|
46
|
+
top_level_oneOf_preserved: Array.isArray(bridged?.oneOf),
|
|
47
|
+
top_level_allOf_preserved: Array.isArray(bridged?.allOf),
|
|
48
|
+
nested_structure_preserved: Boolean(bridged?.properties?.payload?.properties?.target),
|
|
49
|
+
required_fields_retained: required.includes('kind') && required.includes('payload'),
|
|
50
|
+
bridged_schema: bridged
|
|
51
|
+
};
|
|
52
|
+
return {
|
|
53
|
+
...result,
|
|
54
|
+
blockers: result.ok ? [] : ['codex_rich_tool_schema_preservation_failed']
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=codex-tool-schema-fixtures.js.map
|
package/dist/core/fsx.js
CHANGED
|
@@ -5,7 +5,7 @@ import os from 'node:os';
|
|
|
5
5
|
import crypto from 'node:crypto';
|
|
6
6
|
import { spawn } from 'node:child_process';
|
|
7
7
|
import { fileURLToPath } from 'node:url';
|
|
8
|
-
export const PACKAGE_VERSION = '3.0.
|
|
8
|
+
export const PACKAGE_VERSION = '3.0.3';
|
|
9
9
|
export const DEFAULT_PROCESS_TAIL_BYTES = 256 * 1024;
|
|
10
10
|
export const DEFAULT_PROCESS_TIMEOUT_MS = 30 * 60 * 1000;
|
|
11
11
|
export function nowIso() {
|
|
@@ -63,6 +63,9 @@ export function compactMcpToolSchema(schema, maxBytes = 8192) {
|
|
|
63
63
|
type: schema?.type || 'object',
|
|
64
64
|
description: String(schema?.description || '').slice(0, 512),
|
|
65
65
|
properties: Object.fromEntries(Object.entries(schema?.properties || {}).slice(0, 50)),
|
|
66
|
+
...(Array.isArray(schema?.oneOf) ? { oneOf: schema.oneOf } : {}),
|
|
67
|
+
...(Array.isArray(schema?.allOf) ? { allOf: schema.allOf } : {}),
|
|
68
|
+
...(Array.isArray(schema?.required) ? { required: schema.required } : {}),
|
|
66
69
|
...preservedDefs,
|
|
67
70
|
...(refs.length ? { refs } : {})
|
|
68
71
|
},
|
|
@@ -29,6 +29,7 @@ import { CODEX_APP_IMAGE_GENERATION_DOC_URL, CODEX_COMPUTER_USE_EVIDENCE_SOURCE,
|
|
|
29
29
|
import { TEAM_DECOMPOSITION_ARTIFACT, TEAM_GRAPH_ARTIFACT, TEAM_INBOX_DIR, TEAM_RUNTIME_TASKS_ARTIFACT, teamRuntimePlanMetadata, teamRuntimeRequiredArtifacts, validateTeamRuntimeArtifacts, writeTeamRuntimeArtifacts } from '../team-dag.js';
|
|
30
30
|
import { formatAgentReasoning, formatRoleCounts, initTeamLive, parseTeamSpecText, teamReasoningPolicy } from '../team-live.js';
|
|
31
31
|
import { evaluateTeamReviewPolicyGate, MIN_TEAM_REVIEWER_LANES, MIN_TEAM_REVIEW_POLICY_TEXT, teamReviewPolicy } from '../team-review-policy.js';
|
|
32
|
+
import { normalizeCodexMultiAgentEventName } from '../codex-control/codex-multi-agent-event-normalizer.js';
|
|
32
33
|
export { routePrompt };
|
|
33
34
|
export const PIPELINE_PLAN_ARTIFACT = 'pipeline-plan.json';
|
|
34
35
|
export const PIPELINE_PLAN_SCHEMA_VERSION = 1;
|
|
@@ -1257,7 +1258,11 @@ function subagentStage(payload) {
|
|
|
1257
1258
|
return 'exception';
|
|
1258
1259
|
if (/spawn_agent/i.test(hay))
|
|
1259
1260
|
return 'spawn_agent';
|
|
1260
|
-
|
|
1261
|
+
for (const name of ['interrupt_agent', 'close_agent']) {
|
|
1262
|
+
if (hay.includes(name) && normalizeCodexMultiAgentEventName(name).stage === 'result')
|
|
1263
|
+
return 'result';
|
|
1264
|
+
}
|
|
1265
|
+
if (/wait_agent|completed|final/i.test(hay))
|
|
1261
1266
|
return 'result';
|
|
1262
1267
|
return 'subagent';
|
|
1263
1268
|
}
|
package/dist/core/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const PACKAGE_VERSION = '3.0.
|
|
1
|
+
export const PACKAGE_VERSION = '3.0.3';
|
|
2
2
|
//# sourceMappingURL=version.js.map
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { runProcess } from '../fsx.js';
|
|
4
|
+
import { runFakeZellij } from './zellij-fake-adapter.js';
|
|
4
5
|
export const ZELLIJ_UNIX_SOCKET_PATH_LIMIT = 103;
|
|
5
6
|
export async function runZellij(args = [], opts = {}) {
|
|
6
7
|
const started = Date.now();
|
|
@@ -16,7 +17,17 @@ export async function runZellij(args = [], opts = {}) {
|
|
|
16
17
|
runOpts.stdoutFile = opts.stdoutFile;
|
|
17
18
|
if (opts.stderrFile !== undefined)
|
|
18
19
|
runOpts.stderrFile = opts.stderrFile;
|
|
19
|
-
const
|
|
20
|
+
const fakeOpts = {
|
|
21
|
+
cwd: runOpts.cwd || process.cwd(),
|
|
22
|
+
env: preparedEnv.env
|
|
23
|
+
};
|
|
24
|
+
if (runOpts.timeoutMs !== undefined)
|
|
25
|
+
fakeOpts.timeoutMs = runOpts.timeoutMs;
|
|
26
|
+
if (runOpts.maxOutputBytes !== undefined)
|
|
27
|
+
fakeOpts.maxOutputBytes = runOpts.maxOutputBytes;
|
|
28
|
+
const result = process.env.SKS_ZELLIJ_FAKE_ADAPTER === '1' || preparedEnv.env.SKS_ZELLIJ_FAKE_ADAPTER === '1'
|
|
29
|
+
? await runFakeZellij(args, fakeOpts)
|
|
30
|
+
: await runProcess('zellij', args, runOpts);
|
|
20
31
|
const ok = result.code === 0;
|
|
21
32
|
const stderr = String(result.stderr || '');
|
|
22
33
|
const missing = result.code === -1 && /ENOENT|not found|spawn zellij/i.test(stderr);
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { appendJsonl, ensureDir, nowIso } from '../fsx.js';
|
|
3
|
+
const sessions = new Map();
|
|
4
|
+
export async function runFakeZellij(args = [], opts = {}) {
|
|
5
|
+
const env = { ...process.env, ...(opts.env || {}) };
|
|
6
|
+
const root = path.resolve(String(env.SKS_ZELLIJ_FAKE_ROOT || opts.cwd || process.cwd()));
|
|
7
|
+
const version = String(env.SKS_ZELLIJ_FAKE_VERSION || '0.43.1');
|
|
8
|
+
const delayMs = Math.max(0, Number(env.SKS_ZELLIJ_FAKE_DELAY_MS || 0) || 0);
|
|
9
|
+
const sessionName = sessionFromArgs(args);
|
|
10
|
+
const startedAt = Date.now();
|
|
11
|
+
let result;
|
|
12
|
+
if (args.length === 1 && args[0] === '--version') {
|
|
13
|
+
result = ok(`zellij ${version}\n`);
|
|
14
|
+
}
|
|
15
|
+
else if (args[0] === 'attach' && args[1] === '--create-background') {
|
|
16
|
+
getSession(String(args[2] || 'default'));
|
|
17
|
+
result = ok('');
|
|
18
|
+
}
|
|
19
|
+
else if (args.includes('new-pane')) {
|
|
20
|
+
if (args.includes('--stacked') && !supportsStacked(version)) {
|
|
21
|
+
result = fail('unknown option --stacked');
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
if (delayMs > 0)
|
|
25
|
+
await sleep(delayMs);
|
|
26
|
+
const session = getSession(sessionName);
|
|
27
|
+
const name = optionValue(args, '--name') || `pane-${session.next_id}`;
|
|
28
|
+
const paneId = `terminal_${session.next_id++}`;
|
|
29
|
+
const command = commandAfter(args, '--') || '';
|
|
30
|
+
const pane = { pane_id: paneId, title: name, name, terminal_command: command, exited: false };
|
|
31
|
+
session.panes.push(pane);
|
|
32
|
+
session.focused_pane_id = paneId;
|
|
33
|
+
result = ok(`${JSON.stringify({ pane_id: paneId })}\n`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
else if (args.includes('focus-pane-id')) {
|
|
37
|
+
const paneId = String(args[args.indexOf('focus-pane-id') + 1] || '');
|
|
38
|
+
const session = getSession(sessionName);
|
|
39
|
+
const pane = findPane(session, paneId);
|
|
40
|
+
if (!pane)
|
|
41
|
+
result = fail(`Pane ${paneId} not found`);
|
|
42
|
+
else {
|
|
43
|
+
session.focused_pane_id = pane.pane_id;
|
|
44
|
+
result = ok('');
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
else if (args.includes('list-panes')) {
|
|
48
|
+
const session = getSession(sessionName);
|
|
49
|
+
result = ok(`${JSON.stringify(session.panes)}\n`);
|
|
50
|
+
}
|
|
51
|
+
else if (args.includes('dump-screen')) {
|
|
52
|
+
const session = getSession(sessionName);
|
|
53
|
+
result = ok(session.panes.map((pane) => pane.title).join('\n') + '\n');
|
|
54
|
+
}
|
|
55
|
+
else if (args.includes('rename-pane')) {
|
|
56
|
+
const session = getSession(sessionName);
|
|
57
|
+
const paneId = optionValue(args, '--pane-id');
|
|
58
|
+
const name = String(args[args.length - 1] || '');
|
|
59
|
+
const pane = paneId ? findPane(session, paneId) : session.panes.find((row) => row.pane_id === session.focused_pane_id);
|
|
60
|
+
if (!pane)
|
|
61
|
+
result = fail(`Pane ${paneId || 'focused'} not found`);
|
|
62
|
+
else {
|
|
63
|
+
pane.title = name;
|
|
64
|
+
pane.name = name;
|
|
65
|
+
result = ok('');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
else if (args.includes('close-pane')) {
|
|
69
|
+
const session = getSession(sessionName);
|
|
70
|
+
const paneId = optionValue(args, '--pane-id');
|
|
71
|
+
const pane = paneId ? findPane(session, paneId) : session.panes.find((row) => row.pane_id === session.focused_pane_id);
|
|
72
|
+
if (!pane)
|
|
73
|
+
result = fail(`Pane ${paneId || 'focused'} not found`);
|
|
74
|
+
else {
|
|
75
|
+
pane.exited = true;
|
|
76
|
+
result = ok('');
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
result = ok('');
|
|
81
|
+
}
|
|
82
|
+
await recordFakeZellijCall(root, args, {
|
|
83
|
+
session_name: sessionName,
|
|
84
|
+
version,
|
|
85
|
+
exit_code: result.code,
|
|
86
|
+
duration_ms: Date.now() - startedAt
|
|
87
|
+
});
|
|
88
|
+
return result;
|
|
89
|
+
}
|
|
90
|
+
async function recordFakeZellijCall(root, args, meta) {
|
|
91
|
+
const file = path.join(root, '.sneakoscope', 'fake-zellij-calls.jsonl');
|
|
92
|
+
await ensureDir(path.dirname(file));
|
|
93
|
+
await appendJsonl(file, {
|
|
94
|
+
schema: 'sks.fake-zellij-call.v1',
|
|
95
|
+
ts: nowIso(),
|
|
96
|
+
args: [...args],
|
|
97
|
+
...meta
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
function getSession(name) {
|
|
101
|
+
const key = String(name || 'default');
|
|
102
|
+
const existing = sessions.get(key);
|
|
103
|
+
if (existing)
|
|
104
|
+
return existing;
|
|
105
|
+
const next = { next_id: 1, focused_pane_id: null, panes: [] };
|
|
106
|
+
sessions.set(key, next);
|
|
107
|
+
return next;
|
|
108
|
+
}
|
|
109
|
+
function sessionFromArgs(args) {
|
|
110
|
+
const explicit = optionValue(args, '--session');
|
|
111
|
+
if (explicit)
|
|
112
|
+
return explicit;
|
|
113
|
+
if (args[0] === 'attach' && args[1] === '--create-background')
|
|
114
|
+
return String(args[2] || 'default');
|
|
115
|
+
return 'default';
|
|
116
|
+
}
|
|
117
|
+
function optionValue(args, flag) {
|
|
118
|
+
const index = args.indexOf(flag);
|
|
119
|
+
if (index < 0)
|
|
120
|
+
return null;
|
|
121
|
+
const value = args[index + 1];
|
|
122
|
+
return value == null ? null : String(value);
|
|
123
|
+
}
|
|
124
|
+
function commandAfter(args, marker) {
|
|
125
|
+
const index = args.indexOf(marker);
|
|
126
|
+
if (index < 0)
|
|
127
|
+
return null;
|
|
128
|
+
return args.slice(index + 1).map(String).join(' ');
|
|
129
|
+
}
|
|
130
|
+
function findPane(session, id) {
|
|
131
|
+
const normalized = String(id || '').replace(/^terminal_/, '');
|
|
132
|
+
return session.panes.find((pane) => pane.pane_id === id || pane.pane_id.replace(/^terminal_/, '') === normalized) || null;
|
|
133
|
+
}
|
|
134
|
+
function supportsStacked(version) {
|
|
135
|
+
const parts = String(version || '0.0.0').match(/(\d+)\.(\d+)\.(\d+)/)?.slice(1).map((part) => Number.parseInt(part, 10) || 0) || [0, 0, 0];
|
|
136
|
+
return parts[0] > 0 || parts[1] > 43 || (parts[1] === 43 && parts[2] >= 0);
|
|
137
|
+
}
|
|
138
|
+
function ok(stdout) {
|
|
139
|
+
return {
|
|
140
|
+
code: 0,
|
|
141
|
+
stdout,
|
|
142
|
+
stderr: '',
|
|
143
|
+
stdoutBytes: Buffer.byteLength(stdout),
|
|
144
|
+
stderrBytes: 0,
|
|
145
|
+
truncated: false,
|
|
146
|
+
timedOut: false
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
function fail(stderr) {
|
|
150
|
+
return {
|
|
151
|
+
code: 1,
|
|
152
|
+
stdout: '',
|
|
153
|
+
stderr,
|
|
154
|
+
stdoutBytes: 0,
|
|
155
|
+
stderrBytes: Buffer.byteLength(stderr),
|
|
156
|
+
truncated: false,
|
|
157
|
+
timedOut: false
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
function sleep(ms) {
|
|
161
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=zellij-fake-adapter.js.map
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { readJson, readText, writeJsonAtomic } from '../fsx.js';
|
|
4
|
+
export async function buildZellijWorkerPaneSummary(root, missionId) {
|
|
5
|
+
const missionDir = path.join(path.resolve(root), '.sneakoscope', 'missions', missionId);
|
|
6
|
+
const ledgerRows = await readJsonl(path.join(path.resolve(root), 'agent-zellij-pane-launch-ledger.jsonl'));
|
|
7
|
+
const missionRows = ledgerRows.filter((row) => !row.mission_id || row.mission_id === missionId);
|
|
8
|
+
const state = await readJson(path.join(missionDir, 'zellij-right-column-state.json'), null);
|
|
9
|
+
const metrics = await readJsonl(path.join(missionDir, 'zellij', 'pane-creation-lock-events.jsonl'));
|
|
10
|
+
const requested = missionRows.filter((row) => row.worker_stacked_requested === true);
|
|
11
|
+
const applied = missionRows.filter((row) => row.worker_stacked_applied === true);
|
|
12
|
+
const fallbackRows = missionRows.filter((row) => row.worker_stacked_requested === true && row.worker_stacked_applied !== true);
|
|
13
|
+
const fallbackModes = {};
|
|
14
|
+
for (const row of fallbackRows) {
|
|
15
|
+
const mode = String(row.worker_stacked_fallback_mode || 'unknown');
|
|
16
|
+
fallbackModes[mode] = (fallbackModes[mode] || 0) + 1;
|
|
17
|
+
}
|
|
18
|
+
const anchors = new Set([
|
|
19
|
+
...missionRows.map((row) => row.slot_column_anchor_pane_id).filter(Boolean).map(String),
|
|
20
|
+
...(state?.slot_column_anchor_pane_id ? [String(state.slot_column_anchor_pane_id)] : [])
|
|
21
|
+
]);
|
|
22
|
+
const stackedCapable = missionRows.some((row) => row.worker_stacked_capability?.supports_stacked_panes === true);
|
|
23
|
+
const waitP95 = percentile(metrics.map((row) => Number(row.wait_ms || 0)), 0.95);
|
|
24
|
+
const heldP95 = percentile(metrics.map((row) => Number(row.held_ms || 0)), 0.95);
|
|
25
|
+
const blockers = [
|
|
26
|
+
...(anchors.size > 1 ? ['zellij_duplicate_slot_anchor_count_gt_1'] : []),
|
|
27
|
+
...(requested.length > 0 && applied.length === 0 && stackedCapable ? ['zellij_stacked_requested_but_none_applied'] : []),
|
|
28
|
+
...(waitP95 > 5000 && requested.length <= 1 ? ['zellij_pane_lock_wait_high_with_low_concurrency'] : [])
|
|
29
|
+
];
|
|
30
|
+
const summary = {
|
|
31
|
+
schema: 'sks.zellij-worker-pane-summary.v1',
|
|
32
|
+
ok: blockers.length === 0,
|
|
33
|
+
mission_id: missionId,
|
|
34
|
+
stacked_requested_count: requested.length,
|
|
35
|
+
stacked_applied_count: applied.length,
|
|
36
|
+
stacked_fallback_count: fallbackRows.length,
|
|
37
|
+
fallback_modes: fallbackModes,
|
|
38
|
+
pane_lock_wait_p95_ms: waitP95,
|
|
39
|
+
pane_lock_held_p95_ms: heldP95,
|
|
40
|
+
duplicate_slot_anchor_count: anchors.size,
|
|
41
|
+
blockers
|
|
42
|
+
};
|
|
43
|
+
await writeJsonAtomic(path.join(missionDir, 'zellij-worker-pane-summary.json'), summary);
|
|
44
|
+
await writeJsonAtomic(path.join(path.resolve(root), '.sneakoscope', 'reports', 'zellij-worker-pane-summary.json'), summary);
|
|
45
|
+
return summary;
|
|
46
|
+
}
|
|
47
|
+
async function readJsonl(file) {
|
|
48
|
+
const text = await readText(file, '').catch(() => '');
|
|
49
|
+
return String(text || '').split(/\n+/).filter(Boolean).flatMap((line) => {
|
|
50
|
+
try {
|
|
51
|
+
return [JSON.parse(line)];
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return [];
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
function percentile(values, p) {
|
|
59
|
+
const sorted = values.filter((value) => Number.isFinite(value)).sort((a, b) => a - b);
|
|
60
|
+
if (!sorted.length)
|
|
61
|
+
return 0;
|
|
62
|
+
const index = Math.min(sorted.length - 1, Math.max(0, Math.ceil(sorted.length * p) - 1));
|
|
63
|
+
return Math.round(sorted[index] || 0);
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=zellij-worker-pane-summary.js.map
|
|
@@ -6,12 +6,27 @@ import { assertGate, root } from './sks-1-18-gate-lib.js';
|
|
|
6
6
|
const args = process.argv.slice(2);
|
|
7
7
|
const pkg = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8'));
|
|
8
8
|
const truth = readJson('.sneakoscope/release-proof-truth.json') || readJson('dist/release-proof-truth.json');
|
|
9
|
+
const codex0139 = readJson('.sneakoscope/codex-0139-capability.json');
|
|
10
|
+
const zellij = readJson('.sneakoscope/reports/zellij-worker-pane-summary.json');
|
|
9
11
|
const changelog = fs.readFileSync(path.join(root, 'CHANGELOG.md'), 'utf8');
|
|
10
12
|
const latest = latestChangelogSection(changelog);
|
|
13
|
+
const sdkVersion = readCodexSdkPackageVersion();
|
|
14
|
+
const warnings = [
|
|
15
|
+
...(truth?.package_version && truth.package_version !== latest.version ? [`package version ${truth.package_version} does not match changelog latest ${latest.version}`] : []),
|
|
16
|
+
...(pkg.version !== latest.version ? [`package.json version ${pkg.version} does not match changelog latest ${latest.version}`] : []),
|
|
17
|
+
...(!truth ? ['release proof truth missing'] : []),
|
|
18
|
+
...(truth?.git_status_clean === false ? ['git working tree dirty when proof truth was generated'] : [])
|
|
19
|
+
];
|
|
11
20
|
const body = [
|
|
12
21
|
`Version: ${pkg.version}`,
|
|
13
22
|
`Commit: ${truth?.git_commit_sha || 'unknown'}`,
|
|
23
|
+
`Dirty: ${truth?.git_status_clean === false ? 'yes' : truth?.git_status_clean === true ? 'no' : 'unknown'}`,
|
|
24
|
+
`Release proof truth: ${truth ? '.sneakoscope/release-proof-truth.json' : 'missing'}`,
|
|
25
|
+
`Codex SDK package: ${sdkVersion || 'unknown'}`,
|
|
26
|
+
`External Codex CLI 0.139 capability: ${codex0139 ? `${codex0139.ok ? 'ok' : 'blocked'}${codex0139.parsed_version ? ` (${codex0139.parsed_version})` : ''}` : 'not recorded'}`,
|
|
27
|
+
`Zellij stacked panes: ${zellij ? `${zellij.stacked_applied_count || 0}/${zellij.stacked_requested_count || 0} applied, fallback ${zellij.stacked_fallback_count || 0}, SLOTS anchors ${zellij.duplicate_slot_anchor_count || 0}` : 'not recorded'}`,
|
|
14
28
|
`Packlist: ${truth?.npm_packlist_count ?? 'unknown'} files / ${truth?.npm_packlist_bytes ?? 'unknown'} bytes`,
|
|
29
|
+
...(warnings.length ? [`Warnings: ${warnings.join('; ')}`] : ['Warnings: none']),
|
|
15
30
|
'Release gates: passed',
|
|
16
31
|
'',
|
|
17
32
|
latest.body.trim()
|
|
@@ -19,7 +34,8 @@ const body = [
|
|
|
19
34
|
if (args.includes('--check')) {
|
|
20
35
|
assertGate(Boolean(truth && truth.schema === 'sks.release-proof-truth.v1'), 'release proof truth missing; run npm run release:proof-truth first');
|
|
21
36
|
assertGate(latest.version === pkg.version, 'latest changelog section must match package version', { latest: latest.version, package: pkg.version });
|
|
22
|
-
assertGate(body.includes(`Version: ${pkg.version}`) && body.includes('Commit:') && body.includes('Packlist:'), 'github release body helper missing source truth fields', { body });
|
|
37
|
+
assertGate(body.includes(`Version: ${pkg.version}`) && body.includes('Commit:') && body.includes('Dirty:') && body.includes('Release proof truth:') && body.includes('Codex SDK package:') && body.includes('External Codex CLI 0.139 capability:') && body.includes('Zellij stacked panes:') && body.includes('Packlist:'), 'github release body helper missing source truth fields', { body });
|
|
38
|
+
assertGate(!warnings.some((warning) => warning.includes('package version') || warning.includes('changelog latest') || warning.includes('release proof truth missing')), 'github release body helper source truth warnings must not include version/proof mismatch', { warnings, body });
|
|
23
39
|
}
|
|
24
40
|
console.log(body);
|
|
25
41
|
function readJson(rel) {
|
|
@@ -40,4 +56,8 @@ function latestChangelogSection(text) {
|
|
|
40
56
|
const end = second?.index || text.length;
|
|
41
57
|
return { version: first[1], body: text.slice(start, end) };
|
|
42
58
|
}
|
|
59
|
+
function readCodexSdkPackageVersion() {
|
|
60
|
+
const lock = readJson('package-lock.json');
|
|
61
|
+
return lock?.packages?.['node_modules/@openai/codex-sdk']?.version || pkg.dependencies?.['@openai/codex-sdk'] || null;
|
|
62
|
+
}
|
|
43
63
|
//# sourceMappingURL=github-release-body-helper.js.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sneakoscope",
|
|
3
3
|
"displayName": "ㅅㅋㅅ",
|
|
4
|
-
"version": "3.0.
|
|
4
|
+
"version": "3.0.3",
|
|
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",
|
|
@@ -718,7 +718,21 @@
|
|
|
718
718
|
"zellij:update-prompt-safety": "node ./dist/scripts/zellij-update-prompt-safety-check.js",
|
|
719
719
|
"zellij:update-prompt-matrix": "node ./dist/scripts/zellij-update-prompt-matrix-check.js",
|
|
720
720
|
"release:proof-truth": "node ./dist/scripts/release-proof-truth-check.js",
|
|
721
|
-
"release:github-body-helper": "node ./dist/scripts/github-release-body-helper.js --check"
|
|
721
|
+
"release:github-body-helper": "node ./dist/scripts/github-release-body-helper.js --check",
|
|
722
|
+
"codex:0139-feature-probes": "node ./dist/scripts/codex-0139-feature-probes-check.js",
|
|
723
|
+
"codex:0139-interrupt-agent": "node ./dist/scripts/codex-0139-interrupt-agent-check.js",
|
|
724
|
+
"codex:0139-rich-tool-schema": "node ./dist/scripts/codex-0139-rich-tool-schema-check.js",
|
|
725
|
+
"codex:0139-doctor-env-redaction": "node ./dist/scripts/codex-0139-doctor-env-redaction-check.js",
|
|
726
|
+
"codex:0139-code-mode-web-search": "node ./dist/scripts/codex-0139-code-mode-web-search-check.js",
|
|
727
|
+
"codex:0139-marketplace-source": "node ./dist/scripts/codex-0139-marketplace-source-check.js",
|
|
728
|
+
"codex:0139-sandbox-profile-alias": "node ./dist/scripts/codex-0139-sandbox-profile-alias-check.js",
|
|
729
|
+
"codex:0139-real-probes": "node ./dist/scripts/codex-0139-real-probes-check.js --require-real",
|
|
730
|
+
"zellij:fake-adapter": "node ./dist/scripts/zellij-fake-adapter-check.js",
|
|
731
|
+
"zellij:pane-lock-open-worker-integration": "node ./dist/scripts/zellij-pane-lock-open-worker-integration-blackbox.js",
|
|
732
|
+
"zellij:stacked-fallback-integration": "node ./dist/scripts/zellij-stacked-fallback-integration-blackbox.js",
|
|
733
|
+
"runtime:proof-zellij-stacked-summary": "node ./dist/scripts/runtime-proof-zellij-stacked-summary-check.js",
|
|
734
|
+
"naruto:proof-zellij-stacked-summary": "node ./dist/scripts/naruto-proof-zellij-stacked-summary-check.js",
|
|
735
|
+
"docs:codex-0139-wording": "node ./dist/scripts/docs-codex-0139-wording-check.js"
|
|
722
736
|
},
|
|
723
737
|
"keywords": [
|
|
724
738
|
"sneakoscope",
|