sneakoscope 4.0.0 → 4.0.1
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 +2 -2
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/crates/sks-core/src/main.rs +1 -1
- package/dist/bin/sks.js +1 -1
- package/dist/core/build/build-once-runner.js +5 -1
- package/dist/core/commands/check-command.js +3 -1
- package/dist/core/commands/mad-sks-command.js +7 -2
- package/dist/core/daemon/sksd-ipc.js +9 -0
- package/dist/core/daemon/sksd.js +37 -5
- package/dist/core/doctor/doctor-dirty-planner.js +70 -5
- package/dist/core/fsx.js +1 -1
- package/dist/core/probes/probe-memoization.js +40 -2
- package/dist/core/release/critical-path-ledger.js +12 -0
- package/dist/core/release/extreme-parallel-scheduler.js +53 -0
- package/dist/core/release/gate-pack-fixture-cache.js +39 -0
- package/dist/core/release/gate-pack-runner.js +145 -1
- package/dist/core/release/release-gate-cache-v2.js +6 -1
- package/dist/core/release/release-gate-dag.js +9 -2
- package/dist/core/triwiki/triwiki-affected-graph.js +63 -7
- package/dist/core/triwiki/triwiki-cache-key.js +27 -7
- package/dist/core/triwiki/triwiki-gate-impact-map.js +47 -2
- package/dist/core/triwiki/triwiki-invalidation.js +81 -0
- package/dist/core/triwiki/triwiki-module-card.js +48 -11
- package/dist/core/triwiki/triwiki-proof-bank.js +82 -4
- package/dist/core/triwiki/triwiki-proof-card.js +34 -3
- package/dist/core/triwiki/triwiki-sla-certificate.js +25 -2
- package/dist/core/version.js +1 -1
- package/dist/core/zellij/zellij-launcher.js +13 -0
- package/dist/core/zellij/zellij-worker-pane-manager.js +68 -17
- package/dist/scripts/release-4001-required-gates.js +13 -0
- package/dist/scripts/sizecheck.js +4 -2
- package/package.json +11 -2
|
@@ -1,15 +1,32 @@
|
|
|
1
1
|
export const TRIWIKI_MODULE_CARD_SCHEMA = 'sks.triwiki-module-card.v1';
|
|
2
2
|
export const DEFAULT_TRIWIKI_MODULE_CARDS = [
|
|
3
3
|
moduleCard('triwiki', ['src/core/triwiki/**', 'src/scripts/triwiki-*.ts'], ['triwiki:'], ['triwiki'], 'high'),
|
|
4
|
-
moduleCard('release', ['
|
|
5
|
-
moduleCard('
|
|
6
|
-
moduleCard('
|
|
7
|
-
moduleCard('
|
|
8
|
-
moduleCard('
|
|
9
|
-
moduleCard('
|
|
10
|
-
moduleCard('
|
|
11
|
-
moduleCard('
|
|
12
|
-
moduleCard('
|
|
4
|
+
moduleCard('release-parity', ['package.json', 'package-lock.json', 'release-gates.v2.json'], ['release:'], ['release-parity'], 'high'),
|
|
5
|
+
moduleCard('release-dag', ['src/core/release/release-gate-*.ts', 'src/scripts/release-*.ts'], ['release:'], ['release-parity'], 'high'),
|
|
6
|
+
moduleCard('triwiki-proof-bank', ['src/core/triwiki/triwiki-proof-*.ts', 'src/core/triwiki/triwiki-cache-key.ts', 'src/core/triwiki/triwiki-invalidation.ts', 'src/scripts/triwiki-proof-*.ts', 'src/scripts/triwiki-cache-*.ts', 'src/scripts/triwiki-stale-*.ts'], ['triwiki:proof', 'triwiki:cache', 'triwiki:stale'], ['triwiki'], 'high'),
|
|
7
|
+
moduleCard('triwiki-affected-graph', ['src/core/triwiki/triwiki-module-card.ts', 'src/core/triwiki/triwiki-gate-impact-map.ts', 'src/core/triwiki/triwiki-affected-graph.ts', 'src/scripts/triwiki-affected-*.ts', 'src/scripts/triwiki-module-*.ts'], ['triwiki:affected', 'triwiki:module', 'triwiki:gate-impact'], ['triwiki'], 'high'),
|
|
8
|
+
moduleCard('gate-pack-runner', ['src/core/release/gate-pack-*.ts', 'src/scripts/gate-pack-*.ts'], ['gate-pack:'], ['release-parity'], 'high'),
|
|
9
|
+
moduleCard('extreme-scheduler', ['src/core/release/*scheduler.ts', 'src/core/release/resource-class-budget.ts', 'src/core/release/critical-path-ledger.ts', 'src/scripts/scheduler-*.ts'], ['scheduler:'], ['release-parity'], 'high'),
|
|
10
|
+
moduleCard('build-once', ['src/core/build/**', 'src/scripts/build-once-*.ts', 'tsconfig.json'], ['build-once:'], ['doctor-production'], 'medium'),
|
|
11
|
+
moduleCard('sksd-daemon', ['src/core/daemon/**', 'src/scripts/sksd-*.ts'], ['sksd:'], ['startup-mcp'], 'medium'),
|
|
12
|
+
moduleCard('probe-memoization', ['src/core/probes/**', 'src/scripts/probe-*.ts'], ['probes:'], ['startup-mcp'], 'medium'),
|
|
13
|
+
moduleCard('doctor-transaction', ['src/core/doctor/doctor-transaction.ts', 'src/commands/doctor.ts', 'src/scripts/doctor-transaction-*.ts'], ['doctor:transaction'], ['doctor-production'], 'high'),
|
|
14
|
+
moduleCard('doctor-dirty-repair', ['src/core/doctor/doctor-dirty-planner.ts', 'src/core/doctor/doctor-repair-postcheck.ts', 'src/scripts/doctor-dirty-*.ts'], ['doctor:dirty'], ['doctor-production'], 'high'),
|
|
15
|
+
moduleCard('startup-config-repair', ['src/core/doctor/*startup*.ts', 'src/scripts/doctor-startup-*.ts'], ['doctor:startup'], ['doctor-production'], 'high'),
|
|
16
|
+
moduleCard('context7-mcp', ['src/core/doctor/*context7*.ts', 'src/commands/context7.ts'], ['doctor:context7', 'context7:'], ['startup-mcp'], 'critical'),
|
|
17
|
+
moduleCard('supabase-mcp', ['src/core/doctor/*supabase*.ts', 'src/commands/db.ts'], ['doctor:supabase', 'db:'], ['startup-mcp'], 'critical'),
|
|
18
|
+
moduleCard('native-capability', ['src/core/codex-native/**', 'src/scripts/native-*.ts'], ['native:', 'codex-native:'], ['native-capability'], 'high'),
|
|
19
|
+
moduleCard('secret-preservation', ['src/core/**/secret*.ts', 'src/scripts/secret-*.ts', 'safety-mutation-allowlist.json'], ['secret:', 'supabase-secret'], ['doctor-production'], 'critical'),
|
|
20
|
+
moduleCard('core-skill', ['.agents/skills/**', 'src/scripts/core-skill-*.ts'], ['core-skill:'], ['core-skill'], 'high'),
|
|
21
|
+
moduleCard('skill-dedupe', ['src/scripts/skill-*.ts', '.sneakoscope/skills/**'], ['skill:'], ['skill-dedupe'], 'medium'),
|
|
22
|
+
moduleCard('zellij-runtime', ['src/core/zellij/**', 'src/commands/zellij*.ts', 'templates/zellij/**'], ['zellij:'], ['zellij'], 'high'),
|
|
23
|
+
moduleCard('codex-0140', ['src/scripts/codex-0140-*.ts', 'src/vendor/openai-codex/**'], ['codex:0140'], ['codex-0140'], 'medium'),
|
|
24
|
+
moduleCard('loop-mesh', ['src/core/loops/**', 'src/scripts/loop-*.ts'], ['loop:'], ['loop-mesh'], 'medium'),
|
|
25
|
+
moduleCard('qa-loop', ['src/commands/qa-loop.ts', 'src/scripts/qa-*.ts'], ['qa-', 'qa:'], ['qa-research-image'], 'medium'),
|
|
26
|
+
moduleCard('research', ['src/commands/research.ts', 'src/scripts/research-*.ts'], ['research:'], ['qa-research-image'], 'medium'),
|
|
27
|
+
moduleCard('image-path', ['src/commands/image-ux-review.ts', 'src/scripts/*image*.ts', 'src/scripts/ux-review-*.ts'], ['image:', 'ux-review:'], ['qa-research-image'], 'medium'),
|
|
28
|
+
moduleCard('legacy-purge', ['src/scripts/legacy-*.ts', 'src/scripts/orphan-*.ts', 'docs/sks-4-migration.md'], ['legacy:', 'orphan:'], ['zellij'], 'high'),
|
|
29
|
+
moduleCard('cli-check', ['src/core/commands/check-command.ts', 'src/commands/**/*.ts', 'src/cli/**'], ['cli:', 'sks:', 'check:'], ['native-capability'], 'high')
|
|
13
30
|
];
|
|
14
31
|
export function moduleCard(moduleId, paths, ownsGatePrefixes, gatePacks, risk) {
|
|
15
32
|
return {
|
|
@@ -18,7 +35,9 @@ export function moduleCard(moduleId, paths, ownsGatePrefixes, gatePacks, risk) {
|
|
|
18
35
|
paths,
|
|
19
36
|
owns_gate_prefixes: ownsGatePrefixes,
|
|
20
37
|
gate_packs: gatePacks,
|
|
21
|
-
risk
|
|
38
|
+
risk,
|
|
39
|
+
invariants: [`${moduleId}:release-equivalent-proof-required`],
|
|
40
|
+
required_proof_type: risk === 'critical' ? 'real-postcheck-plus-release-gate' : 'release-gate'
|
|
22
41
|
};
|
|
23
42
|
}
|
|
24
43
|
export function moduleIdsForPath(file, cards = DEFAULT_TRIWIKI_MODULE_CARDS) {
|
|
@@ -31,7 +50,25 @@ export function pathMatches(pattern, file) {
|
|
|
31
50
|
return file === pattern.slice(0, -3) || file.startsWith(pattern.slice(0, -2));
|
|
32
51
|
if (!pattern.includes('*'))
|
|
33
52
|
return file === pattern || file.startsWith(`${pattern}/`);
|
|
34
|
-
const re = new RegExp(`^${pattern
|
|
53
|
+
const re = new RegExp(`^${globToRegexSource(pattern)}$`);
|
|
35
54
|
return re.test(file);
|
|
36
55
|
}
|
|
56
|
+
function globToRegexSource(pattern) {
|
|
57
|
+
let out = '';
|
|
58
|
+
for (let i = 0; i < pattern.length; i += 1) {
|
|
59
|
+
const char = pattern[i];
|
|
60
|
+
if (char === '*') {
|
|
61
|
+
if (pattern[i + 1] === '*') {
|
|
62
|
+
out += '.*';
|
|
63
|
+
i += 1;
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
out += '[^/]*';
|
|
67
|
+
}
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
out += /[\\^$+?.()|{}[\]]/.test(char || '') ? `\\${char}` : char;
|
|
71
|
+
}
|
|
72
|
+
return out;
|
|
73
|
+
}
|
|
37
74
|
//# sourceMappingURL=triwiki-module-card.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import { TRIWIKI_PROOF_CARD_SCHEMA, isReusableTriWikiProofCard } from './triwiki-proof-card.js';
|
|
3
|
+
import { TRIWIKI_PROOF_CARD_SCHEMA, classifyTriWikiProofCardSchema, isReusableTriWikiProofCard } from './triwiki-proof-card.js';
|
|
4
4
|
export const TRIWIKI_PROOF_BANK_SCHEMA = 'sks.triwiki-proof-bank.v1';
|
|
5
5
|
export function triWikiProofBankDir(root) {
|
|
6
6
|
return path.join(root, '.sneakoscope', 'triwiki', 'proof-bank');
|
|
@@ -9,8 +9,10 @@ export function writeTriWikiProofCard(root, card, subjectType = pluralSubject(ca
|
|
|
9
9
|
const dir = path.join(triWikiProofBankDir(root), subjectType, safeId(card.subject_id));
|
|
10
10
|
fs.mkdirSync(dir, { recursive: true });
|
|
11
11
|
const file = path.join(dir, `${safeId(card.proof_id)}.json`);
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
return withSubjectLock(root, subjectType, card.subject_id, () => {
|
|
13
|
+
atomicWriteJson(file, card);
|
|
14
|
+
return file;
|
|
15
|
+
});
|
|
14
16
|
}
|
|
15
17
|
export function readReusableTriWikiProofCard(input) {
|
|
16
18
|
const dir = path.join(triWikiProofBankDir(input.root), input.subjectType || 'gates', safeId(input.subjectId));
|
|
@@ -25,6 +27,11 @@ export function readReusableTriWikiProofCard(input) {
|
|
|
25
27
|
reasons.push(`corrupt:${file}`);
|
|
26
28
|
continue;
|
|
27
29
|
}
|
|
30
|
+
const schemaClass = classifyTriWikiProofCardSchema(card);
|
|
31
|
+
if (schemaClass === 'legacy_proof_card_schema') {
|
|
32
|
+
reasons.push(`legacy_proof_card_schema:${file}`);
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
28
35
|
if (card.cache_key !== input.cacheKey) {
|
|
29
36
|
reasons.push(`cache_key_mismatch:${file}`);
|
|
30
37
|
continue;
|
|
@@ -45,7 +52,7 @@ export function markTriWikiProofInvalidated(root, subjectId, proofId, reason, su
|
|
|
45
52
|
reusable: false,
|
|
46
53
|
invalidation_reasons: [...new Set([...(card.invalidation_reasons || []), reason])]
|
|
47
54
|
};
|
|
48
|
-
|
|
55
|
+
atomicWriteJson(file, next);
|
|
49
56
|
return true;
|
|
50
57
|
}
|
|
51
58
|
export function summarizeTriWikiProofBank(root) {
|
|
@@ -100,6 +107,77 @@ function backupCorruptProof(file) {
|
|
|
100
107
|
const backup = `${file}.corrupt-${Date.now()}.bak`;
|
|
101
108
|
fs.renameSync(file, backup);
|
|
102
109
|
}
|
|
110
|
+
function atomicWriteJson(file, value) {
|
|
111
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
112
|
+
const temp = path.join(path.dirname(file), `.${path.basename(file)}.${process.pid}.${Date.now()}.tmp`);
|
|
113
|
+
const fd = fs.openSync(temp, 'w');
|
|
114
|
+
try {
|
|
115
|
+
fs.writeFileSync(fd, `${JSON.stringify(value, null, 2)}\n`);
|
|
116
|
+
try {
|
|
117
|
+
fs.fsyncSync(fd);
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
// fsync can be unavailable on some virtual filesystems; rename remains atomic.
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
finally {
|
|
124
|
+
fs.closeSync(fd);
|
|
125
|
+
}
|
|
126
|
+
fs.renameSync(temp, file);
|
|
127
|
+
}
|
|
128
|
+
function withSubjectLock(root, subjectType, subjectId, fn) {
|
|
129
|
+
const lockDir = path.join(triWikiProofBankDir(root), '.locks', subjectType);
|
|
130
|
+
fs.mkdirSync(lockDir, { recursive: true });
|
|
131
|
+
const lockFile = path.join(lockDir, `${safeId(subjectId)}.lock`);
|
|
132
|
+
const staleAfterMs = 30_000;
|
|
133
|
+
const started = Date.now();
|
|
134
|
+
while (true) {
|
|
135
|
+
try {
|
|
136
|
+
const fd = fs.openSync(lockFile, 'wx');
|
|
137
|
+
fs.writeFileSync(fd, `${JSON.stringify({ schema: 'sks.triwiki-proof-bank-lock.v1', pid: process.pid, acquired_at: new Date().toISOString(), stale_after_ms: staleAfterMs }, null, 2)}\n`);
|
|
138
|
+
fs.closeSync(fd);
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
catch (err) {
|
|
142
|
+
if (isLockStale(lockFile, staleAfterMs)) {
|
|
143
|
+
try {
|
|
144
|
+
fs.rmSync(lockFile, { force: true });
|
|
145
|
+
}
|
|
146
|
+
catch { }
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
if (Date.now() - started > staleAfterMs * 2)
|
|
150
|
+
throw err;
|
|
151
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 25);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
try {
|
|
155
|
+
return fn();
|
|
156
|
+
}
|
|
157
|
+
finally {
|
|
158
|
+
try {
|
|
159
|
+
fs.rmSync(lockFile, { force: true });
|
|
160
|
+
}
|
|
161
|
+
catch { }
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
function isLockStale(file, staleAfterMs) {
|
|
165
|
+
try {
|
|
166
|
+
const stat = fs.statSync(file);
|
|
167
|
+
const raw = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
168
|
+
const pidAlive = typeof raw.pid === 'number' && process.kill(raw.pid, 0) !== undefined;
|
|
169
|
+
return !pidAlive || Date.now() - stat.mtimeMs > staleAfterMs;
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
try {
|
|
173
|
+
const stat = fs.statSync(file);
|
|
174
|
+
return Date.now() - stat.mtimeMs > staleAfterMs;
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
return true;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
103
181
|
function walkJson(dir) {
|
|
104
182
|
const out = [];
|
|
105
183
|
const stack = [dir];
|
|
@@ -7,8 +7,13 @@ export function createTriWikiProofCard(input) {
|
|
|
7
7
|
subject_id: input.subject_id,
|
|
8
8
|
cache_key: input.cache_key,
|
|
9
9
|
input_hash: input.input_hash,
|
|
10
|
-
implementation_hash: input.implementation_hash,
|
|
11
|
-
|
|
10
|
+
implementation_hash: input.implementation_hash || input.gate_impl_hash || 'unknown',
|
|
11
|
+
gate_impl_hash: input.gate_impl_hash || input.implementation_hash || 'unknown',
|
|
12
|
+
package_lock_hash: input.package_lock_hash || 'legacy-missing',
|
|
13
|
+
release_gates_hash: input.release_gates_hash || 'legacy-missing',
|
|
14
|
+
env_allowlist_hash: input.env_allowlist_hash || 'legacy-missing',
|
|
15
|
+
tool_versions: input.tool_versions || (input.tool_version ? { sks: input.tool_version } : {}),
|
|
16
|
+
tool_version: input.tool_version || input.tool_versions?.sks || 'unknown',
|
|
12
17
|
fixture_version: input.fixture_version,
|
|
13
18
|
result: input.result,
|
|
14
19
|
reusable: input.reusable,
|
|
@@ -24,11 +29,24 @@ export function createTriWikiProofCard(input) {
|
|
|
24
29
|
};
|
|
25
30
|
}
|
|
26
31
|
export function proofIdFor(value) {
|
|
27
|
-
return `proof-${hashJson(
|
|
32
|
+
return `proof-${hashJson({
|
|
33
|
+
subject_type: value.subject_type,
|
|
34
|
+
subject_id: value.subject_id,
|
|
35
|
+
cache_key: value.cache_key,
|
|
36
|
+
input_hash: value.input_hash,
|
|
37
|
+
gate_impl_hash: value.gate_impl_hash || value.implementation_hash,
|
|
38
|
+
package_lock_hash: value.package_lock_hash,
|
|
39
|
+
release_gates_hash: value.release_gates_hash,
|
|
40
|
+
env_allowlist_hash: value.env_allowlist_hash,
|
|
41
|
+
tool_versions: value.tool_versions,
|
|
42
|
+
fixture_version: value.fixture_version
|
|
43
|
+
}).slice(0, 24)}`;
|
|
28
44
|
}
|
|
29
45
|
export function isReusableTriWikiProofCard(card, now = new Date()) {
|
|
30
46
|
if (card.schema !== TRIWIKI_PROOF_CARD_SCHEMA)
|
|
31
47
|
return false;
|
|
48
|
+
if (!hasV401InvalidationMaterial(card))
|
|
49
|
+
return false;
|
|
32
50
|
if (card.reusable !== true)
|
|
33
51
|
return false;
|
|
34
52
|
if (card.result !== 'passed')
|
|
@@ -39,4 +57,17 @@ export function isReusableTriWikiProofCard(card, now = new Date()) {
|
|
|
39
57
|
return false;
|
|
40
58
|
return true;
|
|
41
59
|
}
|
|
60
|
+
export function classifyTriWikiProofCardSchema(card) {
|
|
61
|
+
if (card.schema !== TRIWIKI_PROOF_CARD_SCHEMA)
|
|
62
|
+
return 'invalid';
|
|
63
|
+
return hasV401InvalidationMaterial(card) ? 'current' : 'legacy_proof_card_schema';
|
|
64
|
+
}
|
|
65
|
+
function hasV401InvalidationMaterial(card) {
|
|
66
|
+
return Boolean(card.gate_impl_hash &&
|
|
67
|
+
card.package_lock_hash &&
|
|
68
|
+
card.release_gates_hash &&
|
|
69
|
+
card.env_allowlist_hash &&
|
|
70
|
+
card.tool_versions &&
|
|
71
|
+
Object.keys(card.tool_versions).length > 0);
|
|
72
|
+
}
|
|
42
73
|
//# sourceMappingURL=triwiki-proof-card.js.map
|
|
@@ -4,9 +4,12 @@ export const TRIWIKI_SLA_CERTIFICATE_SCHEMA = 'sks.triwiki-sla-certificate.v1';
|
|
|
4
4
|
export function buildTriWikiSlaCertificate(input) {
|
|
5
5
|
const reductionRatio = input.estimatedSequentialMs <= 0 ? 1 : input.estimatedCriticalPathMs / input.estimatedSequentialMs;
|
|
6
6
|
const blockers = input.blockers || [];
|
|
7
|
+
const mode = input.mode || 'plan';
|
|
7
8
|
if (input.estimatedCriticalPathMs > input.slaMs)
|
|
8
9
|
blockers.push('sla_estimate_exceeds_budget');
|
|
9
|
-
|
|
10
|
+
if (mode === 'actual' && input.actualDurationMs === undefined)
|
|
11
|
+
blockers.push('actual_mode_missing_execution_stats');
|
|
12
|
+
const certificate = {
|
|
10
13
|
schema: TRIWIKI_SLA_CERTIFICATE_SCHEMA,
|
|
11
14
|
ok: blockers.length === 0,
|
|
12
15
|
created_at: new Date().toISOString(),
|
|
@@ -18,8 +21,28 @@ export function buildTriWikiSlaCertificate(input) {
|
|
|
18
21
|
release_equivalent_within_scope: input.graph.release_equivalent_within_scope,
|
|
19
22
|
gates: input.graph.gates.length,
|
|
20
23
|
gate_packs: input.graph.gate_packs,
|
|
21
|
-
blockers
|
|
24
|
+
blockers,
|
|
25
|
+
mode
|
|
22
26
|
};
|
|
27
|
+
if (input.actualDurationMs !== undefined)
|
|
28
|
+
certificate.actual_duration_ms = input.actualDurationMs;
|
|
29
|
+
if (input.executedGates !== undefined)
|
|
30
|
+
certificate.executed_gates = input.executedGates;
|
|
31
|
+
if (input.executedPacks !== undefined)
|
|
32
|
+
certificate.executed_packs = input.executedPacks;
|
|
33
|
+
if (input.reusedProofs !== undefined)
|
|
34
|
+
certificate.reused_proofs = input.reusedProofs;
|
|
35
|
+
if (input.invalidatedProofs !== undefined)
|
|
36
|
+
certificate.invalidated_proofs = input.invalidatedProofs;
|
|
37
|
+
if (input.newProofs !== undefined)
|
|
38
|
+
certificate.new_proofs = input.newProofs;
|
|
39
|
+
if (input.skippedAsValidCache !== undefined)
|
|
40
|
+
certificate.skipped_as_valid_cache = input.skippedAsValidCache;
|
|
41
|
+
if (input.skippedAsUnaffected !== undefined)
|
|
42
|
+
certificate.skipped_as_unaffected = input.skippedAsUnaffected;
|
|
43
|
+
if (input.backgroundFullRelease !== undefined)
|
|
44
|
+
certificate.background_full_release = input.backgroundFullRelease;
|
|
45
|
+
return certificate;
|
|
23
46
|
}
|
|
24
47
|
export function writeTriWikiSlaCertificate(root, certificate) {
|
|
25
48
|
const file = path.join(root, '.sneakoscope', 'reports', 'triwiki-sla-certificate.json');
|
package/dist/core/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const PACKAGE_VERSION = '4.0.
|
|
1
|
+
export const PACKAGE_VERSION = '4.0.1';
|
|
2
2
|
//# sourceMappingURL=version.js.map
|
|
@@ -37,6 +37,18 @@ export async function launchZellijLayout(opts = {}) {
|
|
|
37
37
|
const createCommand = ['attach', '--create-background', sessionName, 'options', '--default-layout', layout.layout_path, ...clipboard.optionFlags];
|
|
38
38
|
const attachCommand = ['attach', sessionName];
|
|
39
39
|
const zellijEnv = resolveZellijProcessEnvMeta();
|
|
40
|
+
// Reset a stale same-named session before recreating it so the launch starts
|
|
41
|
+
// main-only. `attach --create-background` is idempotent and otherwise reuses an
|
|
42
|
+
// existing session, causing each run to pile another right-split SLOTS column
|
|
43
|
+
// onto leftover panes from prior missions. Skipped on dry-run, when zellij is
|
|
44
|
+
// unavailable, or when the user opts out with SKS_ZELLIJ_KEEP_SESSION=1.
|
|
45
|
+
const resetSession = opts.freshSession === true
|
|
46
|
+
&& opts.dryRun !== true
|
|
47
|
+
&& capability.status === 'ok'
|
|
48
|
+
&& process.env.SKS_ZELLIJ_KEEP_SESSION !== '1';
|
|
49
|
+
const sessionReset = resetSession
|
|
50
|
+
? await runZellij(['kill-session', sessionName], { cwd: opts.cwd || root, timeoutMs: 5000, optional: true })
|
|
51
|
+
: null;
|
|
40
52
|
const launch = opts.dryRun === true || capability.status !== 'ok'
|
|
41
53
|
? null
|
|
42
54
|
: {
|
|
@@ -104,6 +116,7 @@ export async function launchZellijLayout(opts = {}) {
|
|
|
104
116
|
dry_run: opts.dryRun === true,
|
|
105
117
|
capability,
|
|
106
118
|
launch,
|
|
119
|
+
session_reset: sessionReset,
|
|
107
120
|
blockers,
|
|
108
121
|
warnings: [
|
|
109
122
|
...capability.warnings,
|
|
@@ -227,24 +227,19 @@ export async function openWorkerPane(input) {
|
|
|
227
227
|
let columnCreationDirectionRequested = null;
|
|
228
228
|
let columnCreationDirectionApplied = null;
|
|
229
229
|
if (rightColumn && !freshFocusCandidate) {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
});
|
|
238
|
-
anchorLaunch = createSession.ok
|
|
239
|
-
? await runZellij(['--session', input.sessionName, 'action', 'new-pane', '--direction', 'right', '--name', 'SLOTS', '--', 'sh', '-lc', anchorCommand], {
|
|
240
|
-
cwd,
|
|
241
|
-
timeoutMs: 5000,
|
|
242
|
-
optional: false
|
|
243
|
-
})
|
|
230
|
+
// Single right-column invariant: if this zellij session was reused (stable
|
|
231
|
+
// per-cwd name) and already carries a SLOTS anchor from a prior mission, adopt
|
|
232
|
+
// it and stack workers underneath instead of splitting ANOTHER `--direction
|
|
233
|
+
// right` column — repeated right-splits are exactly what fragments the screen
|
|
234
|
+
// into side-by-side columns. A fresh column is only split when none exists yet.
|
|
235
|
+
const adoptedAnchorPaneId = createSession.ok
|
|
236
|
+
? await findExistingSlotsAnchorPaneId(input.sessionName, cwd).catch(() => null)
|
|
244
237
|
: null;
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
238
|
+
if (adoptedAnchorPaneId) {
|
|
239
|
+
// Adopted an existing column: no creation was requested, so leave the
|
|
240
|
+
// column-creation direction fields null (avoids a false
|
|
241
|
+
// `zellij_worker_slot_column_anchor_not_created` blocker).
|
|
242
|
+
slotColumnAnchorPaneId = adoptedAnchorPaneId;
|
|
248
243
|
await recordSlotColumnAnchorInRightColumn({
|
|
249
244
|
root,
|
|
250
245
|
...(input.projectRoot ? { projectRoot: input.projectRoot } : {}),
|
|
@@ -253,6 +248,34 @@ export async function openWorkerPane(input) {
|
|
|
253
248
|
paneId: slotColumnAnchorPaneId
|
|
254
249
|
});
|
|
255
250
|
}
|
|
251
|
+
else {
|
|
252
|
+
columnCreationDirectionRequested = 'right';
|
|
253
|
+
const anchorCommand = buildZellijSlotColumnAnchorCommand({
|
|
254
|
+
cliPath: path.join(packageRoot(), 'dist', 'bin', 'sks.js'),
|
|
255
|
+
missionId: input.missionId,
|
|
256
|
+
mode: input.uiMode || 'compact-slots',
|
|
257
|
+
artifactRoot: root,
|
|
258
|
+
watch: true
|
|
259
|
+
});
|
|
260
|
+
anchorLaunch = createSession.ok
|
|
261
|
+
? await runZellij(['--session', input.sessionName, 'action', 'new-pane', '--direction', 'right', '--name', 'SLOTS', '--', 'sh', '-lc', anchorCommand], {
|
|
262
|
+
cwd,
|
|
263
|
+
timeoutMs: 5000,
|
|
264
|
+
optional: false
|
|
265
|
+
})
|
|
266
|
+
: null;
|
|
267
|
+
slotColumnAnchorPaneId = anchorLaunch?.ok ? extractZellijPaneIdFromOutput(anchorLaunch.stdout_tail) : null;
|
|
268
|
+
columnCreationDirectionApplied = anchorLaunch?.ok ? (slotColumnAnchorPaneId ? 'right' : 'unknown') : 'not_applied';
|
|
269
|
+
if (slotColumnAnchorPaneId) {
|
|
270
|
+
await recordSlotColumnAnchorInRightColumn({
|
|
271
|
+
root,
|
|
272
|
+
...(input.projectRoot ? { projectRoot: input.projectRoot } : {}),
|
|
273
|
+
missionId: input.missionId,
|
|
274
|
+
sessionName: input.sessionName,
|
|
275
|
+
paneId: slotColumnAnchorPaneId
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
}
|
|
256
279
|
}
|
|
257
280
|
const focusPaneId = lastVisibleWorkerPaneId || slotColumnAnchorPaneId || freshFocusCandidate || null;
|
|
258
281
|
const directionRequested = 'down';
|
|
@@ -595,6 +618,34 @@ async function reconcileZellijWorkerPaneId(sessionName, paneName, resultPath, cw
|
|
|
595
618
|
blockers: paneId == null ? ['zellij_worker_pane_id_not_reconciled'] : []
|
|
596
619
|
};
|
|
597
620
|
}
|
|
621
|
+
// Look up an already-open SLOTS anchor pane in a (possibly reused) session so a
|
|
622
|
+
// new mission can stack its workers under the existing right column instead of
|
|
623
|
+
// splitting another one. Returns the live pane id (terminal_<n>) or null.
|
|
624
|
+
async function findExistingSlotsAnchorPaneId(sessionName, cwd) {
|
|
625
|
+
const listed = await runZellij(['--session', sessionName, 'action', 'list-panes', '--json', '--all'], {
|
|
626
|
+
cwd,
|
|
627
|
+
timeoutMs: 5000,
|
|
628
|
+
optional: true
|
|
629
|
+
});
|
|
630
|
+
if (!listed.ok)
|
|
631
|
+
return null;
|
|
632
|
+
const rows = parsePaneRows(listed.stdout_tail);
|
|
633
|
+
const pane = rows.find((row) => {
|
|
634
|
+
if (row?.is_plugin === true)
|
|
635
|
+
return false;
|
|
636
|
+
const exited = row?.exited === true || row?.is_exited === true || row?.exit_status != null;
|
|
637
|
+
if (exited)
|
|
638
|
+
return false;
|
|
639
|
+
const title = String(row?.title || row?.name || row?.pane_name || '');
|
|
640
|
+
return title === 'SLOTS';
|
|
641
|
+
});
|
|
642
|
+
if (!pane)
|
|
643
|
+
return null;
|
|
644
|
+
const rawPaneId = pane.pane_id ?? pane.paneId;
|
|
645
|
+
if (rawPaneId != null && String(rawPaneId).trim())
|
|
646
|
+
return String(rawPaneId).trim();
|
|
647
|
+
return pane.id == null ? null : `terminal_${pane.id}`;
|
|
648
|
+
}
|
|
598
649
|
function normalizePaneProviderContext(context, serviceTier) {
|
|
599
650
|
const tier = normalizeServiceTier(serviceTier || context?.service_tier);
|
|
600
651
|
return context
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export const REQUIRED_4001_RELEASE_IDS = [
|
|
2
|
+
'triwiki:stale-proof-rejection',
|
|
3
|
+
'gate-pack:fixture-cache',
|
|
4
|
+
'release:triwiki-first-runner',
|
|
5
|
+
'release:cache-bridge',
|
|
6
|
+
'doctor:dirty-semantic',
|
|
7
|
+
'legacy:strong-inventory',
|
|
8
|
+
'orphan:strong-detection',
|
|
9
|
+
'sks:401-five-minute-actual-blackbox',
|
|
10
|
+
'sks:401-all-feature-regression'
|
|
11
|
+
];
|
|
12
|
+
export const REQUIRED_4001_REAL_CHECK_IDS = [];
|
|
13
|
+
//# sourceMappingURL=release-4001-required-gates.js.map
|
|
@@ -8,13 +8,15 @@ import { fileURLToPath } from 'node:url';
|
|
|
8
8
|
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..');
|
|
9
9
|
const limits = {
|
|
10
10
|
packedBytes: Number(process.env.SKS_MAX_PACK_BYTES || 1536 * 1024),
|
|
11
|
-
unpackedBytes: Number(process.env.SKS_MAX_UNPACKED_BYTES ||
|
|
11
|
+
unpackedBytes: Number(process.env.SKS_MAX_UNPACKED_BYTES || 6400 * 1024),
|
|
12
12
|
packFiles: Number(process.env.SKS_MAX_PACK_FILES || 1200),
|
|
13
13
|
trackedFileBytes: Number(process.env.SKS_MAX_TRACKED_FILE_BYTES || 384 * 1024)
|
|
14
14
|
};
|
|
15
15
|
const trackedFileSizeAllowlist = new Set([
|
|
16
16
|
// Historical source documentation export; not included in the npm package payload.
|
|
17
|
-
'docs/sks-local-llm-mode/exports/sks-local-llm-mode-deck.pdf'
|
|
17
|
+
'docs/sks-local-llm-mode/exports/sks-local-llm-mode-deck.pdf',
|
|
18
|
+
// Central release DAG manifest; package footprint limits still apply below.
|
|
19
|
+
'release-gates.v2.json'
|
|
18
20
|
]);
|
|
19
21
|
const npmBin = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
20
22
|
function fail(message, detail = '') {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sneakoscope",
|
|
3
3
|
"displayName": "ㅅㅋㅅ",
|
|
4
|
-
"version": "4.0.
|
|
4
|
+
"version": "4.0.1",
|
|
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",
|
|
@@ -994,7 +994,16 @@
|
|
|
994
994
|
"cli:check-tiers": "node ./dist/scripts/cli-check-tiers-check.js",
|
|
995
995
|
"cli:five-minute-task": "node ./dist/scripts/cli-five-minute-task-check.js",
|
|
996
996
|
"certificate:sla": "node ./dist/scripts/certificate-sla-check.js",
|
|
997
|
-
"sks:400-all-feature-regression": "node ./dist/scripts/sks-400-all-feature-regression-blackbox.js"
|
|
997
|
+
"sks:400-all-feature-regression": "node ./dist/scripts/sks-400-all-feature-regression-blackbox.js",
|
|
998
|
+
"triwiki:stale-proof-rejection": "node ./dist/scripts/triwiki-stale-proof-rejection-check.js",
|
|
999
|
+
"gate-pack:fixture-cache": "node ./dist/scripts/gate-pack-fixture-cache-check.js",
|
|
1000
|
+
"release:triwiki-first-runner": "node ./dist/scripts/release-triwiki-first-runner-check.js",
|
|
1001
|
+
"release:cache-bridge": "node ./dist/scripts/release-cache-bridge-check.js",
|
|
1002
|
+
"doctor:dirty-semantic": "node ./dist/scripts/doctor-dirty-semantic-check.js",
|
|
1003
|
+
"legacy:strong-inventory": "node ./dist/scripts/legacy-strong-inventory-check.js",
|
|
1004
|
+
"orphan:strong-detection": "node ./dist/scripts/orphan-strong-detection-check.js",
|
|
1005
|
+
"sks:401-five-minute-actual-blackbox": "node ./dist/scripts/sks-401-five-minute-actual-blackbox.js",
|
|
1006
|
+
"sks:401-all-feature-regression": "node ./dist/scripts/sks-401-all-feature-regression-blackbox.js"
|
|
998
1007
|
},
|
|
999
1008
|
"keywords": [
|
|
1000
1009
|
"sneakoscope",
|