sneakoscope 3.1.11 → 3.1.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 (49) hide show
  1. package/README.md +8 -7
  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/bin/sks.js +1 -1
  6. package/dist/commands/doctor.js +161 -2
  7. package/dist/core/agents/agent-role-config.js +12 -1
  8. package/dist/core/codex/agent-config-file-repair.js +157 -0
  9. package/dist/core/codex/codex-startup-config-postcheck.js +83 -0
  10. package/dist/core/codex-control/codex-0140-capability.js +136 -0
  11. package/dist/core/codex-control/codex-0140-feature-probes.js +195 -0
  12. package/dist/core/codex-control/codex-0140-probe-runner.js +5 -0
  13. package/dist/core/codex-control/codex-0140-real-probe-summary.js +12 -0
  14. package/dist/core/codex-control/codex-0140-real-probes.js +69 -0
  15. package/dist/core/codex-control/codex-0140-usage-parser.js +81 -0
  16. package/dist/core/codex-native/codex-native-feature-broker.js +15 -1
  17. package/dist/core/codex-native/native-capability-postcheck.js +5 -2
  18. package/dist/core/codex-native/native-capability-repair-matrix.js +4 -4
  19. package/dist/core/config/config-migration-journal.js +2 -0
  20. package/dist/core/config/secret-preservation.js +108 -11
  21. package/dist/core/config/supabase-secret-preservation.js +1 -0
  22. package/dist/core/doctor/codex-startup-config-repair.js +40 -0
  23. package/dist/core/doctor/context7-mcp-repair.js +77 -0
  24. package/dist/core/doctor/doctor-codex-startup-repair.js +127 -15
  25. package/dist/core/doctor/doctor-context7-repair.js +40 -1
  26. package/dist/core/doctor/doctor-repair-postcheck.js +17 -0
  27. package/dist/core/doctor/doctor-transaction.js +126 -0
  28. package/dist/core/doctor/supabase-mcp-repair.js +66 -0
  29. package/dist/core/fsx.js +1 -1
  30. package/dist/core/loops/loop-concurrency-budget.js +22 -0
  31. package/dist/core/mcp/mcp-config-preservation.js +53 -0
  32. package/dist/core/naruto/naruto-loop-mesh.js +5 -1
  33. package/dist/core/version.js +1 -1
  34. package/dist/core/zellij/zellij-fake-adapter.js +8 -2
  35. package/dist/core/zellij/zellij-launcher.js +16 -0
  36. package/dist/core/zellij/zellij-worker-pane-manager.js +19 -2
  37. package/dist/scripts/codex-0140-feature-gate-lib.js +14 -0
  38. package/dist/scripts/release-3112-required-gates.js +30 -0
  39. package/dist/scripts/release-3113-required-gates.js +25 -0
  40. package/package.json +38 -2
  41. package/dist/.sks-build-stamp.json +0 -8
  42. package/dist/scripts/loop-directive-check-lib.js +0 -388
  43. package/dist/scripts/loop-hardening-check-lib.js +0 -289
  44. package/dist/scripts/sks-1-12-real-execution-check-lib.js +0 -27
  45. package/dist/scripts/sks-3-1-4-directive-check-lib.js +0 -212
  46. package/dist/scripts/sks-3-1-5-directive-check-lib.js +0 -318
  47. package/dist/scripts/sks-3-1-6-directive-check-lib.js +0 -522
  48. package/dist/scripts/sks-3-1-7-directive-check-lib.js +0 -58
  49. package/dist/scripts/sks-3-1-8-check-lib.js +0 -30
@@ -1,522 +0,0 @@
1
- #!/usr/bin/env node
2
- import fs from 'node:fs';
3
- import fsp from 'node:fs/promises';
4
- import os from 'node:os';
5
- import path from 'node:path';
6
- import { createHash } from 'node:crypto';
7
- import { fileURLToPath, pathToFileURL } from 'node:url';
8
- import { spawnSync } from 'node:child_process';
9
- export const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..');
10
- const REQUIRED_SCRIPT_IDS = [
11
- 'brand-neutrality:rename-map',
12
- 'brand-neutrality:zero-leakage',
13
- 'brand-neutrality:zero-leakage-blackbox',
14
- 'docs:brand-neutrality',
15
- 'codex-native:feature-broker',
16
- 'codex-native:harness-compat',
17
- 'codex-native:invocation-defaults',
18
- 'codex-native:invocation-router',
19
- 'codex-native:route-map',
20
- 'pipeline:codex-native-loop-routing',
21
- 'pipeline:codex-native-qa-routing',
22
- 'pipeline:codex-native-research-routing',
23
- 'pipeline:codex-native-image-routing',
24
- 'pipeline:codex-native-doctor-mad-routing',
25
- 'codex-native:pattern-analysis',
26
- 'codex-native:reference-evidence',
27
- 'codex-native:pattern-analysis-blackbox',
28
- 'codex-native:interop-policy',
29
- 'codex-native:skill-content',
30
- 'codex-native:agent-role-content',
31
- 'codex-native:hook-lifecycle-proof',
32
- 'init-deep:backup-retention',
33
- 'init-deep:memory-scope-safety',
34
- 'release-scripts:type-safe',
35
- 'lint:no-ts-nocheck-release-scripts',
36
- 'doctor:codex-native-readiness-ux',
37
- 'doctor:codex-native-repair-actions',
38
- 'codex-native:feature-broker-blackbox',
39
- 'pipeline:codex-native-e2e-blackbox'
40
- ];
41
- export async function runDirective316Gate(id) {
42
- if (id === 'brand-neutrality:rename-map')
43
- return brandRenameMap(id);
44
- if (id === 'brand-neutrality:zero-leakage')
45
- return brandZeroLeakage(id);
46
- if (id === 'brand-neutrality:zero-leakage-blackbox')
47
- return brandZeroLeakageBlackbox(id);
48
- if (id === 'docs:brand-neutrality')
49
- return docsBrandNeutrality(id);
50
- if (id === 'codex-native:feature-broker')
51
- return featureBroker(id);
52
- if (id === 'codex-native:harness-compat')
53
- return harnessCompat(id);
54
- if (id === 'codex-native:invocation-defaults')
55
- return invocationDefaults(id);
56
- if (id === 'codex-native:invocation-router')
57
- return invocationRouter(id);
58
- if (id === 'codex-native:route-map')
59
- return routeMap(id);
60
- if (id.startsWith('pipeline:codex-native-'))
61
- return pipelineGate(id);
62
- if (id === 'codex-native:pattern-analysis')
63
- return patternAnalysis(id);
64
- if (id === 'codex-native:reference-evidence')
65
- return referenceEvidence(id);
66
- if (id === 'codex-native:pattern-analysis-blackbox')
67
- return patternAnalysisBlackbox(id);
68
- if (id === 'codex-native:interop-policy')
69
- return interopPolicy(id);
70
- if (id === 'codex-native:skill-content')
71
- return skillContent(id);
72
- if (id === 'codex-native:agent-role-content')
73
- return agentRoleContent(id);
74
- if (id === 'codex-native:hook-lifecycle-proof')
75
- return hookLifecycleProof(id);
76
- if (id === 'init-deep:backup-retention')
77
- return initDeepBackupRetention(id);
78
- if (id === 'init-deep:memory-scope-safety')
79
- return initDeepMemoryScopeSafety(id);
80
- if (id === 'release-scripts:type-safe')
81
- return releaseScriptsTypeSafe(id);
82
- if (id === 'lint:no-ts-nocheck-release-scripts')
83
- return noTsNoCheckReleaseScripts(id);
84
- if (id === 'doctor:codex-native-readiness-ux')
85
- return doctorReadinessUx(id);
86
- if (id === 'doctor:codex-native-repair-actions')
87
- return doctorRepairActions(id);
88
- if (id === 'codex-native:feature-broker-blackbox')
89
- return featureBrokerBlackbox(id);
90
- throw new Error(`unknown_gate:${id}`);
91
- }
92
- async function brandRenameMap(id) {
93
- const mod = await importDist('core/codex-native/codex-native-rename-map.js');
94
- const targets = mod.codexNativeRenameTargets();
95
- for (const expected of [
96
- 'codex-native:pattern-analysis',
97
- 'codex-native:reference-evidence',
98
- 'codex-native:feature-broker',
99
- 'codex-native:invocation-router',
100
- 'sks.codex-native-feature-matrix.v1',
101
- '.sneakoscope/reports/codex-native-invocation-plan.json'
102
- ])
103
- assertGate(targets.includes(expected), `rename target missing:${expected}`, { targets });
104
- emitGate(id, { targets: targets.length });
105
- }
106
- async function brandZeroLeakage(id) {
107
- const report = await scanBrandLeakage(root);
108
- const out = path.join(root, '.sneakoscope', 'reports', 'brand-neutrality-zero-leakage.json');
109
- await fsp.mkdir(path.dirname(out), { recursive: true });
110
- await fsp.writeFile(out, `${JSON.stringify(report, null, 2)}\n`, 'utf8');
111
- assertGate(report.ok, 'brand neutrality leakage detected', report);
112
- emitGate(id, { scanned_files: report.scanned_files, forbidden_term_hashes: report.forbidden_term_hashes });
113
- }
114
- async function brandZeroLeakageBlackbox(id) {
115
- const tmp = await tempRoot(id);
116
- await fsp.mkdir(path.join(tmp, 'docs'), { recursive: true });
117
- await fsp.writeFile(path.join(tmp, 'docs', 'fixture.md'), 'secret-reference-token appears here\n', 'utf8');
118
- const previous = process.env.FORBIDDEN_EXTERNAL_REFERENCE_TERMS;
119
- process.env.FORBIDDEN_EXTERNAL_REFERENCE_TERMS = 'secret-reference-token';
120
- try {
121
- const report = await scanBrandLeakage(tmp);
122
- assertGate(report.ok === false && report.redacted_offenders.length === 1, 'blackbox must detect forbidden token without printing it', report);
123
- assertGate(!JSON.stringify(report).includes('secret-reference-token'), 'blackbox output leaked forbidden token', report);
124
- }
125
- finally {
126
- if (previous === undefined)
127
- delete process.env.FORBIDDEN_EXTERNAL_REFERENCE_TERMS;
128
- else
129
- process.env.FORBIDDEN_EXTERNAL_REFERENCE_TERMS = previous;
130
- }
131
- emitGate(id);
132
- }
133
- async function docsBrandNeutrality(id) {
134
- const report = await scanBrandLeakage(root, ['README.md', 'CHANGELOG.md', 'docs']);
135
- assertGate(report.ok, 'docs contain forbidden external reference terms', report);
136
- assertGate(fs.existsSync(path.join(root, 'docs', 'codex-native-patterns.md')), 'codex native patterns docs missing');
137
- emitGate(id, { scanned_files: report.scanned_files });
138
- }
139
- async function featureBroker(id) {
140
- const matrix = await buildFixtureMatrix(id, { hook: 'approved', agentType: 'supported' });
141
- assertGate(matrix.schema === 'sks.codex-native-feature-matrix.v1', 'matrix schema mismatch', matrix);
142
- assertGate(matrix.features.agent_type.ok === true, 'agent_type feature not available in fixture', matrix.features.agent_type);
143
- assertGate(matrix.invocation_defaults.loop_worker_role_strategy === 'agent_type', 'loop strategy should use agent_type', matrix.invocation_defaults);
144
- emitGate(id, { strategy: matrix.invocation_defaults.loop_worker_role_strategy });
145
- }
146
- async function harnessCompat(id) {
147
- const previous = fakeEnv({ hook: 'approved', agentType: 'supported' });
148
- try {
149
- const tmp = await tempRoot(id);
150
- const mod = await importDist('core/codex-app/codex-app-harness-matrix.js');
151
- const matrix = await mod.buildCodexAppHarnessMatrix({ root: tmp });
152
- assertGate(matrix.schema === 'sks.codex-app-harness-matrix.v1', 'compat schema mismatch', matrix);
153
- assertGate(matrix.app_features.agent_type_supported === true, 'compat adapter did not expose agent_type', matrix);
154
- }
155
- finally {
156
- restoreEnv(previous);
157
- }
158
- emitGate(id);
159
- }
160
- async function invocationDefaults(id) {
161
- const approved = await buildFixtureMatrix(id, { hook: 'approved', agentType: 'supported' });
162
- assertGate(approved.invocation_defaults.hook_evidence_policy === 'approved-only', 'approved hook must count', approved.invocation_defaults);
163
- const unknown = await buildFixtureMatrix(`${id}-unknown`, { hook: 'unknown', agentType: 'unsupported' });
164
- assertGate(unknown.invocation_defaults.hook_evidence_policy === 'unknown-do-not-count', 'unknown hook must not count', unknown.invocation_defaults);
165
- assertGate(unknown.invocation_defaults.loop_worker_role_strategy === 'message-role', 'unsupported agent_type must fallback', unknown.invocation_defaults);
166
- emitGate(id);
167
- }
168
- async function invocationRouter(id) {
169
- const previous = fakeEnv({ hook: 'unknown', agentType: 'unsupported' });
170
- try {
171
- const tmp = await tempRoot(id);
172
- const mod = await importDist('core/codex-native/codex-native-invocation-router.js');
173
- const agent = await mod.resolveCodexNativeInvocationPlan({ root: tmp, missionId: 'M-router', route: '$Loop', desiredCapability: 'agent-role' });
174
- const hook = await mod.resolveCodexNativeInvocationPlan({ root: tmp, missionId: 'M-router', route: '$MAD', desiredCapability: 'hook-evidence' });
175
- assertGate(agent.selected_strategy === 'message-role-fallback', 'agent-role should fallback when unsupported', agent);
176
- assertGate(hook.selected_strategy === 'blocked' && hook.blockers.includes('hook_approval_not_approved'), 'hook evidence must block when approval unknown', hook);
177
- assertGate(fs.existsSync(path.join(tmp, '.sneakoscope', 'missions', 'M-router', 'codex-native-invocation-plan.loop.agent-role.json')), 'mission invocation artifact missing');
178
- }
179
- finally {
180
- restoreEnv(previous);
181
- }
182
- emitGate(id);
183
- }
184
- async function routeMap(id) {
185
- const source = readText('src/core/codex-native/codex-native-invocation-router.ts');
186
- for (const token of ['$Loop', '$QA-LOOP', '$Research', '$Image', '$MAD', '$Doctor', 'hook_approval_not_approved', 'message-role-fallback']) {
187
- assertGate(source.includes(token), `route map token missing:${token}`);
188
- }
189
- emitGate(id);
190
- }
191
- async function pipelineGate(id) {
192
- if (id === 'pipeline:codex-native-loop-routing') {
193
- const source = readText('src/core/loops/loop-worker-runtime.ts');
194
- assertGate(source.includes('resolveCodexNativeInvocationPlan') && source.includes('SKS_CODEX_NATIVE_STRATEGY') && source.includes('codex_native_invocation_plan'), 'loop routing not wired');
195
- }
196
- else if (id === 'pipeline:codex-native-qa-routing') {
197
- const source = readText('src/core/qa-loop.ts');
198
- assertGate(source.includes('resolveQaCodexNativeInvocation') && source.includes('hook_evidence_policy') && source.includes('image_path_strategy'), 'QA routing not wired');
199
- }
200
- else if (id === 'pipeline:codex-native-research-routing') {
201
- const source = readText('src/core/research.ts');
202
- assertGate(source.includes('resolveResearchCodexNativeInvocation') && source.includes('selected_source_strategy'), 'Research routing not wired');
203
- }
204
- else if (id === 'pipeline:codex-native-image-routing') {
205
- const source = readText('src/core/image/image-artifact-path-contract.ts');
206
- assertGate(source.includes('codex_native_followup_strategy') && source.includes('resolveCodexNativeInvocationPlan'), 'Image routing not wired');
207
- }
208
- else if (id === 'pipeline:codex-native-doctor-mad-routing') {
209
- const doctor = readText('src/commands/doctor.ts');
210
- const mad = readText('src/core/commands/mad-sks-command.ts');
211
- assertGate(doctor.includes('SKS Runtime Readiness') && doctor.includes('buildCodexNativeFeatureMatrix'), 'Doctor readiness not wired');
212
- assertGate(mad.includes('codex-native') || doctor.includes('hook-derived evidence will not count'), 'MAD/Doctor hook evidence policy not visible');
213
- }
214
- else if (id === 'pipeline:codex-native-e2e-blackbox') {
215
- await invocationRouter('pipeline:codex-native-e2e-blackbox/router');
216
- await pipelineGate('pipeline:codex-native-loop-routing');
217
- await pipelineGate('pipeline:codex-native-qa-routing');
218
- await pipelineGate('pipeline:codex-native-research-routing');
219
- await pipelineGate('pipeline:codex-native-image-routing');
220
- }
221
- emitGate(id);
222
- }
223
- async function referenceEvidence(id) {
224
- const previous = fakeEnv({ hook: 'approved', agentType: 'supported' });
225
- try {
226
- const tmp = await tempRoot(id);
227
- const sourceDir = await referenceFixture(tmp);
228
- const mod = await importDist('core/codex-native/codex-native-reference-evidence.js');
229
- const report = await mod.analyzeCodexNativeReferenceSource({ root: tmp, sourceDir, writeReport: true });
230
- assertGate(report.schema === 'sks.codex-native-reference-evidence.v1' && report.evidence.length >= 4, 'reference evidence report incomplete', report);
231
- assertGate(!JSON.stringify(report).includes('secret-reference-token'), 'reference evidence should store hashes only', report);
232
- }
233
- finally {
234
- restoreEnv(previous);
235
- }
236
- emitGate(id);
237
- }
238
- async function patternAnalysis(id) {
239
- const tmp = await tempRoot(id);
240
- const sourceDir = await referenceFixture(tmp);
241
- const mod = await importDist('core/codex-native/codex-native-pattern-analysis.js');
242
- const report = await mod.writeCodexNativePatternAnalysis(tmp, { sourceDir });
243
- assertGate(report.schema === 'sks.codex-native-pattern-analysis.v1' && report.patterns.length >= 12, 'pattern analysis incomplete', report);
244
- emitGate(id, { patterns: report.patterns.length });
245
- }
246
- async function patternAnalysisBlackbox(id) {
247
- await patternAnalysis(id);
248
- await brandZeroLeakage('brand-neutrality:zero-leakage');
249
- emitGate(id);
250
- }
251
- async function interopPolicy(id) {
252
- assertGate(readText('src/core/codex-native/codex-native-feature-broker.ts').includes('external route assets') === false, 'broker should not expose interop branding text');
253
- emitGate(id);
254
- }
255
- async function skillContent(id) {
256
- const tmp = await tempRoot(id);
257
- const mod = await importDist('core/codex-app/codex-skill-sync.js');
258
- const skillsRoot = path.join(tmp, 'skills');
259
- const report = await mod.syncCodexSksSkills({ root: tmp, skillsRoot, apply: true });
260
- const skill = fs.readFileSync(path.join(skillsRoot, 'loop', 'SKILL.md'), 'utf8');
261
- assertGate(skill.includes('Purpose:') && skill.includes('Route:') && skill.includes('Proof paths:') && skill.includes('Failure recovery:'), 'managed skill content incomplete', { skill, report });
262
- assertGate(report.interop.clobbered_user_skills === false, 'skill sync clobbered user skills', report);
263
- emitGate(id);
264
- }
265
- async function agentRoleContent(id) {
266
- const previous = fakeEnv({ hook: 'approved', agentType: 'supported' });
267
- try {
268
- const tmp = await tempRoot(id);
269
- const mod = await importDist('core/codex-app/codex-agent-role-sync.js');
270
- const report = await mod.syncCodexAgentRoles({ root: tmp, codexHome: path.join(tmp, 'codex-home'), apply: true });
271
- const role = fs.readFileSync(path.join(tmp, 'codex-home', 'agents', 'sks-implementer.toml'), 'utf8');
272
- assertGate(role.includes('Bounded ownership') && role.includes('Maker/checker separation') && role.includes('Required proof artifacts'), 'agent role content incomplete', { role, report });
273
- }
274
- finally {
275
- restoreEnv(previous);
276
- }
277
- emitGate(id);
278
- }
279
- async function hookLifecycleProof(id) {
280
- const previous = fakeEnv({ hook: 'unknown', agentType: 'supported' });
281
- try {
282
- const tmp = await tempRoot(id);
283
- const mod = await importDist('core/codex-app/codex-hook-lifecycle.js');
284
- const report = await mod.buildCodexHookLifecycle({ root: tmp });
285
- const events = Object.values(report.lifecycle || {});
286
- assertGate(events.every((event) => event.counted_as_evidence === false), 'unknown hooks must not count as evidence', report);
287
- }
288
- finally {
289
- restoreEnv(previous);
290
- }
291
- emitGate(id);
292
- }
293
- async function initDeepBackupRetention(id) {
294
- const tmp = await tempRoot(id);
295
- await fsp.mkdir(path.join(tmp, 'src/core/zellij'), { recursive: true });
296
- await fsp.writeFile(path.join(tmp, 'src/core/zellij', 'AGENTS.md'), '# User local guidance\nKeep me.\n', 'utf8');
297
- for (let index = 0; index < 18; index += 1)
298
- await fsp.writeFile(path.join(tmp, 'src/core/zellij', `f${index}.ts`), 'export {}\n', 'utf8');
299
- const previous = process.env.SKS_INIT_DEEP_BACKUP_RETENTION;
300
- process.env.SKS_INIT_DEEP_BACKUP_RETENTION = '1';
301
- try {
302
- const mod = await importDist('core/codex-app/codex-init-deep.js');
303
- const first = await mod.runCodexInitDeep({ root: tmp, apply: true, directoryLocal: true });
304
- const second = await mod.runCodexInitDeep({ root: tmp, apply: true, directoryLocal: true });
305
- assertGate(first.directory_local_agents.changed_only_backup === true, 'changed-only backup flag missing', first);
306
- assertGate(second.directory_local_agents.unchanged_files.length >= 1, 'unchanged second run should not create backup', second);
307
- }
308
- finally {
309
- if (previous === undefined)
310
- delete process.env.SKS_INIT_DEEP_BACKUP_RETENTION;
311
- else
312
- process.env.SKS_INIT_DEEP_BACKUP_RETENTION = previous;
313
- }
314
- emitGate(id);
315
- }
316
- async function initDeepMemoryScopeSafety(id) {
317
- const planner = readText('src/core/loops/loop-planner.ts');
318
- const owner = readText('src/core/loops/loop-owner-inference.ts');
319
- assertGate(planner.includes('memory_did_not_expand_scope') && planner.includes('memory_hints_used'), 'loop planner must prove memory scope safety');
320
- assertGate(owner.includes('memoryHintMayExpandOwnerScope'), 'owner inference must expose memory scope safety contract');
321
- emitGate(id);
322
- }
323
- async function releaseScriptsTypeSafe(id) {
324
- for (const rel of ['src/scripts/release-dag-full-coverage-check.ts', 'src/scripts/sks-3-1-5-directive-check-lib.ts', 'src/scripts/sks-3-1-6-directive-check-lib.ts', 'src/scripts/sks-3-1-7-directive-check-lib.ts']) {
325
- const text = readText(rel);
326
- assertGate(!/^\s*\/\/\s*@ts-nocheck\b/m.test(text), `release helper still has ts-nocheck:${rel}`);
327
- }
328
- assertGate(readText('src/scripts/release-dag-full-coverage-check.ts').includes('interface ReleaseGate'), 'release DAG helper missing typed interfaces');
329
- assertGate(readText('src/scripts/sks-3-1-6-directive-check-lib.ts').includes('interface PackageJsonShape'), '3.1.6 helper missing typed package shape');
330
- emitGate(id);
331
- }
332
- async function noTsNoCheckReleaseScripts(id) {
333
- const offenders = [];
334
- const checked = listFiles(path.join(root, 'src/scripts')).filter((file) => {
335
- const rel = path.relative(root, file).split(path.sep).join('/');
336
- return /^src\/scripts\/release-dag-full-coverage-check\.ts$/.test(rel)
337
- || /^src\/scripts\/sks-3-1-[567]-directive-check-lib\.ts$/.test(rel)
338
- || /^src\/scripts\/no-ts-nocheck-release-scripts-check\.ts$/.test(rel)
339
- || /^src\/scripts\/release-script-type-safety-check\.ts$/.test(rel);
340
- });
341
- for (const file of checked) {
342
- if (/^\s*\/\/\s*@ts-nocheck\b/m.test(fs.readFileSync(file, 'utf8')))
343
- offenders.push(path.relative(root, file));
344
- }
345
- assertGate(offenders.length === 0, 'release script ts-nocheck offenders found', { offenders, checked: checked.length });
346
- emitGate(id, { checked: checked.length });
347
- }
348
- async function doctorReadinessUx(id) {
349
- const source = readText('src/commands/doctor.ts');
350
- for (const token of ['SKS Runtime Readiness', 'Codex Native:', 'Loop Mesh:', 'QA Visual:', 'Research Sources:', 'hook-derived evidence will not count', 'message-role fallback active']) {
351
- assertGate(source.includes(token), `doctor readiness token missing:${token}`);
352
- }
353
- emitGate(id);
354
- }
355
- async function doctorRepairActions(id) {
356
- const source = readText('src/commands/doctor.ts');
357
- for (const token of ['sks doctor --fix --yes', 'sks doctor --fix --repair-codex-native --yes', 'sks codex-native init-deep --apply --directory-local']) {
358
- assertGate(source.includes(token), `doctor repair action missing:${token}`);
359
- }
360
- emitGate(id);
361
- }
362
- async function featureBrokerBlackbox(id) {
363
- const all = await buildFixtureMatrix(`${id}-all`, { hook: 'approved', agentType: 'supported' });
364
- assertGate(all.invocation_defaults.loop_worker_role_strategy === 'agent_type', 'all-ready scenario should use agent_type', all);
365
- const unknownHook = await buildFixtureMatrix(`${id}-hook`, { hook: 'unknown', agentType: 'supported' });
366
- assertGate(unknownHook.invocation_defaults.hook_evidence_policy === 'unknown-do-not-count', 'unknown hook scenario should not count', unknownHook);
367
- const noAgent = await buildFixtureMatrix(`${id}-agent`, { hook: 'approved', agentType: 'unsupported' });
368
- assertGate(noAgent.invocation_defaults.loop_worker_role_strategy === 'message-role', 'agent unsupported scenario should fallback', noAgent);
369
- emitGate(id);
370
- }
371
- async function buildFixtureMatrix(id, opts) {
372
- const previous = fakeEnv({ hook: opts.hook, agentType: opts.agentType });
373
- try {
374
- const tmp = await tempRoot(id);
375
- const mod = await importDist('core/codex-native/codex-native-feature-broker.js');
376
- return await mod.buildCodexNativeFeatureMatrix({ root: tmp });
377
- }
378
- finally {
379
- restoreEnv(previous);
380
- }
381
- }
382
- async function referenceFixture(tmp) {
383
- const dir = path.join(tmp, 'reference-source');
384
- await fsp.mkdir(dir, { recursive: true });
385
- await fsp.writeFile(path.join(dir, 'README.md'), [
386
- 'Use npx for optional no-global setup.',
387
- 'Codex plugin lifecycle keeps install and approval separate.',
388
- 'Hook approval requires startup review before evidence counts.',
389
- '$Loop and $Research are command picker route bridges.',
390
- 'spawn_agent uses agent_type when present and message-role fallback otherwise.',
391
- 'Directory-local AGENTS.md memory is guidance only.',
392
- 'Plan work proof separation keeps long tasks resumable.',
393
- 'Doctor readiness matrix lists MCP server candidates and non-clobber managed assets.'
394
- ].join('\n'), 'utf8');
395
- return dir;
396
- }
397
- async function scanBrandLeakage(base, customTargets) {
398
- const terms = forbiddenTerms();
399
- const targets = customTargets || ['src/core', 'src/scripts', 'docs', 'README.md', 'CHANGELOG.md', 'package.json', 'release-gates.v2.json', 'schemas'];
400
- const files = targets.flatMap((target) => {
401
- const full = path.join(base, target);
402
- if (!fs.existsSync(full))
403
- return [];
404
- return fs.statSync(full).isDirectory() ? listFiles(full) : [full];
405
- }).filter((file) => !/\/(?:node_modules|dist|\.git)\//.test(file));
406
- const offenders = [];
407
- for (const file of files) {
408
- const text = fs.readFileSync(file, 'utf8');
409
- for (const term of terms) {
410
- if (term && text.toLowerCase().includes(term.toLowerCase())) {
411
- offenders.push(`${path.relative(base, file)}#${hash(term).slice(0, 12)}`);
412
- }
413
- }
414
- }
415
- return {
416
- schema: 'sks.brand-neutrality-zero-leakage.v1',
417
- ok: offenders.length === 0,
418
- scanned_files: files.length,
419
- redacted_offenders: offenders,
420
- forbidden_term_hashes: terms.map((term) => hash(term))
421
- };
422
- }
423
- function forbiddenTerms() {
424
- const raw = process.env.FORBIDDEN_EXTERNAL_REFERENCE_TERMS;
425
- if (raw) {
426
- try {
427
- const parsed = JSON.parse(raw);
428
- if (Array.isArray(parsed))
429
- return parsed.map(String).filter(Boolean);
430
- }
431
- catch { }
432
- return raw.split(/[,;\n]/).map((term) => term.trim()).filter(Boolean);
433
- }
434
- return ['bGF6eWNvZGV4', 'b3BlbmNsYXc=', 'aGVybWVz', 'b2gtbXktb3BlbmFnZW50', 'c2lzeXBodXNsYWJz'].map((value) => Buffer.from(value, 'base64').toString('utf8'));
435
- }
436
- function fakeEnv(opts) {
437
- return swapEnv({
438
- SKS_CODEX_0138_FAKE: '1',
439
- SKS_CODEX_0139_FAKE: '1',
440
- SKS_CODEX_PLUGIN_JSON_FAKE: '1',
441
- SKS_CODEX_HOOK_APPROVAL_FIXTURE: opts.hook,
442
- SKS_CODEX_AGENT_TYPE_FIXTURE: opts.agentType,
443
- CODEX_BIN: 'codex'
444
- });
445
- }
446
- function swapEnv(values) {
447
- const previous = {};
448
- for (const [key, value] of Object.entries(values)) {
449
- previous[key] = process.env[key];
450
- process.env[key] = value;
451
- }
452
- return previous;
453
- }
454
- function restoreEnv(previous) {
455
- for (const [key, value] of Object.entries(previous)) {
456
- if (value === undefined)
457
- delete process.env[key];
458
- else
459
- process.env[key] = value;
460
- }
461
- }
462
- async function tempRoot(id) {
463
- const dir = await fsp.mkdtemp(path.join(os.tmpdir(), `${id.replace(/[^a-z0-9-]/gi, '-')}-`));
464
- await fsp.mkdir(path.join(dir, '.sneakoscope', 'reports'), { recursive: true });
465
- await fsp.mkdir(path.join(dir, 'docs'), { recursive: true });
466
- await fsp.writeFile(path.join(dir, 'package.json'), '{"name":"fixture","version":"3.1.6","scripts":{}}\n', 'utf8');
467
- return dir;
468
- }
469
- function listFiles(dir) {
470
- const out = [];
471
- const walk = (current) => {
472
- for (const entry of fs.readdirSync(current, { withFileTypes: true })) {
473
- if (['.git', 'node_modules', 'dist'].includes(entry.name))
474
- continue;
475
- const full = path.join(current, entry.name);
476
- if (entry.isDirectory())
477
- walk(full);
478
- else if (entry.isFile())
479
- out.push(full);
480
- }
481
- };
482
- if (fs.existsSync(dir))
483
- walk(dir);
484
- return out.filter((file) => /\.(ts|js|json|md|txt|toml|ya?ml)$/i.test(file));
485
- }
486
- async function importDist(rel) {
487
- const absolute = path.join(root, 'dist', rel);
488
- assertGate(fs.existsSync(absolute), `dist module missing:${rel}`, { hint: 'run npm run build first' });
489
- return import(pathToFileURL(absolute).href);
490
- }
491
- function readText(rel) {
492
- return fs.readFileSync(path.join(root, rel), 'utf8');
493
- }
494
- function readJson(rel) {
495
- return JSON.parse(readText(rel));
496
- }
497
- function hash(text) {
498
- return createHash('sha256').update(text).digest('hex');
499
- }
500
- function assertGate(condition, message, detail = {}) {
501
- if (condition)
502
- return;
503
- console.error(JSON.stringify({ ok: false, message, detail }, null, 2));
504
- process.exit(1);
505
- }
506
- function emitGate(name, detail = {}) {
507
- console.log(JSON.stringify({ schema: 'sks.release-gate.v1', ok: true, gate: name, ...detail }, null, 2));
508
- }
509
- export function packageJson() {
510
- return readJson('package.json');
511
- }
512
- export function gateManifest() {
513
- return readJson('release-gates.v2.json');
514
- }
515
- export function required316ScriptIds() {
516
- return [...REQUIRED_SCRIPT_IDS];
517
- }
518
- export function checkCommand(command, args) {
519
- const result = spawnSync(command, args, { cwd: root, encoding: 'utf8', timeout: 120_000 });
520
- return { status: result.status, stdout: result.stdout || '', stderr: result.stderr || '' };
521
- }
522
- //# sourceMappingURL=sks-3-1-6-directive-check-lib.js.map
@@ -1,58 +0,0 @@
1
- #!/usr/bin/env node
2
- import fs from 'node:fs';
3
- import path from 'node:path';
4
- import { fileURLToPath } from 'node:url';
5
- export const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..');
6
- const RELEASE_HELPERS = [
7
- 'src/scripts/release-dag-full-coverage-check.ts',
8
- 'src/scripts/sks-3-1-5-directive-check-lib.ts',
9
- 'src/scripts/sks-3-1-6-directive-check-lib.ts',
10
- 'src/scripts/sks-3-1-7-directive-check-lib.ts',
11
- 'src/scripts/release-script-type-safety-check.ts',
12
- 'src/scripts/no-ts-nocheck-release-scripts-check.ts'
13
- ];
14
- export async function runDirective317Gate(id) {
15
- if (id === 'release-scripts:type-safe')
16
- return releaseScriptsTypeSafe(id);
17
- if (id === 'lint:no-ts-nocheck-release-scripts')
18
- return noTsNoCheckReleaseScripts(id);
19
- throw new Error(`unknown_3_1_7_gate:${id}`);
20
- }
21
- function releaseScriptsTypeSafe(id) {
22
- checkNoTsNoCheckReleaseScripts();
23
- const dag = readText('src/scripts/release-dag-full-coverage-check.ts');
24
- for (const token of [
25
- 'interface PackageJsonShape',
26
- 'interface ReleaseGate',
27
- 'interface ReleaseGateManifest',
28
- 'function readPackageJson',
29
- 'function readReleaseGateManifest',
30
- 'function isReleaseGate',
31
- 'function normalizeStringList',
32
- 'const parsed: unknown'
33
- ]) {
34
- assertGate(dag.includes(token), `release DAG helper missing typed token:${token}`);
35
- }
36
- emitGate(id, { checked_files: RELEASE_HELPERS });
37
- }
38
- function noTsNoCheckReleaseScripts(id) {
39
- checkNoTsNoCheckReleaseScripts();
40
- emitGate(id, { checked_files: RELEASE_HELPERS });
41
- }
42
- function checkNoTsNoCheckReleaseScripts() {
43
- const offenders = RELEASE_HELPERS.filter((rel) => /^\s*\/\/\s*@ts-nocheck\b/m.test(readText(rel)));
44
- assertGate(offenders.length === 0, 'release script ts-nocheck offenders found', { offenders, checked_files: RELEASE_HELPERS });
45
- }
46
- function readText(rel) {
47
- return fs.readFileSync(path.join(root, rel), 'utf8');
48
- }
49
- function assertGate(condition, message, detail = {}) {
50
- if (condition)
51
- return;
52
- console.error(JSON.stringify({ ok: false, message, detail }, null, 2));
53
- process.exit(1);
54
- }
55
- function emitGate(gate, detail = {}) {
56
- console.log(JSON.stringify({ schema: 'sks.release-gate.v1', ok: true, gate, ...detail }, null, 2));
57
- }
58
- //# sourceMappingURL=sks-3-1-7-directive-check-lib.js.map
@@ -1,30 +0,0 @@
1
- import fs from 'node:fs/promises';
2
- import os from 'node:os';
3
- import path from 'node:path';
4
- import { assertGate, emitGate } from './sks-1-18-gate-lib.js';
5
- import { renderCoreSkillTemplate } from '../core/codex-native/core-skill-manifest.js';
6
- export { assertGate, emitGate };
7
- export async function makeTempRoot(prefix) {
8
- const root = await fs.mkdtemp(path.join(os.tmpdir(), prefix));
9
- await fs.mkdir(path.join(root, '.sneakoscope', 'reports'), { recursive: true });
10
- await fs.mkdir(path.join(root, '.sneakoscope', 'locks'), { recursive: true });
11
- return root;
12
- }
13
- export async function writeText(file, text) {
14
- await fs.mkdir(path.dirname(file), { recursive: true });
15
- await fs.writeFile(file, text, 'utf8');
16
- }
17
- export async function readJson(file) {
18
- return JSON.parse(await fs.readFile(file, 'utf8'));
19
- }
20
- export async function writeManagedCoreSkill(root, relRoot, name) {
21
- const file = path.join(root, relRoot, name, 'SKILL.md');
22
- await writeText(file, renderCoreSkillTemplate(name));
23
- return file;
24
- }
25
- export async function writeUserSkill(root, relRoot, name, display = name) {
26
- const file = path.join(root, relRoot, name, 'SKILL.md');
27
- await writeText(file, `---\nname: ${display}\ndescription: user-authored fixture\n---\n\nUser skill fixture.\n`);
28
- return file;
29
- }
30
- //# sourceMappingURL=sks-3-1-8-check-lib.js.map