sneakoscope 4.1.0 → 4.2.0

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 (94) hide show
  1. package/README.md +16 -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/bin/sks.js +1 -1
  6. package/dist/cli/command-registry.js +1 -1
  7. package/dist/cli/router.js +6 -1
  8. package/dist/commands/doctor.js +272 -127
  9. package/dist/core/auto-review.js +1 -1
  10. package/dist/core/codex/agent-config-file-repair.js +43 -2
  11. package/dist/core/codex-app/codex-agent-role-sync.js +4 -4
  12. package/dist/core/codex-control/codex-0142-capability.js +51 -6
  13. package/dist/core/codex-control/codex-app-server-v2-client.js +2 -2
  14. package/dist/core/codex-native/codex-native-feature-broker.js +50 -0
  15. package/dist/core/codex-native/native-capability-postcheck.js +59 -16
  16. package/dist/core/codex-native/native-capability-repair-matrix.js +77 -13
  17. package/dist/core/commands/mad-db-command.js +146 -51
  18. package/dist/core/commands/mad-sks-command.js +51 -61
  19. package/dist/core/db-safety.js +35 -37
  20. package/dist/core/doctor/doctor-dirty-planner.js +9 -4
  21. package/dist/core/doctor/doctor-native-capability-repair.js +42 -7
  22. package/dist/core/doctor/doctor-readiness-matrix.js +9 -5
  23. package/dist/core/doctor/doctor-repair-postcheck.js +10 -1
  24. package/dist/core/doctor/doctor-transaction.js +1 -1
  25. package/dist/core/doctor/supabase-mcp-repair.js +2 -2
  26. package/dist/core/feature-registry.js +1 -1
  27. package/dist/core/fsx.js +1 -1
  28. package/dist/core/init.js +5 -4
  29. package/dist/core/mad-db/mad-db-capability.js +203 -74
  30. package/dist/core/mad-db/mad-db-coordinator.js +287 -0
  31. package/dist/core/mad-db/mad-db-executor.js +156 -0
  32. package/dist/core/mad-db/mad-db-ledger.js +1 -1
  33. package/dist/core/mad-db/mad-db-lock.js +40 -0
  34. package/dist/core/mad-db/mad-db-operation-store.js +140 -0
  35. package/dist/core/mad-db/mad-db-policy-resolver.js +42 -22
  36. package/dist/core/mad-db/mad-db-policy.js +195 -0
  37. package/dist/core/mad-db/mad-db-postconditions.js +30 -0
  38. package/dist/core/mad-db/mad-db-recovery.js +27 -0
  39. package/dist/core/mad-db/mad-db-result-lifecycle.js +31 -102
  40. package/dist/core/mad-db/mad-db-runtime-profile.js +121 -0
  41. package/dist/core/mad-db/mad-db-target.js +64 -0
  42. package/dist/core/managed-assets/managed-assets-manifest.js +14 -4
  43. package/dist/core/pipeline-internals/runtime-core.js +40 -0
  44. package/dist/core/providers/glm/bench/glm-benchmark-runner.js +4 -3
  45. package/dist/core/providers/glm/bench/glm-benchmark-types.js +1 -1
  46. package/dist/core/release/release-gate-dag.js +6 -5
  47. package/dist/core/routes.js +23 -8
  48. package/dist/core/update/update-migration-state.js +265 -50
  49. package/dist/core/update-check.js +6 -6
  50. package/dist/core/version.js +1 -1
  51. package/dist/core/zellij/zellij-launcher.js +17 -5
  52. package/dist/core/zellij/zellij-slot-column-anchor.js +5 -1
  53. package/dist/scripts/check-dist-runtime.js +3 -2
  54. package/dist/scripts/codex-0142-manifest-check.js +2 -1
  55. package/dist/scripts/config-managed-merge-callsite-coverage-check.js +6 -0
  56. package/dist/scripts/doctor-dirty-plan-check.js +1 -1
  57. package/dist/scripts/doctor-transaction-engine-check.js +1 -0
  58. package/dist/scripts/doctor-warning-only-not-blocker-check.js +18 -1
  59. package/dist/scripts/loop-directive-check-lib.js +2 -1
  60. package/dist/scripts/mad-db-capability-check.js +13 -2
  61. package/dist/scripts/mad-db-command-check.js +7 -5
  62. package/dist/scripts/mad-db-hook-idempotency-check.js +21 -0
  63. package/dist/scripts/mad-db-ledger-check.js +2 -1
  64. package/dist/scripts/mad-db-lifecycle-hook-decision-check.js +5 -4
  65. package/dist/scripts/mad-db-mad-command-check.js +29 -16
  66. package/dist/scripts/mad-db-mcp-result-lifecycle-check.js +11 -10
  67. package/dist/scripts/mad-db-one-cycle-bounded-check.js +15 -18
  68. package/dist/scripts/mad-db-one-cycle-consumption-check.js +3 -3
  69. package/dist/scripts/mad-db-operation-lifecycle-blackbox.js +9 -9
  70. package/dist/scripts/mad-db-operation-lifecycle-ledger-check.js +6 -6
  71. package/dist/scripts/mad-db-parallel-lifecycle-check.js +24 -0
  72. package/dist/scripts/mad-db-policy-v2-check.js +20 -0
  73. package/dist/scripts/mad-db-priority-resolver-check.js +5 -5
  74. package/dist/scripts/mad-db-real-supabase-e2e.js +166 -0
  75. package/dist/scripts/mad-db-route-identity-check.js +28 -0
  76. package/dist/scripts/mad-db-runtime-profile-lifecycle-check.js +24 -0
  77. package/dist/scripts/mad-db-safety-conflict-matrix-check.js +3 -3
  78. package/dist/scripts/mad-db-skill-policy-snapshot-check.js +15 -0
  79. package/dist/scripts/mad-sks-zellij-launch-check.js +7 -1
  80. package/dist/scripts/managed-role-manifest-parity-check.js +4 -1
  81. package/dist/scripts/naruto-real-parallelism-blackbox.js +17 -4
  82. package/dist/scripts/native-capability-postcheck-check.js +1 -0
  83. package/dist/scripts/native-capability-repair-matrix-check.js +2 -0
  84. package/dist/scripts/native-chrome-web-review-repair-check.js +1 -0
  85. package/dist/scripts/native-computer-use-repair-check.js +1 -0
  86. package/dist/scripts/release-dag-full-coverage-check.js +6 -0
  87. package/dist/scripts/release-triwiki-first-runner-blackbox.js +5 -1
  88. package/dist/scripts/sks-3-1-5-directive-check-lib.js +1 -1
  89. package/dist/scripts/sks-401-all-feature-regression-blackbox.js +1 -1
  90. package/dist/scripts/update-concurrent-lock-check.js +1 -0
  91. package/dist/scripts/update-first-command-migration-check.js +4 -3
  92. package/package.json +13 -2
  93. package/schemas/mad-db/mad-db-capability.schema.json +92 -19
  94. package/schemas/update-migration.schema.json +13 -1
@@ -1,98 +1,178 @@
1
- import { initProject } from '../init.js';
2
- import { createMission, findLatestMission, setCurrent } from '../mission.js';
3
- import { exists, sksRoot } from '../fsx.js';
4
1
  import path from 'node:path';
5
- import { createMadDbCapability, isMadDbCapabilityActive, MAD_DB_ACK, readMadDbCapability, resolveMadDbMissionId, revokeMadDbCapability } from '../mad-db/mad-db-capability.js';
2
+ import { initProject } from '../init.js';
3
+ import { findLatestMission, setCurrent } from '../mission.js';
4
+ import { exists, readText, sksRoot } from '../fsx.js';
5
+ import { closeMadDbCycle, isMadDbCapabilityActive, MAD_DB_ACK, readMadDbCapability, resolveMadDbMissionId, revokeMadDbCapability } from '../mad-db/mad-db-capability.js';
6
+ import { closeMadDbRuntimeProfile, verifyReadOnlyRestored } from '../mad-db/mad-db-runtime-profile.js';
7
+ import { runMadDbCycle } from '../mad-db/mad-db-coordinator.js';
8
+ import { resolveMadDbTarget } from '../mad-db/mad-db-target.js';
9
+ import { quarantineStaleMadDbRuntimeProfiles } from '../mad-db/mad-db-recovery.js';
10
+ import { sha256 } from '../fsx.js';
6
11
  export async function madDbCommand(args = []) {
7
12
  const action = String(args[0] && !String(args[0]).startsWith('--') ? args[0] : 'status');
8
13
  const rest = action === args[0] ? args.slice(1) : args;
9
14
  const root = await sksRoot();
10
15
  if (!(await exists(path.join(root, '.sneakoscope'))))
11
16
  await initProject(root, {});
17
+ if (action === 'run')
18
+ return runMadDb(root, rest);
19
+ if (action === 'exec')
20
+ return execMadDb(root, rest);
21
+ if (action === 'apply-migration')
22
+ return applyMigrationMadDb(root, rest);
23
+ if (action === 'doctor')
24
+ return doctorMadDb(root, rest);
25
+ if (action === 'close')
26
+ return closeMadDb(root, rest);
12
27
  if (action === 'enable')
13
28
  return enableMadDb(root, rest);
14
29
  if (action === 'revoke')
15
30
  return revokeMadDb(root, rest);
16
31
  if (action === 'status')
17
32
  return statusMadDb(root, rest);
18
- console.error('Usage: sks mad-db enable --ack "I AUTHORIZE ONE-CYCLE DB BREAK-GLASS" [--mission latest|new|M-...] | status | revoke');
33
+ console.error('Usage: sks mad-db run "<task-or-sql>" | exec --sql "<SQL>" | apply-migration --name <name> --file <sql-file> | doctor|status|close|revoke [--json]');
19
34
  process.exitCode = 1;
20
35
  }
36
+ async function runMadDb(root, args) {
37
+ const task = positionalText(args) || readOption(args, '--task', '');
38
+ const sql = readOption(args, '--sql', '');
39
+ const result = await runMadDbCycle({
40
+ root,
41
+ action: 'run',
42
+ task,
43
+ sql: sql || null,
44
+ verifySql: readOption(args, '--verify-sql', '') || null,
45
+ args
46
+ });
47
+ return printResult(result, args);
48
+ }
49
+ async function execMadDb(root, args) {
50
+ const sql = readOption(args, '--sql', '') || positionalText(args);
51
+ const result = await runMadDbCycle({
52
+ root,
53
+ action: 'exec',
54
+ task: sql || 'sks mad-db exec',
55
+ sql: sql || null,
56
+ verifySql: readOption(args, '--verify-sql', '') || null,
57
+ args
58
+ });
59
+ return printResult(result, args);
60
+ }
61
+ async function applyMigrationMadDb(root, args) {
62
+ const file = readOption(args, '--file', '');
63
+ const sql = readOption(args, '--sql', '') || (file ? await readText(path.resolve(file), '') : '');
64
+ const result = await runMadDbCycle({
65
+ root,
66
+ action: 'apply-migration',
67
+ task: `apply migration ${readOption(args, '--name', 'mad_db_migration')}`,
68
+ sql: sql || null,
69
+ migrationName: readOption(args, '--name', `mad_db_${Date.now()}`),
70
+ migrationFile: file || null,
71
+ verifySql: readOption(args, '--verify-sql', '') || null,
72
+ args
73
+ });
74
+ return printResult(result, args);
75
+ }
76
+ async function doctorMadDb(root, args) {
77
+ const target = await resolveMadDbTarget(root, { args });
78
+ const recovery = await quarantineStaleMadDbRuntimeProfiles(root);
79
+ const restoration = await verifyReadOnlyRestored(root, null);
80
+ const result = {
81
+ schema: 'sks.mad-db-doctor.v1',
82
+ ok: target.blockers.length === 0 && restoration.persistent_supabase_read_only,
83
+ target: { ...target, project_ref: target.project_ref ? `<hash:${target.project_ref_hash}>` : null },
84
+ stale_recovery: recovery,
85
+ read_only_restoration: restoration,
86
+ execute_sql_apply_migration_inventory_checked: false,
87
+ note: 'doctor does not open write transport; run/exec/apply-migration verifies tool inventory inside a bound cycle'
88
+ };
89
+ return printJsonOrText(result, args, result.ok ? 'MadDB doctor passed local checks.' : `MadDB doctor found blockers: ${[...target.blockers, ...restoration.blockers].join(', ')}`);
90
+ }
21
91
  async function enableMadDb(root, args) {
22
92
  const json = hasFlag(args, '--json');
23
93
  const ack = readOption(args, '--ack', '');
24
94
  if (ack !== MAD_DB_ACK) {
25
- const result = { schema: 'sks.mad-db-command.v1', ok: false, action: 'enable', reason: 'ack_phrase_required', required_ack: MAD_DB_ACK };
95
+ const result = { schema: 'sks.mad-db-command.v2', ok: false, action: 'enable', reason: 'deprecated_enable_no_capability', required_ack: MAD_DB_ACK, token_only: true };
26
96
  if (json)
27
97
  return console.log(JSON.stringify(result, null, 2));
28
- console.error(`Mad-DB enable blocked. Required --ack ${JSON.stringify(MAD_DB_ACK)}`);
98
+ console.error(`MadDB enable is deprecated and does not create a capability. Use sks mad-db run|exec|apply-migration for an executable cycle. Legacy ack was ${JSON.stringify(MAD_DB_ACK)}.`);
29
99
  process.exitCode = 2;
30
100
  return result;
31
101
  }
32
- const requestedMission = readOption(args, '--mission', 'latest');
33
- let missionId = requestedMission === 'new' ? null : await resolveMadDbMissionId(root, {}, requestedMission);
34
- if (!missionId) {
35
- const created = await createMission(root, { mode: 'mad-db', prompt: 'sks mad-db enable one-cycle DB break-glass' });
36
- missionId = created.id;
37
- }
38
- const capability = await createMadDbCapability(root, {
39
- missionId,
40
- ack,
41
- cwd: process.cwd(),
42
- ttlMs: Number(readOption(args, '--ttl-ms', String(2 * 60 * 60 * 1000)))
43
- });
44
- await setCurrent(root, {
45
- mission_id: missionId,
46
- route: 'MadDB',
47
- route_command: '$MAD-DB',
48
- mode: 'MADDB',
49
- phase: 'MADDB_ONE_CYCLE_CAPABILITY_ACTIVE',
50
- mad_db_active: true,
51
- mad_db_cycle_id: capability.cycle_id,
52
- mad_db_capability_file: 'mad-db-capability.json',
53
- mad_db_ack_phrase: 'accepted',
54
- stop_gate: 'mad-db-capability.json'
55
- });
56
- const result = { schema: 'sks.mad-db-command.v1', ok: true, action: 'enable', mission_id: missionId, capability };
102
+ const result = {
103
+ schema: 'sks.mad-db-command.v2',
104
+ ok: false,
105
+ action: 'enable',
106
+ reason: 'deprecated_enable_no_capability',
107
+ token_only: true,
108
+ executable_commands: ['sks mad-db run', 'sks mad-db exec', 'sks mad-db apply-migration']
109
+ };
57
110
  if (json)
58
111
  return console.log(JSON.stringify(result, null, 2));
59
- console.log(`Mad-DB one-cycle capability active for ${missionId}; expires ${capability.expires_at}.`);
112
+ console.error('MadDB enable no longer creates a capability. Use sks mad-db run|exec|apply-migration to create the bound mission/profile/capability and execute SQL.');
113
+ process.exitCode = 2;
60
114
  return result;
61
115
  }
62
116
  async function statusMadDb(root, args) {
63
- const json = hasFlag(args, '--json');
64
117
  const missionId = await resolveMadDbMissionId(root, {}, readOption(args, '--mission', 'latest'));
65
118
  const capability = missionId ? await readMadDbCapability(root, missionId) : null;
66
119
  const result = {
67
- schema: 'sks.mad-db-command.v1',
120
+ schema: 'sks.mad-db-status.v2',
68
121
  ok: true,
69
122
  action: 'status',
70
123
  mission_id: missionId,
71
124
  active: isMadDbCapabilityActive(capability),
72
- capability
125
+ capability: capability ? redactCapability(capability) : null
73
126
  };
74
- if (json)
75
- return console.log(JSON.stringify(result, null, 2));
76
- if (!missionId || !capability)
77
- console.log('Mad-DB: no capability found.');
78
- else
79
- console.log(`Mad-DB: ${result.active ? 'active' : 'inactive'} for ${missionId}; consumed=${capability.consumed}; expires=${capability.expires_at}.`);
80
- return result;
127
+ return printJsonOrText(result, args, !missionId || !capability ? 'MadDB: no capability found.' : `MadDB: ${result.active ? 'active' : 'inactive'} for ${missionId}; status=${capability.status}; expires=${capability.expires_at}.`);
128
+ }
129
+ async function closeMadDb(root, args) {
130
+ const missionId = await resolveMadDbMissionId(root, {}, readOption(args, '--mission', 'latest')) || await findLatestMission(root);
131
+ const capability = missionId ? await readMadDbCapability(root, missionId) : null;
132
+ const restoration = missionId ? await closeMadDbRuntimeProfile({ root, missionId, reason: 'operator_close' }) : null;
133
+ const closed = missionId && capability ? await closeMadDbCycle(root, missionId, capability.cycle_id, 'operator_close') : null;
134
+ if (missionId)
135
+ await setCurrent(root, { mad_db_active: false, phase: 'MADDB_CLOSED' });
136
+ const result = { schema: 'sks.mad-db-close.v2', ok: Boolean(closed), action: 'close', mission_id: missionId, capability: closed ? redactCapability(closed) : null, read_only_restoration: restoration };
137
+ return printJsonOrText(result, args, closed ? `MadDB cycle closed for ${missionId}.` : 'MadDB: no capability to close.');
81
138
  }
82
139
  async function revokeMadDb(root, args) {
83
- const json = hasFlag(args, '--json');
84
140
  const missionId = await resolveMadDbMissionId(root, {}, readOption(args, '--mission', 'latest')) || await findLatestMission(root);
85
141
  const revoked = missionId ? await revokeMadDbCapability(root, missionId, readOption(args, '--reason', 'operator_revoked')) : null;
142
+ const restoration = missionId ? await closeMadDbRuntimeProfile({ root, missionId, reason: 'operator_revoke' }) : null;
86
143
  await setCurrent(root, { mad_db_active: false, phase: 'MADDB_REVOKED' });
87
- const result = { schema: 'sks.mad-db-command.v1', ok: Boolean(revoked), action: 'revoke', mission_id: missionId, capability: revoked };
88
- if (json)
89
- return console.log(JSON.stringify(result, null, 2));
90
- if (!revoked)
91
- console.log('Mad-DB: no capability to revoke.');
144
+ const result = { schema: 'sks.mad-db-command.v2', ok: Boolean(revoked), action: 'revoke', mission_id: missionId, capability: revoked ? redactCapability(revoked) : null, read_only_restoration: restoration };
145
+ return printJsonOrText(result, args, revoked ? `MadDB capability revoked for ${missionId}.` : 'MadDB: no capability to revoke.');
146
+ }
147
+ function printResult(result, args) {
148
+ if (hasFlag(args, '--json')) {
149
+ console.log(JSON.stringify(result, null, 2));
150
+ }
151
+ else if (result.ok) {
152
+ console.log(`MadDB complete: mission=${result.mission_id} cycle=${result.cycle_id} execution=${result.execution?.ok ? 'succeeded' : 'unknown'} verification=${result.read_back?.ok === true ? 'passed' : 'not-requested'} read-only-restored=${result.read_only_restoration?.ok === true}`);
153
+ }
154
+ else {
155
+ console.error(`MadDB failed: mission=${result.mission_id} blockers=${(result.blockers || []).join(', ') || 'unknown'} read-only-restored=${result.read_only_restoration?.ok === true}`);
156
+ process.exitCode = 1;
157
+ }
158
+ return result;
159
+ }
160
+ function printJsonOrText(result, args, text) {
161
+ if (hasFlag(args, '--json'))
162
+ console.log(JSON.stringify(result, null, 2));
92
163
  else
93
- console.log(`Mad-DB capability revoked for ${missionId}.`);
164
+ console.log(text);
165
+ if (result.ok === false)
166
+ process.exitCode = process.exitCode || 1;
94
167
  return result;
95
168
  }
169
+ function redactCapability(capability) {
170
+ return {
171
+ ...capability,
172
+ project_ref: capability.project_ref ? `<hash:${sha256(capability.project_ref).slice(0, 16)}>` : null,
173
+ transport: capability.transport ? { ...capability.transport, server_url_redacted: capability.transport.server_url_redacted || '<redacted>' } : null
174
+ };
175
+ }
96
176
  function hasFlag(args, flag) {
97
177
  return args.includes(flag);
98
178
  }
@@ -100,7 +180,22 @@ function readOption(args, name, fallback) {
100
180
  const index = args.indexOf(name);
101
181
  if (index >= 0 && args[index + 1] && !String(args[index + 1]).startsWith('--'))
102
182
  return String(args[index + 1]);
103
- const prefixed = args.find((arg) => String(arg).startsWith(name + '='));
183
+ const prefixed = args.find((arg) => String(arg).startsWith(`${name}=`));
104
184
  return prefixed ? prefixed.slice(name.length + 1) : fallback;
105
185
  }
186
+ function positionalText(args) {
187
+ const out = [];
188
+ for (let index = 0; index < args.length; index += 1) {
189
+ const arg = args[index];
190
+ if (!arg)
191
+ continue;
192
+ if (arg.startsWith('--')) {
193
+ if (!arg.includes('=') && args[index + 1] && !String(args[index + 1]).startsWith('--'))
194
+ index += 1;
195
+ continue;
196
+ }
197
+ out.push(arg);
198
+ }
199
+ return out.join(' ').trim();
200
+ }
106
201
  //# sourceMappingURL=mad-db-command.js.map
@@ -19,7 +19,6 @@ import { repairCodexConfigEperm } from '../codex/codex-config-eperm-repair.js';
19
19
  import { runCodexLaunchPreflight } from '../preflight/parallel-preflight-engine.js';
20
20
  import { diffCodexAppUiSnapshots, writeCodexAppUiSnapshot } from '../codex-app/codex-app-ui-state-snapshot.js';
21
21
  import { checkSksUpdateNotice } from '../update/update-notice.js';
22
- import { createMadDbCapability, MAD_DB_ACK } from '../mad-db/mad-db-capability.js';
23
22
  import { writeCodex0138CapabilityArtifacts } from '../codex-control/codex-0138-capability.js';
24
23
  import { writeCodex0139CapabilityArtifacts } from '../codex-control/codex-0139-capability.js';
25
24
  import { resolveCodexNativeInvocationPlan } from '../codex-native/codex-native-invocation-router.js';
@@ -100,7 +99,7 @@ export async function madHighCommand(args = [], deps = {}) {
100
99
  }
101
100
  return report;
102
101
  }
103
- const codexUpdate = deps.maybePromptCodexUpdateForLaunch ? await deps.maybePromptCodexUpdateForLaunch(args, { label: glmMadLaunch ? 'GLM MAD launch' : 'MAD launch' }) : { status: 'skipped' };
102
+ const codexUpdate = { status: 'deferred_background', reason: 'update_prompt_deferred_until_after_mad_ui' };
104
103
  if (codexUpdate.status === 'failed' || codexUpdate.status === 'updated_not_reflected') {
105
104
  console.error(`Codex CLI update failed: ${codexUpdate.error || 'updated version was not visible on PATH'}`);
106
105
  process.exitCode = 1;
@@ -147,14 +146,15 @@ export async function madHighCommand(args = [], deps = {}) {
147
146
  }
148
147
  const lb = glmMadLaunch
149
148
  ? { status: 'skipped_glm_openrouter', ok: false, reason: 'glm_mad_uses_openrouter_directly' }
150
- : deps.maybePromptCodexLbSetupForLaunch ? await deps.maybePromptCodexLbSetupForLaunch(args) : { status: 'skipped' };
149
+ : { status: 'deferred_until_provider_route', ok: true, reason: 'codex_lb_setup_prompt_deferred_until_provider_route' };
151
150
  if (!glmMadLaunch && lb.status === 'missing_api_key') {
152
151
  process.exitCode = 1;
153
152
  return;
154
153
  }
155
154
  const profile = buildMadHighLaunchProfileNoWrite();
156
155
  const uiSnapshotId = Date.now().toString(36);
157
- const beforeUi = await writeCodexAppUiSnapshot(launchRoot, `mad-before-${uiSnapshotId}`).catch(() => null);
156
+ const strictUiSnapshot = process.env.SKS_MAD_STRICT_UI_SNAPSHOT === '1';
157
+ const beforeUi = strictUiSnapshot ? await writeCodexAppUiSnapshot(launchRoot, `mad-before-${uiSnapshotId}`).catch(() => null) : null;
158
158
  // launchFast skips the redundant live-`codex exec` config probe (up to ~20s, run
159
159
  // up to 3x via repair re-inspections): the real codex profile is exercised moments
160
160
  // later when the Zellij session opens. All filesystem/permission/EPERM/symlink/ACL
@@ -202,64 +202,48 @@ export async function madHighCommand(args = [], deps = {}) {
202
202
  process.exitCode = 1;
203
203
  return glmRuntime;
204
204
  }
205
- const madDbCapability = madDbGrant.enabled
206
- ? await createMadDbCapability(madLaunch.root, { missionId: madLaunch.mission_id, ack: madDbGrant.ack, cwd: process.cwd() })
207
- : null;
208
- if (madDbCapability) {
205
+ if (madDbGrant.requested) {
209
206
  const grantReport = {
210
- schema: 'sks.mad-sks-launch-grants.v1',
207
+ schema: 'sks.mad-sks-launch-grants.v2',
211
208
  generated_at: nowIso(),
212
209
  mission_id: madLaunch.mission_id,
213
210
  mad_sks_active: true,
214
- mad_db_active: true,
215
- mad_db_default_grant: madDbGrant.source === 'sks_mad_default',
211
+ mad_db_active: false,
212
+ mad_db_default_grant: false,
216
213
  mad_db_grant_source: madDbGrant.source,
217
- mad_db_one_cycle_only: true,
218
- mad_db_capability_file: 'mad-db-capability.json',
219
- mad_db_cycle_id: madDbCapability.cycle_id,
220
- mad_db_expires_at: madDbCapability.expires_at,
214
+ mad_db_requires_first_class_route: true,
215
+ mad_db_cli: 'sks mad-db run|exec|apply-migration',
216
+ mad_db_capability_file: null,
221
217
  standalone_mad_db_enable_still_requires_ack: true
222
218
  };
223
219
  await writeJsonAtomic(path.join(madLaunch.dir, 'mad-sks-launch-grants.json'), grantReport);
224
- await setCurrent(madLaunch.root, {
225
- mission_id: madLaunch.mission_id,
226
- mad_db_active: true,
227
- mad_db_cycle_id: madDbCapability.cycle_id,
228
- mad_db_capability_file: 'mad-db-capability.json',
229
- mad_db_break_glass: true,
230
- mad_db_default_grant: madDbGrant.source === 'sks_mad_default',
231
- mad_db_grant_source: madDbGrant.source,
232
- mad_db_one_cycle_only: true,
233
- mad_db_priority_override_active: true,
234
- mad_sks_launch_grants_file: 'mad-sks-launch-grants.json'
235
- });
236
- await appendJsonlBounded(path.join(madLaunch.dir, 'events.jsonl'), { ts: nowIso(), type: 'mad_db.capability_created', grant_source: madDbGrant.source, cycle_id: madDbCapability.cycle_id, expires_at: madDbCapability.expires_at });
220
+ await appendJsonlBounded(path.join(madLaunch.dir, 'events.jsonl'), { ts: nowIso(), type: 'mad_db.first_class_route_required', grant_source: madDbGrant.source, cli: grantReport.mad_db_cli });
237
221
  }
238
- const updateNotice = await checkSksUpdateNotice({
239
- packageName: deps.packageName || 'sneakoscope',
240
- currentVersion: deps.packageVersion || PACKAGE_VERSION,
241
- missionDir: madLaunch.dir
242
- }).catch((err) => ({
222
+ const updateNotice = {
243
223
  schema: 'sks.update-notice.v1',
244
224
  checked_at: nowIso(),
245
225
  package_name: deps.packageName || 'sneakoscope',
246
226
  current_version: deps.packageVersion || PACKAGE_VERSION,
247
227
  latest_version: null,
248
228
  update_available: false,
249
- source: 'error',
229
+ source: 'deferred_background',
250
230
  cache_ttl_ms: 0,
251
- message: 'SKS update notice check failed; MAD launch continues.',
252
- error: err?.message || String(err)
253
- }));
231
+ message: 'SKS update notice refresh deferred until after MAD UI launch.'
232
+ };
233
+ void checkSksUpdateNotice({
234
+ packageName: deps.packageName || 'sneakoscope',
235
+ currentVersion: deps.packageVersion || PACKAGE_VERSION,
236
+ missionDir: madLaunch.dir
237
+ }).then((notice) => appendJsonlBounded(path.join(madLaunch.dir, 'events.jsonl'), { ts: nowIso(), type: 'mad_sks.update_notice_refreshed_background', non_blocking: true, update_available: notice.update_available === true, source: notice.source })).catch((err) => appendJsonlBounded(path.join(madLaunch.dir, 'events.jsonl'), { ts: nowIso(), type: 'mad_sks.update_notice_background_failed', error: err?.message || String(err) }));
254
238
  await appendJsonlBounded(path.join(madLaunch.dir, 'events.jsonl'), { ts: nowIso(), type: 'mad_sks.update_notice_checked', non_blocking: true, update_available: updateNotice.update_available === true, source: updateNotice.source });
255
239
  console.log(`SKS MAD ready: ${glmRuntime?.profile?.profile_name || madHighProfileName()} | gate ${madLaunch.mission_id}`);
256
240
  if (glmRuntime?.profile)
257
241
  console.log(`GLM MAD launch active: ${glmRuntime.profile.model} via OpenRouter; GPT fallback blocked.`);
258
- if (madDbCapability)
259
- console.log(`MAD-DB one-cycle capability active (${madDbGrant.source}); expires ${madDbCapability.expires_at}.`);
242
+ if (madDbGrant.requested)
243
+ console.log('MAD-DB flag observed; use the first-class route: sks mad-db run|exec|apply-migration.');
260
244
  if (updateNotice.update_available === true)
261
245
  console.log(`SKS update notice: ${updateNotice.latest_version} available (non-blocking).`);
262
- console.log('Scoped high-power maintenance authority active; add explicit --allow-* flags for packages, services, network, browser/Computer Use, generated assets, file permissions, or system/admin scopes. MAD-DB one-cycle DB break-glass is already active for this launch; protected-core, audit, and one-cycle bounds remain.');
246
+ console.log('Scoped high-power maintenance authority active; add explicit --allow-* flags for packages, services, network, browser/Computer Use, generated assets, file permissions, or system/admin scopes. MAD-DB SQL-plane execution is not active in MAD-SKS; use the first-class MadDB route for DROP/TRUNCATE/all-row SQL-plane work.');
263
247
  const launchLb = lb.status === 'present' ? { ...lb, status: 'configured' } : lb;
264
248
  const madSksEnv = {
265
249
  SKS_PROTECTED_CORE_POLICY: madLaunch.gate.protected_core_policy,
@@ -311,7 +295,7 @@ export async function madHighCommand(args = [], deps = {}) {
311
295
  worker_panes_created: 0,
312
296
  right_column_mode: 'spawn-on-first-worker'
313
297
  });
314
- const madNativeSwarm = await startMadNativeSwarm(madLaunch.root, madLaunch, args, launchProfile, {
298
+ const madNativeSwarmPromise = startMadNativeSwarm(madLaunch.root, madLaunch, args, launchProfile, {
315
299
  env: {
316
300
  ...madSksEnv,
317
301
  ...(launch.session_name ? { SKS_ZELLIJ_SESSION_NAME: launch.session_name } : {})
@@ -320,7 +304,8 @@ export async function madHighCommand(args = [], deps = {}) {
320
304
  zellijSessionName: launch.session_name || null,
321
305
  workerPlacement: headlessZellij ? 'process' : shouldAutoAttachZellij(args) ? 'zellij-pane' : 'process',
322
306
  zellijVisiblePaneCap: Number(process.env.SKS_ZELLIJ_VISIBLE_PANE_CAP || 8)
323
- });
307
+ }).catch((err) => appendJsonlBounded(path.join(madLaunch.dir, 'events.jsonl'), { ts: nowIso(), type: 'mad_sks.native_swarm_background_failed', error: err?.message || String(err) }));
308
+ void madNativeSwarmPromise;
324
309
  // The launcher only creates a detached background session. In an interactive
325
310
  // terminal, immediately attach so the session actually opens for the user
326
311
  // instead of leaving them to copy/paste the attach command by hand.
@@ -409,10 +394,11 @@ function buildGlmMadLaunchOpts(cleanArgs = [], opts = {}) {
409
394
  }
410
395
  export function resolveMadLaunchMadDbGrant(args = []) {
411
396
  const list = (args || []).map((arg) => String(arg));
397
+ const requested = list.includes('--mad-db');
412
398
  return {
413
- enabled: true,
414
- source: list.includes('--mad-db') ? 'sks_mad_explicit_redundant_flag' : 'sks_mad_default',
415
- ack: MAD_DB_ACK,
399
+ enabled: false,
400
+ requested,
401
+ source: requested ? 'mad_db_first_class_route_required' : 'not_requested',
416
402
  one_cycle_only: true
417
403
  };
418
404
  }
@@ -646,16 +632,7 @@ async function activateMadZellijPermissionState(cwd = process.cwd(), args = [])
646
632
  const has = (scope) => allowedScopes.has(scope);
647
633
  const dbWriteAllowed = has('db_write');
648
634
  const { id, dir } = await createMission(root, { mode: 'mad-sks', prompt: `${activatedBy} Zellij scoped high-power maintenance session` });
649
- await writeCodex0138CapabilityArtifacts(root, { missionId: id }).catch(() => null);
650
- await writeCodex0139CapabilityArtifacts(root, { missionId: id }).catch(() => null);
651
- const codexNativeInvocation = await resolveCodexNativeInvocationPlan({
652
- root,
653
- missionId: id,
654
- route: '$MAD',
655
- desiredCapability: 'hook-evidence'
656
- }).catch(() => null);
657
- if (codexNativeInvocation)
658
- await writeJsonAtomic(path.join(dir, 'mad-codex-native-invocation.json'), codexNativeInvocation).catch(() => undefined);
635
+ void refreshMadNativeLaunchArtifacts(root, id, dir).catch((err) => appendJsonlBounded(path.join(dir, 'events.jsonl'), { ts: nowIso(), type: 'mad_sks.native_artifact_background_failed', error: err?.message || String(err) }));
659
636
  const protectedCore = resolveProtectedCore({ packageRoot: packageRoot(), targetRoot: cwd });
660
637
  // The interactive launch 'before' snapshot is only persisted (env + policy json)
661
638
  // and is never compared against an 'after' snapshot during the session, so the
@@ -699,13 +676,13 @@ async function activateMadZellijPermissionState(cwd = process.cwd(), args = [])
699
676
  protected_core_policy: protectedCorePolicyPath,
700
677
  protected_core_before: protectedCoreBeforePath,
701
678
  protected_core_digest: protectedCoreBefore.digest,
702
- codex_native_invocation_plan: codexNativeInvocation ? {
703
- selected_strategy: codexNativeInvocation.selected_strategy,
704
- hook_evidence_policy: codexNativeInvocation.env.SKS_CODEX_NATIVE_HOOK_EVIDENCE_POLICY,
705
- blockers: codexNativeInvocation.blockers,
706
- warnings: codexNativeInvocation.warnings,
679
+ codex_native_invocation_plan: {
680
+ selected_strategy: 'message-role-fallback',
681
+ hook_evidence_policy: 'background-verification-do-not-count-until-refreshed',
682
+ blockers: [],
683
+ warnings: ['native_invocation_plan_deferred_until_after_ui'],
707
684
  artifact_path: 'mad-codex-native-invocation.json'
708
- } : null,
685
+ },
709
686
  activated_by: activatedBy,
710
687
  cwd: path.resolve(cwd || process.cwd())
711
688
  };
@@ -740,6 +717,19 @@ async function activateMadZellijPermissionState(cwd = process.cwd(), args = [])
740
717
  });
741
718
  return { mission_id: id, dir, gate, root };
742
719
  }
720
+ async function refreshMadNativeLaunchArtifacts(root, missionId, dir) {
721
+ await writeCodex0138CapabilityArtifacts(root, { missionId }).catch(() => null);
722
+ await writeCodex0139CapabilityArtifacts(root, { missionId }).catch(() => null);
723
+ const codexNativeInvocation = await resolveCodexNativeInvocationPlan({
724
+ root,
725
+ missionId,
726
+ route: '$MAD',
727
+ desiredCapability: 'hook-evidence'
728
+ }).catch(() => null);
729
+ if (codexNativeInvocation)
730
+ await writeJsonAtomic(path.join(dir, 'mad-codex-native-invocation.json'), codexNativeInvocation).catch(() => undefined);
731
+ await appendJsonlBounded(path.join(dir, 'events.jsonl'), { ts: nowIso(), type: 'mad_sks.native_artifacts_refreshed_background', ok: Boolean(codexNativeInvocation) });
732
+ }
743
733
  function baseMadLaunchOnlyFlags() {
744
734
  return new Set([
745
735
  '--mad',
@@ -3,9 +3,10 @@ import { exists, readJson, writeJsonAtomic, readText, nowIso, appendJsonlBounded
3
3
  import { missionDir, setCurrent } from './mission.js';
4
4
  import { evaluateMadSksPermissionGate, isMadSksRouteState } from './permission-gates.js';
5
5
  import { resolveMadDbMutationPolicy } from './mad-db/mad-db-policy-resolver.js';
6
- import { recordMadDbOperation } from './mad-db/mad-db-capability.js';
7
- import { appendMadDbLedgerEvent, appendMadDbOperationLifecycle } from './mad-db/mad-db-ledger.js';
8
- import { lifecycleHookFromUnknown, recordPendingMadDbLifecycleHook } from './mad-db/mad-db-result-lifecycle.js';
6
+ import { appendMadDbLedgerEvent } from './mad-db/mad-db-ledger.js';
7
+ import { lifecycleHookFromUnknown } from './mad-db/mad-db-result-lifecycle.js';
8
+ import { extractCanonicalToolCallId, reserveMadDbOperation, transitionMadDbOperation } from './mad-db/mad-db-operation-store.js';
9
+ import { madDbOperationClassesFromClassification } from './mad-db/mad-db-policy.js';
9
10
  export const DEFAULT_DB_SAFETY_POLICY = Object.freeze({
10
11
  schema_version: 1,
11
12
  mode: 'read_only_default',
@@ -511,19 +512,29 @@ export async function checkDbOperation(root, state, payload, { duringNoQuestion
511
512
  const madDb = await resolveMadDbMutationPolicy(root, state, classification);
512
513
  if (madDb.allowed === true && state?.mission_id) {
513
514
  const madDbDecision = madDb;
514
- const operationId = `mad-db-op-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
515
- const sqlHash = classification.sql?.statements?.length ? sha256(String(classification.sql.statements.join('\n'))) : null;
516
- await appendMadDbOperationLifecycle(root, state.mission_id, {
517
- type: 'db_operation.started',
518
- operationId,
519
- cycleId: madDbDecision.cycle_id,
520
- toolName: classification.toolName || null,
521
- sqlHash,
522
- destructive: classification.level === 'destructive'
515
+ const sqlText = classification.sql?.statements?.length ? String(classification.sql.statements.join('\n')) : null;
516
+ const sqlHash = sqlText ? sha256(sqlText) : null;
517
+ const toolCallId = extractCanonicalToolCallId(payload) || `payload-${sha256(JSON.stringify({ tool: classification.toolName || '', sqlHash, level: classification.level })).slice(0, 16)}`;
518
+ const operationClasses = madDbDecision.operation_classes?.length ? madDbDecision.operation_classes : madDbOperationClassesFromClassification(classification);
519
+ const reservation = await reserveMadDbOperation({
520
+ root,
521
+ missionId: String(state.mission_id),
522
+ capability: madDbDecision.capability,
523
+ toolCallId,
524
+ toolName: classification.toolName || 'unknown_database_tool',
525
+ sql: sqlText,
526
+ operationClasses
527
+ });
528
+ await transitionMadDbOperation({
529
+ root,
530
+ missionId: String(state.mission_id),
531
+ toolCallId,
532
+ state: 'started'
523
533
  });
524
534
  const lifecycleHook = {
525
535
  mission_id: String(state.mission_id),
526
- operation_id: operationId,
536
+ operation_id: reservation.operation.operation_id,
537
+ tool_call_id: toolCallId,
527
538
  cycle_id: madDbDecision.cycle_id || null,
528
539
  tool_name: classification.toolName || null,
529
540
  sql_hash: sqlHash,
@@ -538,35 +549,22 @@ export async function checkDbOperation(root, state, payload, { duringNoQuestion
538
549
  mad_db: {
539
550
  active: true,
540
551
  priority: 'highest',
552
+ capability_schema: 'sks.mad-db-capability.v2',
541
553
  one_cycle_only: true,
542
554
  cycle_id: madDbDecision.cycle_id,
543
555
  capability_file: 'mad-db-capability.json',
544
- consumed: false,
545
- operation_id: operationId,
556
+ status: reservation.capability.status,
557
+ operation_id: reservation.operation.operation_id,
558
+ tool_call_id: toolCallId,
559
+ tool_call_id_missing: extractCanonicalToolCallId(payload) === null,
546
560
  lifecycle_result_pending: true,
547
561
  ledger_result_hook: lifecycleHook,
548
- operation_count: Number(madDbDecision.operation_count || 0) + 1,
549
- max_operations: madDbDecision.max_operations || 20
562
+ operation_classes: operationClasses,
563
+ counters: reservation.capability.counters,
564
+ idempotent_reservation_reused: reservation.reused
550
565
  }
551
566
  };
552
- await appendMadDbLedgerEvent(root, state.mission_id, { type: 'db_mutation.allowed', cycle_id: madDbDecision.cycle_id, mode: madDbDecision.mode, classification, operation_id: operationId });
553
- await appendMadDbOperationLifecycle(root, state.mission_id, {
554
- type: 'db_operation.allowed',
555
- operationId,
556
- cycleId: madDbDecision.cycle_id,
557
- toolName: classification.toolName || null,
558
- sqlHash,
559
- destructive: classification.level === 'destructive',
560
- resultStatus: 'unknown_pending_tool_result'
561
- });
562
- const updatedCapability = await recordMadDbOperation(root, state.mission_id, {
563
- operationId,
564
- ...(classification.toolName ? { toolName: classification.toolName } : {}),
565
- ...(sqlHash ? { sqlHash } : {})
566
- });
567
- decision.mad_db.consumed = updatedCapability?.consumed === true;
568
- decision.mad_db.operation_count = updatedCapability?.operation_count ?? decision.mad_db.operation_count;
569
- await recordPendingMadDbLifecycleHook(root, state.mission_id, lifecycleHook);
567
+ await appendMadDbLedgerEvent(root, state.mission_id, { type: 'db_mutation.allowed', cycle_id: madDbDecision.cycle_id, mode: madDbDecision.mode, classification, operation_id: reservation.operation.operation_id, tool_call_id: toolCallId });
570
568
  await appendJsonlBounded(path.join(missionDir(root, state.mission_id), 'db-safety.jsonl'), { ts: nowIso(), decision });
571
569
  return decision;
572
570
  }
@@ -605,8 +603,8 @@ export function dbBlockReason(decision) {
605
603
  return [
606
604
  'Sneakoscope Codex Database Safety Gate blocked this operation.',
607
605
  `Reasons: ${(decision.reasons || []).join(', ') || 'unknown'}.`,
608
- 'Destructive database operations are never allowed. Production writes are forbidden. Supabase/Postgres MCP write tools must not be used for live destructive changes.',
609
- 'Use read-only/project-scoped Supabase MCP URLs, create migration files, and apply them only to local or preview/branch environments when explicitly allowed by the sealed contract.'
606
+ 'Default DB mode is read-only. Destructive SQL-plane operations require an explicit active MadDB v2 capability opened by $MAD-DB or sks mad-db run|exec|apply-migration.',
607
+ 'Use read-only/project-scoped Supabase MCP URLs outside MadDB. Supabase project/account/billing/credential control-plane operations remain denied even in MadDB.'
610
608
  ].join(' ');
611
609
  }
612
610
  export async function scanDbSafety(root, opts = {}) {
@@ -3,7 +3,6 @@ import path from 'node:path';
3
3
  import { MANAGED_ASSET_VERSION } from '../managed-assets/managed-assets-manifest.js';
4
4
  import { PACKAGE_VERSION, packageRoot, sha256 } from '../fsx.js';
5
5
  import { hashJson } from '../triwiki/triwiki-cache-key.js';
6
- import { triWikiProofBankDir } from '../triwiki/triwiki-proof-bank.js';
7
6
  export const DOCTOR_DIRTY_PLAN_SCHEMA = 'sks.doctor-dirty-plan.v2';
8
7
  export function planDoctorDirtyRepair(root, phaseIds) {
9
8
  const phases = phaseIds.map((id) => {
@@ -205,10 +204,16 @@ function proofExists(root, proofId) {
205
204
  const transaction = path.join(root, '.sneakoscope', 'reports', 'doctor-fix-transaction.json');
206
205
  if (fs.existsSync(transaction) && fs.readFileSync(transaction, 'utf8').includes(proofId))
207
206
  return true;
208
- const bank = triWikiProofBankDir(root);
209
- if (!fs.existsSync(bank))
207
+ const index = path.join(root, '.sneakoscope', 'cache', 'proof-index.json');
208
+ if (!fs.existsSync(index))
210
209
  return false;
211
- return walkFiles(bank).some((file) => path.basename(file) === `${proofId}.json` || fs.readFileSync(file, 'utf8').includes(proofId));
210
+ try {
211
+ const text = fs.readFileSync(index, 'utf8');
212
+ return text.includes(`"${proofId}"`) || text.includes(proofId);
213
+ }
214
+ catch {
215
+ return false;
216
+ }
212
217
  }
213
218
  function phaseRequiresPostcheck(id) {
214
219
  return /zellij|context7|startup|supabase|native|secret/i.test(id);