sneakoscope 2.0.11 → 2.0.13

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 (75) hide show
  1. package/README.md +9 -3
  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 +27 -8
  8. package/dist/core/agents/agent-orchestrator.js +279 -1
  9. package/dist/core/agents/agent-scheduler.js +12 -1
  10. package/dist/core/agents/agent-slot-pane-binding-proof.js +3 -3
  11. package/dist/core/agents/agent-work-queue.js +26 -2
  12. package/dist/core/agents/agent-worker-pipeline.js +2 -0
  13. package/dist/core/agents/native-cli-session-swarm.js +2 -2
  14. package/dist/core/codex-control/codex-sdk-adapter.js +10 -0
  15. package/dist/core/codex-control/codex-task-runner.js +4 -2
  16. package/dist/core/commands/naruto-command.js +104 -51
  17. package/dist/core/commands/research-command.js +43 -4
  18. package/dist/core/fsx.js +1 -1
  19. package/dist/core/git/git-worktree-merge-queue.js +34 -14
  20. package/dist/core/naruto/naruto-rebalance-policy.js +15 -3
  21. package/dist/core/naruto/naruto-work-graph.js +13 -0
  22. package/dist/core/research/claim-evidence-matrix.js +160 -0
  23. package/dist/core/research/experiment-plan.js +53 -0
  24. package/dist/core/research/falsification.js +18 -0
  25. package/dist/core/research/implementation-blueprint-markdown.js +31 -0
  26. package/dist/core/research/implementation-blueprint.js +66 -0
  27. package/dist/core/research/replication-pack.js +50 -0
  28. package/dist/core/research/research-cycle-runner.js +25 -0
  29. package/dist/core/research/research-final-reviewer.js +58 -0
  30. package/dist/core/research/research-handoff.js +51 -0
  31. package/dist/core/research/research-prompt-contract.js +24 -0
  32. package/dist/core/research/research-quality-contract.js +61 -0
  33. package/dist/core/research/research-report-quality.js +67 -0
  34. package/dist/core/research/research-stage-runner.js +16 -0
  35. package/dist/core/research/research-work-graph.js +75 -0
  36. package/dist/core/research/source-quality-report.js +94 -0
  37. package/dist/core/research.js +344 -44
  38. package/dist/core/version.js +1 -1
  39. package/dist/core/zellij/zellij-slot-column-anchor.js +165 -4
  40. package/dist/core/zellij/zellij-slot-pane-renderer.js +259 -16
  41. package/dist/core/zellij/zellij-worker-pane-manager.js +13 -7
  42. package/dist/scripts/agent-real-codex-in-zellij-worker-pane-check.js +8 -2
  43. package/dist/scripts/agent-slot-pane-binding-proof-check.js +4 -4
  44. package/dist/scripts/codex-sdk-release-review-pipeline-check.js +2 -1
  45. package/dist/scripts/codex-sdk-research-pipeline-check.js +7 -0
  46. package/dist/scripts/codex-sdk-zellij-pane-binding-check.js +2 -2
  47. package/dist/scripts/git-worktree-cross-rebase-check.js +13 -1
  48. package/dist/scripts/git-worktree-merge-queue-check.js +1 -0
  49. package/dist/scripts/local-collab-worktree-gpt-final-apply-policy-check.js +63 -0
  50. package/dist/scripts/naruto-actual-worker-control-plane-check.js +30 -3
  51. package/dist/scripts/naruto-allocation-runtime-wiring-check.js +92 -0
  52. package/dist/scripts/naruto-orchestrator-runtime-source-check.js +65 -6
  53. package/dist/scripts/naruto-rebalance-policy-check.js +15 -2
  54. package/dist/scripts/naruto-shadow-clone-swarm-check.js +1 -1
  55. package/dist/scripts/packlist-performance-check.js +1 -1
  56. package/dist/scripts/release-dag-full-coverage-check.js +4 -0
  57. package/dist/scripts/release-real-check.js +258 -77
  58. package/dist/scripts/research-quality-gate-check.js +86 -0
  59. package/dist/scripts/zellij-first-slot-down-stack-check.js +1 -1
  60. package/dist/scripts/zellij-first-slot-down-stack-real-check.js +344 -4
  61. package/dist/scripts/zellij-right-column-manager-check.js +1 -1
  62. package/dist/scripts/zellij-slot-column-anchor-check.js +45 -3
  63. package/dist/scripts/zellij-slot-only-ui-check.js +3 -1
  64. package/dist/scripts/zellij-slot-pane-renderer-check.js +73 -5
  65. package/dist/scripts/zellij-slot-renderer-proof-semantics-check.js +59 -0
  66. package/dist/scripts/zellij-worker-pane-manager-check.js +23 -1
  67. package/dist/scripts/zellij-worker-pane-real-ui-blackbox.js +21 -4
  68. package/package.json +17 -2
  69. package/schemas/research/claim-evidence-matrix.schema.json +37 -0
  70. package/schemas/research/experiment-plan.schema.json +17 -0
  71. package/schemas/research/implementation-blueprint.schema.json +30 -0
  72. package/schemas/research/replication-pack.schema.json +17 -0
  73. package/schemas/research/research-final-review.schema.json +16 -0
  74. package/schemas/research/research-quality-contract.schema.json +37 -0
  75. package/schemas/research/source-quality-report.schema.json +18 -0
@@ -1,100 +1,262 @@
1
1
  #!/usr/bin/env node
2
2
  // @ts-nocheck
3
- import { spawnSync } from 'node:child_process';
3
+ import path from 'node:path';
4
+ import { spawn } from 'node:child_process';
5
+ import { writeJsonAtomic } from '../core/fsx.js';
4
6
  const args = process.argv.slice(2);
5
7
  const skipReleaseCheck = args.includes('--skip-release-check') || process.env.SKS_RELEASE_REAL_CHECK_SKIP_RELEASE_CHECK === '1';
6
8
  const root = process.cwd();
9
+ const concurrency = Math.max(1, Math.floor(Number(process.env.SKS_RELEASE_REAL_CHECK_CONCURRENCY || 4)));
7
10
  const report = {
8
11
  schema: 'sks.release-real-check.v1',
9
12
  generated_at: new Date().toISOString(),
10
13
  ok: false,
14
+ pipeline_shape: {
15
+ schema: 'sks.release-real-check-diamond.v1',
16
+ stages: ['design', 'parallel_processing', 'parallel_verification', 'aggregation'],
17
+ concurrency,
18
+ dependency_model: 'dag-with-ordered-zellij-proof-chains'
19
+ },
11
20
  release_check: null,
12
21
  environment_required_checks: [],
13
22
  real_smoke_checks: [],
23
+ real_ui_checks: [],
24
+ all_checks: [],
25
+ phase_results: [],
14
26
  blockers: [],
15
27
  warnings: []
16
28
  };
17
- if (!skipReleaseCheck) {
18
- report.release_check = runNpm('release:check');
19
- collect(report.release_check);
20
- if (!report.release_check.ok)
21
- finish(false);
22
- }
23
- else {
24
- report.release_check = {
25
- id: 'release:check',
26
- ok: true,
27
- skipped: true,
28
- note: 'Skipped because caller already verified release:check in this workspace.'
29
+ const tasks = [
30
+ task('codex:actual-config-load-probe', 'codex:actual-config-load-probe', { group: 'environment_required', phase: 'parallel_processing' }),
31
+ task('codex:0.137-compat:require-real', 'codex:0.137-compat:require-real', { group: 'environment_required', phase: 'parallel_processing', env: { SKS_REQUIRE_CODEX_0137: '1' } }),
32
+ task('codex:0.136-compat:require-real', 'codex:0.136-compat:require-real', { group: 'environment_required', phase: 'parallel_processing' }),
33
+ task('codex:0.135-compat:require-real', 'codex:0.135-compat:require-real', { group: 'environment_required', phase: 'parallel_processing' }),
34
+ task('doctor:codex-doctor-parity:actual', 'doctor:codex-doctor-parity:actual', { group: 'environment_required', phase: 'parallel_processing' }),
35
+ task('publish:dry-run-performance', 'publish:dry-run-performance', { group: 'environment_required', phase: 'parallel_processing' }),
36
+ task('zellij:capability', 'zellij:capability', { group: 'environment_required', phase: 'parallel_processing', args: ['--require-real'], env: { SKS_REQUIRE_ZELLIJ: '1' } }),
37
+ task('zellij:layout-valid', 'zellij:layout-valid', { group: 'environment_required', phase: 'parallel_processing', args: ['--require-real'], env: { SKS_REQUIRE_ZELLIJ: '1' }, deps: ['zellij:capability'] }),
38
+ task('zellij:real-session-launch:base', 'zellij:real-session-launch', { group: 'environment_required', phase: 'parallel_verification', args: ['--require-real', '--main-only', '--mission', 'M-release-real-zellij', '--session', 'sks-rrz'], env: { SKS_REQUIRE_ZELLIJ: '1' }, deps: ['zellij:layout-valid'] }),
39
+ task('zellij:pane-proof:base', 'zellij:pane-proof', { group: 'environment_required', phase: 'parallel_verification', args: ['--require-real', '--mission', 'M-release-real-zellij', '--session', 'sks-rrz', '--expected-lanes', '0'], env: { SKS_REQUIRE_ZELLIJ: '1' }, deps: ['zellij:real-session-launch:base'] }),
40
+ task('zellij:screen-proof:base', 'zellij:screen-proof', { group: 'environment_required', phase: 'parallel_verification', args: ['--require-real', '--main-only', '--mission', 'M-release-real-zellij'], env: { SKS_REQUIRE_ZELLIJ: '1' }, deps: ['zellij:real-session-launch:base'] }),
41
+ task('zellij:real-session-cleanup:base', 'zellij:real-session-cleanup', { group: 'environment_required', phase: 'aggregation', args: ['--mission', 'M-release-real-zellij', '--session', 'sks-rrz'], env: { SKS_REQUIRE_ZELLIJ: '1' }, deps: ['zellij:pane-proof:base', 'zellij:screen-proof:base'] }),
42
+ task('zellij:first-slot-down-stack:real', 'zellij:first-slot-down-stack:real', { group: 'real_ui', phase: 'parallel_verification', args: ['--require-real'], env: { SKS_REQUIRE_ZELLIJ: '1' }, deps: ['zellij:layout-valid'] }),
43
+ task('zellij:right-column-real-geometry', 'zellij:right-column-real-geometry', { group: 'real_ui', phase: 'parallel_verification', args: ['--require-real'], env: { SKS_REQUIRE_ZELLIJ: '1' }, deps: ['zellij:layout-valid'] }),
44
+ task('naruto:zellij-dynamic-right-column', 'naruto:zellij-dynamic-right-column', { group: 'real_ui', phase: 'parallel_verification', args: ['--require-real'], env: { SKS_REQUIRE_ZELLIJ: '1' }, deps: ['zellij:layout-valid'] }),
45
+ task('zellij:worker-pane-real-ui:blackbox', 'zellij:worker-pane-real-ui:blackbox', { group: 'real_ui', phase: 'parallel_verification', args: ['--require-real'], env: { SKS_REQUIRE_ZELLIJ: '1' }, deps: ['zellij:layout-valid'] }),
46
+ task('zellij:real-session-launch:extra', 'zellij:real-session-launch', { group: 'real_ui', phase: 'parallel_verification', args: ['--require-real', '--main-only', '--mission', 'M-release-real-zellij-extra', '--session', 'sks-rrz-extra'], env: { SKS_REQUIRE_ZELLIJ: '1' }, deps: ['zellij:layout-valid'] }),
47
+ task('zellij:pane-proof:extra', 'zellij:pane-proof', { group: 'real_ui', phase: 'parallel_verification', args: ['--require-real', '--mission', 'M-release-real-zellij-extra', '--session', 'sks-rrz-extra', '--expected-lanes', '0'], env: { SKS_REQUIRE_ZELLIJ: '1' }, deps: ['zellij:real-session-launch:extra'] }),
48
+ task('zellij:screen-proof:extra', 'zellij:screen-proof', { group: 'real_ui', phase: 'parallel_verification', args: ['--require-real', '--main-only', '--mission', 'M-release-real-zellij-extra'], env: { SKS_REQUIRE_ZELLIJ: '1' }, deps: ['zellij:real-session-launch:extra'] }),
49
+ task('zellij:real-session-cleanup:extra', 'zellij:real-session-cleanup', { group: 'real_ui', phase: 'aggregation', args: ['--mission', 'M-release-real-zellij-extra', '--session', 'sks-rrz-extra'], env: { SKS_REQUIRE_ZELLIJ: '1' }, deps: ['zellij:pane-proof:extra', 'zellij:screen-proof:extra'] }),
50
+ task('naruto:worktree-coding:blackbox', 'naruto:worktree-coding:blackbox', { group: 'real_smoke', phase: 'parallel_processing', args: ['--require-real'], env: { SKS_REQUIRE_GIT_WORKTREE: '1' } }),
51
+ task('codex-control:real-smoke', 'codex-control:real-smoke', { group: 'real_smoke', phase: 'parallel_processing', args: ['--require-real'] }),
52
+ task('codex-sdk:real-smoke', 'codex-sdk:real-smoke', { group: 'real_smoke', phase: 'parallel_processing', args: ['--require-real'] }),
53
+ task('local-llm:smoke', 'local-llm:smoke', { group: 'real_smoke', phase: 'parallel_processing', args: ['--require-real'], env: { SKS_REQUIRE_LOCAL_LLM: '1' } }),
54
+ task('local-llm:throughput', 'local-llm:throughput', { group: 'real_smoke', phase: 'parallel_verification', env: { SKS_REQUIRE_LOCAL_LLM: '1' }, deps: ['local-llm:smoke'] }),
55
+ task('local-llm:cache-performance', 'local-llm:cache-performance', { group: 'real_smoke', phase: 'parallel_verification', env: { SKS_REQUIRE_LOCAL_LLM: '1' }, deps: ['local-llm:smoke'] }),
56
+ task('python-sdk:real-smoke', 'python-sdk:real-smoke', {
57
+ group: 'real_smoke',
58
+ phase: 'parallel_verification',
59
+ env: { SKS_REQUIRE_PYTHON_CODEX_SDK: '1', SKS_PYTHON_CODEX_SDK_TIMEOUT_MS: '240000' },
60
+ deps: ['codex-sdk:real-smoke', 'codex-control:real-smoke', 'agent:real-codex-in-zellij-worker-pane'],
61
+ retries: 2,
62
+ retryDelayMs: 1500
63
+ }),
64
+ task('codex:0.134-runner-truth', 'codex:0.134-runner-truth', { group: 'real_smoke', phase: 'parallel_processing' }),
65
+ task('agent:real-codex-patch-envelope-smoke', 'agent:real-codex-patch-envelope-smoke', { group: 'real_smoke', phase: 'parallel_processing' }),
66
+ task('agent:real-codex-parallel-workers', 'agent:real-codex-parallel-workers', { group: 'real_smoke', phase: 'parallel_processing' }),
67
+ task('agent:real-codex-parallel-workers-5', 'agent:real-codex-parallel-workers-5', { group: 'real_smoke', phase: 'parallel_processing' }),
68
+ task('agent:real-codex-parallel-workers-10', 'agent:real-codex-parallel-workers-10', { group: 'real_smoke', phase: 'parallel_processing' }),
69
+ task('agent:real-codex-parallel-workers-20', 'agent:real-codex-parallel-workers-20', { group: 'real_smoke', phase: 'parallel_processing' }),
70
+ task('agent:real-codex-dynamic-smoke-v2', 'agent:real-codex-dynamic-smoke-v2', { group: 'real_smoke', phase: 'parallel_processing' }),
71
+ task('agent:real-codex-dynamic-smoke', 'agent:real-codex-dynamic-smoke', { group: 'real_smoke', phase: 'parallel_processing' }),
72
+ task('agent:real-codex-in-zellij-worker-pane', 'agent:real-codex-in-zellij-worker-pane', { group: 'real_ui', phase: 'parallel_verification', args: ['--require-real'], deps: ['zellij:layout-valid'] }),
73
+ task('imagegen:real-smoke', 'imagegen:real-smoke', { group: 'real_smoke', phase: 'parallel_processing' }),
74
+ task('ux-review:real-imagegen-smoke', 'ux-review:real-imagegen-smoke', { group: 'real_smoke', phase: 'parallel_processing' }),
75
+ task('ppt:real-imagegen-smoke', 'ppt:real-imagegen-smoke', { group: 'real_smoke', phase: 'parallel_processing' }),
76
+ task('naruto:real-local-gpt-final-smoke', 'naruto:real-local-gpt-final-smoke', { group: 'real_smoke', phase: 'parallel_verification', env: { SKS_REQUIRE_LOCAL_LLM: '1', SKS_REQUIRE_GPT_FINAL: '1' }, deps: ['local-llm:smoke'] }),
77
+ task('local-collab:gpt-final-performance', 'local-collab:gpt-final-performance', { group: 'real_smoke', phase: 'parallel_verification', env: { SKS_REQUIRE_LOCAL_LLM: '1', SKS_REQUIRE_GPT_FINAL: '1' }, deps: ['local-llm:smoke'] })
78
+ ];
79
+ main().catch(async (err) => {
80
+ report.blockers.push(`release_real_check_exception:${err?.message || String(err)}`);
81
+ await finish(false);
82
+ });
83
+ async function main() {
84
+ if (!skipReleaseCheck) {
85
+ report.release_check = await runNpm(task('release:check', 'release:check', { group: 'design', phase: 'design' }));
86
+ collect(report.release_check);
87
+ if (!report.release_check.ok)
88
+ return await finish(false);
89
+ }
90
+ else {
91
+ report.release_check = {
92
+ id: 'release:check',
93
+ script: 'release:check',
94
+ group: 'design',
95
+ phase: 'design',
96
+ ok: true,
97
+ skipped: true,
98
+ note: 'Skipped because caller already verified release:check in this workspace.'
99
+ };
100
+ }
101
+ const result = await runDag(tasks, concurrency);
102
+ report.all_checks = result.results;
103
+ report.environment_required_checks = result.results.filter((row) => row.group === 'environment_required');
104
+ report.real_smoke_checks = result.results.filter((row) => row.group === 'real_smoke');
105
+ report.real_ui_checks = result.results.filter((row) => row.group === 'real_ui');
106
+ report.phase_results = summarizePhases(result.results);
107
+ for (const row of result.results)
108
+ collect(row);
109
+ await finish(result.results.every((row) => row.ok));
110
+ }
111
+ function task(id, script, options = {}) {
112
+ return {
113
+ id,
114
+ script,
115
+ group: options.group || 'real_smoke',
116
+ phase: options.phase || 'parallel_processing',
117
+ args: options.args || [],
118
+ env: options.env || {},
119
+ deps: options.deps || [],
120
+ retries: Number(options.retries || 0),
121
+ retryDelayMs: Number(options.retryDelayMs || 0)
29
122
  };
30
123
  }
31
- for (const [script, extraArgs] of [
32
- ['codex:actual-config-load-probe', []],
33
- ['codex:0.137-compat:require-real', []],
34
- ['codex:0.136-compat:require-real', []],
35
- ['codex:0.135-compat:require-real', []],
36
- ['doctor:codex-doctor-parity:actual', []],
37
- ['publish:dry-run-performance', []],
38
- ['zellij:capability', ['--require-real']],
39
- ['zellij:layout-valid', ['--require-real']],
40
- ['zellij:real-session-launch', ['--require-real', '--main-only', '--mission', 'M-release-real-zellij', '--session', 'sks-rrz']],
41
- ['zellij:pane-proof', ['--require-real', '--mission', 'M-release-real-zellij', '--session', 'sks-rrz', '--expected-lanes', '0']],
42
- ['zellij:screen-proof', ['--require-real', '--main-only', '--mission', 'M-release-real-zellij']],
43
- ['zellij:real-session-cleanup', ['--mission', 'M-release-real-zellij', '--session', 'sks-rrz']]
44
- ]) {
45
- const result = runNpm(script, extraArgs);
46
- report.environment_required_checks.push(result);
47
- collect(result);
48
- }
49
- if (report.environment_required_checks.some((row) => !row.ok))
50
- finish(false);
51
- for (const [script, extraArgs] of [
52
- ['codex-sdk:real-smoke', ['--require-real']],
53
- ['local-llm:smoke', ['--require-real']],
54
- ['local-llm:throughput', []],
55
- ['local-llm:cache-performance', []],
56
- ['python-sdk:real-smoke', []],
57
- ['codex:0.134-runner-truth', []],
58
- ['agent:real-codex-patch-envelope-smoke', []],
59
- ['agent:real-codex-parallel-workers', []],
60
- ['agent:real-codex-parallel-workers-5', []],
61
- ['agent:real-codex-parallel-workers-10', []],
62
- ['agent:real-codex-parallel-workers-20', []],
63
- ['agent:real-codex-dynamic-smoke-v2', []],
64
- ['agent:real-codex-dynamic-smoke', []],
65
- ['imagegen:real-smoke', []],
66
- ['ux-review:real-imagegen-smoke', []],
67
- ['ppt:real-imagegen-smoke', []]
68
- ]) {
69
- const result = runNpm(script, extraArgs);
70
- report.real_smoke_checks.push(result);
71
- collect(result);
72
- }
73
- finish(report.real_smoke_checks.every((row) => row.ok));
74
- function runNpm(script, extraArgs = []) {
75
- const npmArgs = ['run', script, '--silent'];
76
- if (extraArgs.length)
77
- npmArgs.push('--', ...extraArgs);
78
- const result = spawnSync('npm', npmArgs, {
79
- cwd: root,
80
- env: process.env,
81
- encoding: 'utf8',
82
- maxBuffer: 50 * 1024 * 1024
124
+ async function runDag(taskList, maxConcurrency) {
125
+ const pending = new Map(taskList.map((row) => [row.id, row]));
126
+ const running = new Map();
127
+ const completed = new Map();
128
+ const results = [];
129
+ while (pending.size || running.size) {
130
+ for (const [id, row] of [...pending]) {
131
+ const failedDeps = row.deps.filter((dep) => completed.has(dep) && !completed.get(dep).ok);
132
+ if (failedDeps.length) {
133
+ pending.delete(id);
134
+ const blocked = blockedResult(row, failedDeps);
135
+ completed.set(id, blocked);
136
+ results.push(blocked);
137
+ }
138
+ }
139
+ const ready = [...pending.values()].filter((row) => row.deps.every((dep) => completed.get(dep)?.ok === true));
140
+ while (running.size < maxConcurrency && ready.length) {
141
+ const row = ready.shift();
142
+ pending.delete(row.id);
143
+ const promise = runNpm(row);
144
+ running.set(row.id, promise);
145
+ }
146
+ if (!running.size) {
147
+ if (pending.size) {
148
+ for (const row of pending.values()) {
149
+ const blocked = blockedResult(row, row.deps.filter((dep) => !completed.get(dep)?.ok));
150
+ completed.set(row.id, blocked);
151
+ results.push(blocked);
152
+ }
153
+ pending.clear();
154
+ }
155
+ continue;
156
+ }
157
+ const result = await Promise.race([...running.values()]);
158
+ running.delete(result.id);
159
+ completed.set(result.id, result);
160
+ results.push(result);
161
+ }
162
+ return { results };
163
+ }
164
+ async function runNpm(row) {
165
+ const maxAttempts = Math.max(1, Number(row.retries || 0) + 1);
166
+ const attempts = [];
167
+ for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
168
+ const result = await runNpmOnce(row, attempt);
169
+ attempts.push(compactAttempt(result));
170
+ if (result.ok || attempt >= maxAttempts) {
171
+ return {
172
+ ...result,
173
+ attempt,
174
+ attempts,
175
+ retried: attempts.length > 1
176
+ };
177
+ }
178
+ await sleep(Math.max(0, Number(row.retryDelayMs || 0)));
179
+ }
180
+ }
181
+ function runNpmOnce(row, attempt) {
182
+ const npmArgs = ['run', row.script, '--silent'];
183
+ if (row.args?.length)
184
+ npmArgs.push('--', ...row.args);
185
+ const started = Date.now();
186
+ let stdout = '';
187
+ let stderr = '';
188
+ return new Promise((resolve) => {
189
+ const child = spawn('npm', npmArgs, {
190
+ cwd: root,
191
+ env: { ...process.env, ...(row.env || {}) },
192
+ stdio: ['ignore', 'pipe', 'pipe']
193
+ });
194
+ child.stdout.on('data', (chunk) => { stdout = appendTail(stdout, chunk); });
195
+ child.stderr.on('data', (chunk) => { stderr = appendTail(stderr, chunk); });
196
+ child.on('error', (err) => {
197
+ resolve(normalizeResult(row, npmArgs, 1, null, { code: err.code, message: err.message }, stdout, stderr, Date.now() - started, attempt));
198
+ });
199
+ child.on('close', (code, signal) => {
200
+ resolve(normalizeResult(row, npmArgs, code, signal, null, stdout, stderr, Date.now() - started, attempt));
201
+ });
83
202
  });
84
- const parsed = parseJson(result.stdout);
203
+ }
204
+ function normalizeResult(row, npmArgs, code, signal, error, stdout, stderr, durationMs, attempt) {
205
+ const parsed = parseJson(stdout);
85
206
  return {
86
- id: script,
207
+ id: row.id,
208
+ script: row.script,
209
+ group: row.group,
210
+ phase: row.phase,
211
+ deps: row.deps || [],
87
212
  command: ['npm', ...npmArgs],
88
- ok: result.status === 0,
89
- exit_code: result.status,
90
- signal: result.signal,
91
- error: result.error ? { code: result.error.code, message: result.error.message } : null,
213
+ ok: code === 0,
214
+ attempt,
215
+ exit_code: code,
216
+ signal,
217
+ duration_ms: durationMs,
218
+ error,
92
219
  parsed_schema: parsed?.schema || null,
93
220
  parsed_ok: typeof parsed?.ok === 'boolean' ? parsed.ok : null,
94
221
  blockers: extractList(parsed, 'blockers'),
95
222
  warnings: extractList(parsed, 'warnings'),
96
- stdout_tail: tail(result.stdout),
97
- stderr_tail: tail(result.stderr)
223
+ stdout_tail: tail(stdout),
224
+ stderr_tail: tail(stderr)
225
+ };
226
+ }
227
+ function compactAttempt(result) {
228
+ return {
229
+ attempt: result.attempt,
230
+ ok: result.ok,
231
+ exit_code: result.exit_code,
232
+ duration_ms: result.duration_ms,
233
+ blockers: result.blockers || [],
234
+ stderr_tail: tail(result.stderr_tail || '', 600)
235
+ };
236
+ }
237
+ function sleep(ms) {
238
+ return new Promise((resolve) => setTimeout(resolve, ms));
239
+ }
240
+ function blockedResult(row, failedDeps) {
241
+ return {
242
+ id: row.id,
243
+ script: row.script,
244
+ group: row.group,
245
+ phase: row.phase,
246
+ deps: row.deps || [],
247
+ command: ['npm', 'run', row.script, '--silent'],
248
+ ok: false,
249
+ blocked: true,
250
+ exit_code: null,
251
+ signal: null,
252
+ duration_ms: 0,
253
+ error: null,
254
+ parsed_schema: null,
255
+ parsed_ok: null,
256
+ blockers: failedDeps.map((dep) => `blocked_by_failed_dependency:${dep}`),
257
+ warnings: [],
258
+ stdout_tail: '',
259
+ stderr_tail: `blocked by failed dependency: ${failedDeps.join(', ')}`
98
260
  };
99
261
  }
100
262
  function collect(result) {
@@ -112,19 +274,34 @@ function collect(result) {
112
274
  report.warnings.push(warning);
113
275
  }
114
276
  }
115
- function finish(ok) {
277
+ function summarizePhases(results) {
278
+ return ['design', 'parallel_processing', 'parallel_verification', 'aggregation'].map((phase) => {
279
+ const rows = phase === 'design' ? [report.release_check].filter(Boolean) : results.filter((row) => row.phase === phase);
280
+ return {
281
+ phase,
282
+ total: rows.length,
283
+ passed: rows.filter((row) => row.ok).length,
284
+ failed: rows.filter((row) => !row.ok).length,
285
+ duration_ms: rows.reduce((sum, row) => sum + Number(row.duration_ms || 0), 0)
286
+ };
287
+ });
288
+ }
289
+ async function finish(ok) {
116
290
  report.ok = ok && report.blockers.length === 0;
291
+ await writeJsonAtomic(path.join(root, '.sneakoscope', 'reports', 'release-real-check.json'), report);
117
292
  console.log(JSON.stringify(report, null, 2));
118
293
  if (!report.ok)
119
294
  process.exitCode = 1;
120
- process.exit();
121
295
  }
122
296
  function parseJson(text) {
123
297
  const value = String(text || '').trim();
124
- if (!value.startsWith('{'))
298
+ if (!value)
299
+ return null;
300
+ const start = value.indexOf('{');
301
+ if (start < 0)
125
302
  return null;
126
303
  try {
127
- return JSON.parse(value);
304
+ return JSON.parse(value.slice(start));
128
305
  }
129
306
  catch {
130
307
  return null;
@@ -142,6 +319,10 @@ function extractList(parsed, key) {
142
319
  }
143
320
  return [...new Set(values)];
144
321
  }
322
+ function appendTail(previous, chunk, limit = 50 * 1024) {
323
+ const text = previous + String(chunk || '');
324
+ return text.length <= limit ? text : text.slice(-limit);
325
+ }
145
326
  function tail(value, limit = 4000) {
146
327
  const text = String(value || '');
147
328
  return text.length <= limit ? text : text.slice(-limit);
@@ -0,0 +1,86 @@
1
+ #!/usr/bin/env node
2
+ // @ts-nocheck
3
+ import { assertGate, emitGate, readText } from './lib/codex-sdk-gate-lib.js';
4
+ const mode = process.argv[2] || 'all';
5
+ const checks = {
6
+ 'quality-contract': () => {
7
+ assertFileIncludes('src/core/research/research-quality-contract.ts', [
8
+ 'min_sources_total: 12',
9
+ 'min_source_layers_covered: 5',
10
+ 'min_counterevidence_sources: 2',
11
+ 'min_trianguled_claims: 6',
12
+ 'min_key_claims: 8',
13
+ 'min_report_words: 2200'
14
+ ]);
15
+ assertFileIncludes('src/core/research.ts', ['quality_contract', 'writeResearchQualityContract', 'research_report_too_short']);
16
+ },
17
+ 'claim-matrix': () => {
18
+ assertFileIncludes('src/core/research/claim-evidence-matrix.ts', ['CLAIM_EVIDENCE_MATRIX_ARTIFACT', 'validateClaimEvidenceMatrix', 'buildClaimEvidenceMatrixFromLedgers']);
19
+ assertFileIncludes('src/core/research.ts', ['claim_evidence_matrix_missing', 'key_claims_below_contract', 'triangulated_claims_below_contract']);
20
+ },
21
+ 'source-quality-report': () => {
22
+ assertFileIncludes('src/core/research/source-quality-report.ts', ['SOURCE_QUALITY_REPORT_ARTIFACT', 'buildSourceQualityReport', 'claim_ids']);
23
+ assertFileIncludes('src/core/research.ts', ['source_quality_report_missing', 'writeSourceQualityReport']);
24
+ },
25
+ 'implementation-blueprint': () => {
26
+ assertFileIncludes('src/core/research/implementation-blueprint.ts', ['IMPLEMENTATION_BLUEPRINT_ARTIFACT', 'validateImplementationBlueprint']);
27
+ assertFileIncludes('src/core/research.ts', ['implementation_blueprint_missing', 'renderImplementationBlueprintMarkdown']);
28
+ },
29
+ 'experiment-plan': () => {
30
+ assertFileIncludes('src/core/research/experiment-plan.ts', ['EXPERIMENT_PLAN_JSON_ARTIFACT', 'min_experiment_steps', 'validateExperimentPlan']);
31
+ assertFileIncludes('src/core/research/experiment-plan.ts', ['experiment_plan_missing', 'experiment_plan_too_thin']);
32
+ assertFileIncludes('src/core/research.ts', ['experiment_plan_missing', 'validateExperimentPlan']);
33
+ },
34
+ 'replication-pack': () => {
35
+ assertFileIncludes('src/core/research/replication-pack.ts', ['REPLICATION_PACK_ARTIFACT', 'validateReplicationPack']);
36
+ assertFileIncludes('src/core/research.ts', ['replication_pack_missing']);
37
+ },
38
+ 'final-reviewer': () => {
39
+ assertFileIncludes('src/core/research/research-final-reviewer.ts', ['RESEARCH_FINAL_REVIEW_ARTIFACT', 'approved', 'runResearchFinalReviewer']);
40
+ assertFileIncludes('src/core/research.ts', ['research_final_review_not_approved']);
41
+ },
42
+ 'work-graph': () => {
43
+ assertFileIncludes('src/core/research/research-work-graph.ts', ['RESEARCH_WORK_GRAPH_ARTIFACT', 'buildResearchWorkGraph', 'sks.naruto-work-graph.v1']);
44
+ assertFileIncludes('src/core/commands/research-command.ts', ['narutoWorkGraph: researchWorkGraph', 'readonly: true', 'runResearchCycle']);
45
+ },
46
+ 'prompt-contract': () => {
47
+ assertFileIncludes('src/core/research/research-prompt-contract.ts', ['researchPromptContractText', 'validateResearchPromptContract']);
48
+ assertFileIncludes('src/core/research.ts', ['QUALITY CONTRACT:', 'researchPromptContractText()']);
49
+ },
50
+ 'gate-thresholds': () => {
51
+ assertFileIncludes('src/core/research.ts', [
52
+ 'source_entries_below_research_quality_contract',
53
+ 'source_layer_coverage_below_contract',
54
+ 'counterevidence_below_contract',
55
+ 'required_artifact_missing'
56
+ ]);
57
+ assertFileIncludes('src/core/research/falsification.ts', ['falsification_cases_below_contract']);
58
+ },
59
+ 'schemas': () => {
60
+ for (const file of [
61
+ 'schemas/research/research-quality-contract.schema.json',
62
+ 'schemas/research/claim-evidence-matrix.schema.json',
63
+ 'schemas/research/source-quality-report.schema.json',
64
+ 'schemas/research/implementation-blueprint.schema.json',
65
+ 'schemas/research/experiment-plan.schema.json',
66
+ 'schemas/research/replication-pack.schema.json',
67
+ 'schemas/research/research-final-review.schema.json'
68
+ ])
69
+ assertGate(readText(file).includes('"$schema"'), `${file} missing JSON Schema header`);
70
+ }
71
+ };
72
+ if (mode === 'all') {
73
+ for (const check of Object.values(checks))
74
+ check();
75
+ }
76
+ else {
77
+ assertGate(Boolean(checks[mode]), `unknown research quality check: ${mode}`);
78
+ checks[mode]();
79
+ }
80
+ emitGate(`research:${mode}`, { mode });
81
+ function assertFileIncludes(file, tokens) {
82
+ const text = readText(file);
83
+ for (const token of tokens)
84
+ assertGate(text.includes(token), `${file} missing token ${token}`);
85
+ }
86
+ //# sourceMappingURL=research-quality-gate-check.js.map
@@ -10,7 +10,7 @@ const checks = {
10
10
  command_registered: registry.includes("'zellij-slot-column-anchor'"),
11
11
  anchor_command_used: worker.includes('buildZellijSlotColumnAnchorCommand'),
12
12
  anchor_created_right: worker.includes("'--direction', 'right', '--name', 'SLOTS'"),
13
- worker_down_only_for_right_column: worker.includes("const directionRequested: 'right' | 'down' = rightColumn ? 'down' : 'right'"),
13
+ worker_down_only_for_right_column: worker.includes("const directionRequested: 'right' | 'down' = 'down'"),
14
14
  legacy_first_worker_right_removed: !worker.includes("rightColumn?.focusPaneId ? 'down' : 'right'"),
15
15
  worker_direction_fields: worker.includes('worker_direction_requested') && worker.includes('worker_direction_applied'),
16
16
  state_anchor_field: rightColumn.includes('slot_column_anchor_pane_id')