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
@@ -24,16 +24,33 @@ const matrix = buildDoctorReadinessMatrix({
24
24
  ]
25
25
  },
26
26
  codex_doctor: codexDoctor,
27
- require_codex_doctor: true
27
+ require_codex_doctor: true,
28
+ doctor_native_capability: {
29
+ ok: true,
30
+ blockers: [],
31
+ optional_warnings: ['computer_use_manual_required', 'chrome_extension_manual_required'],
32
+ native_capabilities: {
33
+ capabilities: [
34
+ { id: 'computer_use', availability: 'manual-required', repairability: 'manual-required', after: 'unknown' },
35
+ { id: 'chrome_web_review', availability: 'manual-required', repairability: 'manual-required', after: 'unknown' }
36
+ ],
37
+ route_blockers: {
38
+ 'route-computer-use': ['computer_use_os_permission_or_capability_unknown'],
39
+ 'route-chrome-web-review': ['codex_chrome_extension_readiness_not_verified']
40
+ }
41
+ }
42
+ }
28
43
  });
29
44
  const report = {
30
45
  schema: 'sks.doctor-warning-only-not-blocker-check.v1',
31
46
  ready: matrix.ready,
32
47
  core_ready: matrix.core_ready,
33
48
  primary_blocker: matrix.primary_blocker,
49
+ optional_capabilities: matrix.optional_capabilities,
34
50
  blockers: matrix.blockers,
35
51
  warnings: matrix.warnings
36
52
  };
37
53
  assertGate(matrix.ready === true && matrix.primary_blocker === null && matrix.blockers.length === 0, 'warning-only Codex Doctor must not block readiness', report);
54
+ assertGate(matrix.optional_capabilities.computer_use === 'manual_required' && matrix.optional_capabilities.chrome_web_review === 'manual_required', 'optional native capabilities must remain route-gated warnings', report);
38
55
  emitGate('doctor:warning-only-not-blocker', report);
39
56
  //# sourceMappingURL=doctor-warning-only-not-blocker-check.js.map
@@ -343,8 +343,9 @@ async function readJson(file) {
343
343
  return JSON.parse(await fs.readFile(file, 'utf8'));
344
344
  }
345
345
  async function productionFixtureNegativeCheck() {
346
+ const runtimeModuleUrl = new URL('../core/loops/loop-worker-runtime.js', import.meta.url).href;
346
347
  const code = `
347
- import { runLoopMakerWorkers } from '../core/loops/loop-worker-runtime.js';
348
+ import { runLoopMakerWorkers } from ${JSON.stringify(runtimeModuleUrl)};
348
349
  const node = {
349
350
  mission_id: 'M-production-fixture-negative',
350
351
  loop_id: 'loop-production-fixture-negative',
@@ -7,9 +7,20 @@ const missionMod = await importDist('core/mission.js');
7
7
  const capMod = await importDist('core/mad-db/mad-db-capability.js');
8
8
  const root = fs.mkdtempSync(path.join(os.tmpdir(), 'sks-mad-db-cap-'));
9
9
  const mission = await missionMod.createMission(root, { mode: 'mad-db', prompt: 'fixture' });
10
- const cap = await capMod.createMadDbCapability(root, { missionId: mission.id, ack: capMod.MAD_DB_ACK, cwd: root });
10
+ const cap = await capMod.createMadDbCapability(root, {
11
+ missionId: mission.id,
12
+ ack: capMod.MAD_DB_ACK,
13
+ cwd: root,
14
+ projectRef: 'fixture-project-ref',
15
+ runtimeSessionId: 'fixture-session',
16
+ profilePath: '.sneakoscope/missions/M/mad-db/runtime/codex-mad-db.config.toml',
17
+ profileSha256: 'fixture-profile-sha',
18
+ status: 'active'
19
+ });
11
20
  assertGate(cap.schema === capMod.MAD_DB_CAPABILITY_SCHEMA, 'Mad-DB capability schema mismatch', cap);
12
- assertGate(cap.enabled === true && cap.one_cycle_only === true && cap.priority === 'highest', 'Mad-DB capability must be one-cycle highest priority', cap);
21
+ assertGate(cap.legacy_compat?.one_cycle_only === true && cap.legacy_compat?.priority === 'highest', 'Mad-DB capability must retain legacy one-cycle priority metadata', cap);
22
+ assertGate(cap.project_ref === 'fixture-project-ref' && cap.runtime_session_id === 'fixture-session' && cap.transport.profile_sha256 === 'fixture-profile-sha', 'Mad-DB capability v2 must bind project/session/profile', cap);
23
+ assertGate(cap.scope.sql_plane === 'all_mutations' && cap.scope.control_plane === 'deny' && cap.scope.operations.includes('truncate'), 'Mad-DB capability v2 must authorize SQL-plane operation classes only', cap);
13
24
  assertGate(capMod.isMadDbCapabilityActive(cap) === true, 'Mad-DB capability must be active before consumption', cap);
14
25
  emitGate('mad-db:capability', { mission_id: mission.id, cycle_id: cap.cycle_id });
15
26
  //# sourceMappingURL=mad-db-capability-check.js.map
@@ -3,11 +3,13 @@ import { DOLLAR_COMMAND_ALIASES, DOLLAR_COMMANDS, routeByDollarCommand } from '.
3
3
  import { assertGate, emitGate, readText } from './sks-1-18-gate-lib.js';
4
4
  assertGate(readText('src/cli/command-registry.ts').includes("'mad-db'"), 'mad-db command must be registered');
5
5
  assertGate(readText('src/commands/mad-db.ts').includes('madDbCommand'), 'mad-db command wrapper missing');
6
- assertGate(readText('src/core/commands/mad-db-command.ts').includes('I AUTHORIZE ONE-CYCLE DB BREAK-GLASS'), 'mad-db command must require exact ack phrase');
6
+ assertGate(readText('src/core/commands/mad-db-command.ts').includes('deprecated_enable_no_capability'), 'legacy mad-db enable must be deprecated and must not create capabilities');
7
7
  assertGate(DOLLAR_COMMANDS.some((entry) => entry.command === '$MAD-DB'), '$MAD-DB dollar command must be visible in sks dollar-commands');
8
- assertGate(DOLLAR_COMMAND_ALIASES.some((entry) => entry.canonical === '$MAD-SKS' && entry.app_skill === '$mad-db'), '$mad-db app skill alias must be visible in sks dollar-commands');
9
- assertGate(routeByDollarCommand('MAD-DB')?.command === '$MAD-SKS', '$MAD-DB must resolve to the MAD-SKS permission route');
10
- assertGate(routeByDollarCommand('mad-db')?.command === '$MAD-SKS', '$mad-db must resolve to the MAD-SKS permission route');
11
- assertGate(readText('src/core/init.ts').includes("'mad-db':") && readText('src/core/init.ts').includes('sks mad-db enable'), 'mad-db generated picker skill template missing');
8
+ assertGate(DOLLAR_COMMAND_ALIASES.some((entry) => entry.canonical === '$MAD-DB' && entry.app_skill === '$mad-db'), '$mad-db app skill alias must point at first-class $MAD-DB');
9
+ assertGate(routeByDollarCommand('MAD-DB')?.command === '$MAD-DB', '$MAD-DB must resolve to the first-class MadDB route');
10
+ assertGate(routeByDollarCommand('mad-db')?.command === '$MAD-DB', '$mad-db must resolve to the first-class MadDB route');
11
+ const initText = readText('src/core/init.ts');
12
+ assertGate(initText.includes("'mad-db':") && initText.includes('madDbSkillText()') && initText.includes('dbSafetyGuardSkillText()'), 'mad-db generated picker skill template must come from typed SSOT');
13
+ assertGate(readText('src/core/commands/mad-db-command.ts').includes('run|exec|apply-migration'), 'mad-db command must expose execution subcommands');
12
14
  emitGate('mad-db:command', { command: 'sks mad-db', dollar_command: '$MAD-DB', app_skill_alias: '$mad-db' });
13
15
  //# sourceMappingURL=mad-db-command-check.js.map
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'node:fs';
3
+ import os from 'node:os';
4
+ import path from 'node:path';
5
+ import { createMission } from '../core/mission.js';
6
+ import { checkDbOperation } from '../core/db-safety.js';
7
+ import { createMadDbCapability, MAD_DB_ACK, readMadDbCapability } from '../core/mad-db/mad-db-capability.js';
8
+ import { assertGate, emitGate } from './sks-1-18-gate-lib.js';
9
+ const root = fs.mkdtempSync(path.join(os.tmpdir(), 'sks-mad-db-idempotency-'));
10
+ const mission = await createMission(root, { mode: 'mad-db', prompt: 'idempotency fixture' });
11
+ await createMadDbCapability(root, { missionId: mission.id, ack: MAD_DB_ACK, cwd: root, projectRef: 'fixture-project-ref', status: 'active' });
12
+ const payload = { tool_name: 'supabase.execute_sql', tool_call_id: 'canonical-call-id-1', sql: 'delete from public.fixture;' };
13
+ const first = await checkDbOperation(root, { mission_id: mission.id }, payload);
14
+ const second = await checkDbOperation(root, { mission_id: mission.id }, payload);
15
+ const cap = await readMadDbCapability(root, mission.id);
16
+ assertGate(first.allowed === true && second.allowed === true, 'same canonical call should be allowed while active', { first, second });
17
+ assertGate(first.mad_db.operation_id === second.mad_db.operation_id, 'same canonical tool_call_id must map to the same operation', { first, second });
18
+ assertGate(second.mad_db.idempotent_reservation_reused === true, 'second reservation must be marked reused', second);
19
+ assertGate(Boolean(cap) && cap.counters.attempts === 1 && cap.counters.reserved === 1, 'PreToolUse/PermissionRequest duplicate handling must not double-count one call', cap || {});
20
+ emitGate('mad-db:hook-idempotency', { operation_id: first.mad_db.operation_id, counters: cap.counters });
21
+ //# sourceMappingURL=mad-db-hook-idempotency-check.js.map
@@ -2,6 +2,7 @@
2
2
  import { assertGate, emitGate, readText } from './sks-1-18-gate-lib.js';
3
3
  const ledger = readText('src/core/mad-db/mad-db-ledger.ts');
4
4
  const cap = readText('src/core/mad-db/mad-db-capability.ts');
5
- assertGate(ledger.includes('mad-db-ledger.jsonl') && cap.includes('capability.consumed'), 'Mad-DB ledger must record lifecycle and consumption events');
5
+ assertGate(ledger.includes('mad-db-ledger.jsonl') && cap.includes('mad-db-capability.closed.json'), 'Mad-DB ledger must record lifecycle and closed capability events');
6
+ assertGate(!ledger.includes('unknown_pending_tool_result'), 'Mad-DB ledger must not use old pending-latest fallback wording');
6
7
  emitGate('mad-db:ledger', { file: 'mad-db-ledger.jsonl' });
7
8
  //# sourceMappingURL=mad-db-ledger-check.js.map
@@ -5,13 +5,14 @@ import os from 'node:os';
5
5
  import path from 'node:path';
6
6
  import { checkDbOperation, madDbLifecycleHookFromDecision } from '../core/db-safety.js';
7
7
  import { createMadDbCapability, MAD_DB_ACK } from '../core/mad-db/mad-db-capability.js';
8
+ import { createMission } from '../core/mission.js';
8
9
  import { assertGate, emitGate } from './sks-1-18-gate-lib.js';
9
10
  const root = await fs.mkdtemp(path.join(os.tmpdir(), 'sks-mad-db-hook-decision-'));
10
- const missionId = 'M-mad-db-hook-decision';
11
- await createMadDbCapability(root, { missionId, ack: MAD_DB_ACK, ttlMs: 60000 });
12
- const decision = await checkDbOperation(root, { mission_id: missionId }, { tool_name: 'supabase.execute_sql', sql: 'insert into audit_log(id) values (1)' });
11
+ const mission = await createMission(root, { mode: 'mad-db', prompt: 'hook fixture' });
12
+ await createMadDbCapability(root, { missionId: mission.id, ack: MAD_DB_ACK, ttlMs: 60000, projectRef: 'fixture-project-ref', status: 'active' });
13
+ const decision = await checkDbOperation(root, { mission_id: mission.id }, { tool_name: 'supabase.execute_sql', tool_call_id: 'hook-decision-call-1', sql: 'insert into audit_log(id) values (1)' });
13
14
  const hook = madDbLifecycleHookFromDecision(decision);
14
15
  assertGate(decision.allowed === true && decision.mad_db?.lifecycle_result_pending === true, 'Mad-DB decision must mark pending lifecycle result', decision);
15
- assertGate(Boolean(hook?.mission_id === missionId && hook?.operation_id && hook?.cycle_id && hook?.tool_name), 'Mad-DB decision must expose ledger result hook', { decision, hook });
16
+ assertGate(Boolean(hook?.mission_id === mission.id && hook?.operation_id && hook?.tool_call_id === 'hook-decision-call-1' && hook?.cycle_id && hook?.tool_name), 'Mad-DB decision must expose canonical tool_call_id ledger result hook', { decision, hook });
16
17
  emitGate('mad-db:lifecycle-hook-decision', { operation_id: hook.operation_id, cycle_id: hook.cycle_id });
17
18
  //# sourceMappingURL=mad-db-lifecycle-hook-decision-check.js.map
@@ -3,7 +3,7 @@ import assert from 'node:assert/strict';
3
3
  import fs from 'node:fs/promises';
4
4
  import os from 'node:os';
5
5
  import path from 'node:path';
6
- import { madHighCommand } from '../core/commands/mad-sks-command.js';
6
+ import { madHighCommand, resolveMadLaunchMadDbGrant } from '../core/commands/mad-sks-command.js';
7
7
  import { checkDbOperation } from '../core/db-safety.js';
8
8
  import { assertGate, emitGate } from './sks-1-18-gate-lib.js';
9
9
  const original = {
@@ -53,27 +53,29 @@ try {
53
53
  assertGate(launch?.ok === true && launch.status === 'headless-fallback', 'sks --mad fixture launch must complete headless', launch);
54
54
  const state = await readJson(path.join(tmp, '.sneakoscope', 'state', 'current.json'));
55
55
  assert.equal(state.mad_sks_active, true);
56
- assert.equal(state.mad_db_active, true);
57
- assert.equal(state.mad_db_grant_source, 'sks_mad_default');
58
- assert.equal(state.mad_db_priority_override_active, true);
56
+ assert.notEqual(state.mad_db_active, true);
57
+ assert.notEqual(state.mad_db_grant_source, 'sks_mad_default');
58
+ assert.notEqual(state.mad_db_priority_override_active, true);
59
59
  const missionDir = path.join(tmp, '.sneakoscope', 'missions', state.mission_id);
60
- const grants = await readJson(path.join(missionDir, 'mad-sks-launch-grants.json'));
61
- const capability = await readJson(path.join(missionDir, 'mad-db-capability.json'));
62
- assert.equal(grants.mad_sks_active, true);
63
- assert.equal(grants.mad_db_active, true);
64
- assert.equal(grants.mad_db_default_grant, true);
65
- assert.equal(capability.enabled, true);
66
- assert.equal(capability.one_cycle_only, true);
67
- assert.equal(capability.consumed, false);
60
+ await assertMissing(path.join(missionDir, 'mad-db-capability.json'), 'bare sks --mad must not create a MadDB capability');
61
+ await assertMissing(path.join(missionDir, 'mad-sks-launch-grants.json'), 'bare sks --mad must not create MadDB grant artifacts');
68
62
  const decision = await checkDbOperation(tmp, state, {
69
63
  tool_name: 'supabase.execute_sql',
70
- sql: "insert into sks_mad_db_probe(message) values ('default grant proof');"
64
+ tool_call_id: 'mad-sks-default-does-not-open-maddb',
65
+ sql: 'truncate sks_mad_db_probe;'
71
66
  });
72
- assertGate(decision.allowed === true && decision.mad_db?.active === true, 'sks --mad default MAD-DB grant must satisfy DB mutation policy locally', decision);
67
+ assertGate(decision.allowed === false && decision.mad_db?.active !== true, 'sks --mad default must not satisfy MadDB mutation policy locally', decision);
68
+ const defaultGrant = resolveMadLaunchMadDbGrant([]);
69
+ const explicitGrant = resolveMadLaunchMadDbGrant(['--mad-db']);
70
+ assert.equal(defaultGrant.enabled, false);
71
+ assert.equal(defaultGrant.requested, false);
72
+ assert.equal(explicitGrant.enabled, false);
73
+ assert.equal(explicitGrant.requested, true);
74
+ assert.equal(explicitGrant.source, 'mad_db_first_class_route_required');
73
75
  emitGate('mad-db:mad-command', {
74
76
  mission_id: state.mission_id,
75
- grant_source: state.mad_db_grant_source,
76
- cycle_id: capability.cycle_id
77
+ default_mad_db_active: state.mad_db_active === true,
78
+ explicit_flag_source: explicitGrant.source
77
79
  });
78
80
  }
79
81
  finally {
@@ -91,6 +93,17 @@ finally {
91
93
  async function readJson(file) {
92
94
  return JSON.parse(await fs.readFile(file, 'utf8'));
93
95
  }
96
+ async function assertMissing(file, message) {
97
+ try {
98
+ await fs.access(file);
99
+ assertGate(false, message, { file });
100
+ }
101
+ catch (err) {
102
+ if (err?.code === 'ENOENT')
103
+ return;
104
+ throw err;
105
+ }
106
+ }
94
107
  function restoreEnv(key, value) {
95
108
  if (value == null)
96
109
  delete process.env[key];
@@ -6,25 +6,26 @@ import path from 'node:path';
6
6
  import { checkDbOperation, madDbLifecycleHookFromDecision } from '../core/db-safety.js';
7
7
  import { evaluateHookPayload } from '../core/hooks-runtime.js';
8
8
  import { createMadDbCapability, MAD_DB_ACK } from '../core/mad-db/mad-db-capability.js';
9
- import { missionDir } from '../core/mission.js';
9
+ import { createMission, missionDir } from '../core/mission.js';
10
10
  import { assertGate, emitGate } from './sks-1-18-gate-lib.js';
11
11
  const root = await fs.mkdtemp(path.join(os.tmpdir(), 'sks-mad-db-mcp-result-'));
12
- const missionId = 'M-mad-db-mcp-result';
13
- await createMadDbCapability(root, { missionId, ack: MAD_DB_ACK, ttlMs: 60000 });
14
- const successPayload = { tool_name: 'supabase.execute_sql', sql: 'insert into audit_log(id) values (1)' };
15
- const successDecision = await checkDbOperation(root, { mission_id: missionId }, successPayload);
12
+ const mission = await createMission(root, { mode: 'mad-db', prompt: 'mcp result fixture' });
13
+ await createMadDbCapability(root, { missionId: mission.id, ack: MAD_DB_ACK, ttlMs: 60000, projectRef: 'fixture-project-ref', status: 'active' });
14
+ const successPayload = { tool_name: 'supabase.execute_sql', tool_call_id: 'mcp-success-call', sql: 'insert into audit_log(id) values (1)' };
15
+ const successDecision = await checkDbOperation(root, { mission_id: mission.id }, successPayload);
16
16
  const successHook = madDbLifecycleHookFromDecision(successDecision);
17
17
  assertGate(Boolean(successHook), 'Mad-DB lifecycle hook missing before post-tool success result', successDecision);
18
- await evaluateHookPayload('post-tool', { tool_name: successPayload.tool_name, success: true, row_count: 1 }, { root, state: { mission_id: missionId } });
19
- const failurePayload = { tool_name: 'supabase.execute_sql', sql: 'update audit_log set id = 2 where id = 1' };
20
- const failureDecision = await checkDbOperation(root, { mission_id: missionId }, failurePayload);
18
+ await evaluateHookPayload('post-tool', { tool_name: successPayload.tool_name, tool_call_id: successHook.tool_call_id, success: true, row_count: 1 }, { root, state: { mission_id: mission.id } });
19
+ const failurePayload = { tool_name: 'supabase.execute_sql', tool_call_id: 'mcp-failure-call', sql: 'update audit_log set id = 2 where id = 1' };
20
+ const failureDecision = await checkDbOperation(root, { mission_id: mission.id }, failurePayload);
21
21
  const failureHook = madDbLifecycleHookFromDecision(failureDecision);
22
22
  assertGate(Boolean(failureHook), 'Mad-DB lifecycle hook missing before post-tool MCP isError result', failureDecision);
23
23
  await evaluateHookPayload('post-tool', {
24
24
  tool_name: failurePayload.tool_name,
25
+ tool_call_id: failureHook.tool_call_id,
25
26
  result: { isError: true, content: [{ type: 'text', text: 'fixture MCP error' }] }
26
- }, { root, state: { mission_id: missionId } });
27
- const ledger = await fs.readFile(path.join(missionDir(root, missionId), 'mad-db-ledger.jsonl'), 'utf8');
27
+ }, { root, state: { mission_id: mission.id } });
28
+ const ledger = await fs.readFile(path.join(missionDir(root, mission.id), 'mad-db-ledger.jsonl'), 'utf8');
28
29
  assertGate(ledger.includes('db_operation.succeeded') && ledger.includes('db_operation.failed') && ledger.includes('fixture MCP error'), 'PostToolUse must append succeeded and MCP isError failed lifecycle events', { ledger });
29
30
  emitGate('mad-db:mcp-result-lifecycle', { success_operation_id: successHook.operation_id, failure_operation_id: failureHook.operation_id, status: 'succeeded_and_failed_checked' });
30
31
  //# sourceMappingURL=mad-db-mcp-result-lifecycle-check.js.map
@@ -3,25 +3,22 @@
3
3
  import fs from 'node:fs/promises';
4
4
  import os from 'node:os';
5
5
  import path from 'node:path';
6
- import { closeMadDbCycle, createMadDbCapability, MAD_DB_ACK, readMadDbCapability } from '../core/mad-db/mad-db-capability.js';
6
+ import { closeMadDbCycle, createMadDbCapability, isMadDbCapabilityActive, MAD_DB_ACK, readMadDbCapability } from '../core/mad-db/mad-db-capability.js';
7
7
  import { checkDbOperation } from '../core/db-safety.js';
8
+ import { createMission } from '../core/mission.js';
8
9
  import { assertGate, emitGate } from './sks-1-18-gate-lib.js';
9
10
  const root = await fs.mkdtemp(path.join(os.tmpdir(), 'sks-mad-db-bounded-'));
10
- const missionId = 'M-mad-db-bounded';
11
- process.env.SKS_MAD_DB_MAX_OPERATIONS = '2';
12
- const cap = await createMadDbCapability(root, { missionId, ack: MAD_DB_ACK, ttlMs: 60000 });
13
- assertGate(cap.max_operations >= 2 && cap.operation_count === 0, 'capability must start as bounded one-cycle', cap);
14
- const payload = { tool_name: 'supabase.execute_sql', sql: 'update users set flag = true where id = 1' };
15
- const first = await checkDbOperation(root, { mission_id: missionId }, payload);
16
- const afterFirst = await readMadDbCapability(root, missionId);
17
- assertGate(first.allowed === true && afterFirst.operation_count === 1 && afterFirst.consumed === false, 'capability must remain active after operation 1 when max_operations > 1', { first, afterFirst });
18
- const second = await checkDbOperation(root, { mission_id: missionId }, payload);
19
- const afterSecond = await readMadDbCapability(root, missionId);
20
- assertGate(second.allowed === true && afterSecond.operation_count === 2 && afterSecond.consumed === true, 'capability must be consumed when operation_count reaches max_operations', { second, afterSecond });
21
- const closeMissionId = 'M-mad-db-close-cycle';
22
- process.env.SKS_MAD_DB_MAX_OPERATIONS = '20';
23
- const closeCap = await createMadDbCapability(root, { missionId: closeMissionId, ack: MAD_DB_ACK, ttlMs: 60000 });
24
- const closed = await closeMadDbCycle(root, closeMissionId, closeCap.cycle_id);
25
- assertGate(closed?.consumed === true && closed?.consumed_by === 'mad-db-cycle-close', 'explicit cycle close must consume active capability', closed);
26
- emitGate('mad-db:one-cycle-bounded', { cycle_id: cap.cycle_id, operation_count: afterSecond.operation_count, max_operations: afterSecond.max_operations, close_cycle: closed?.consumed === true });
11
+ const mission = await createMission(root, { mode: 'mad-db', prompt: 'bounded fixture' });
12
+ const cap = await createMadDbCapability(root, { missionId: mission.id, ack: MAD_DB_ACK, ttlMs: 60000, projectRef: 'fixture-project-ref', status: 'active' });
13
+ assertGate(isMadDbCapabilityActive(cap) === true && Date.parse(cap.expires_at) > Date.now(), 'capability must start active with bounded TTL', cap);
14
+ const payload = { tool_name: 'supabase.execute_sql', tool_call_id: 'bounded-call-1', sql: 'update users set flag = true where id = 1' };
15
+ const first = await checkDbOperation(root, { mission_id: mission.id }, payload);
16
+ const afterFirst = await readMadDbCapability(root, mission.id);
17
+ assertGate(first.allowed === true && afterFirst.counters.reserved === 1 && afterFirst.status === 'active', 'capability must reserve one operation and remain active before final close', { first, afterFirst });
18
+ const second = await checkDbOperation(root, { mission_id: mission.id }, payload);
19
+ const afterSecond = await readMadDbCapability(root, mission.id);
20
+ assertGate(second.allowed === true && second.mad_db?.idempotent_reservation_reused === true && afterSecond.counters.reserved === 1, 'same canonical tool_call_id must be idempotent and not double-counted', { second, afterSecond });
21
+ const closed = await closeMadDbCycle(root, mission.id, cap.cycle_id);
22
+ assertGate(closed?.status === 'closed' && isMadDbCapabilityActive(closed) === false, 'explicit cycle close must deactivate active capability', closed);
23
+ emitGate('mad-db:one-cycle-bounded', { cycle_id: cap.cycle_id, reserved: afterSecond.counters.reserved, close_cycle: closed?.status === 'closed' });
27
24
  //# sourceMappingURL=mad-db-one-cycle-bounded-check.js.map
@@ -7,10 +7,10 @@ const missionMod = await importDist('core/mission.js');
7
7
  const capMod = await importDist('core/mad-db/mad-db-capability.js');
8
8
  const root = fs.mkdtempSync(path.join(os.tmpdir(), 'sks-mad-db-consume-'));
9
9
  const mission = await missionMod.createMission(root, { mode: 'mad-db', prompt: 'fixture' });
10
- const cap = await capMod.createMadDbCapability(root, { missionId: mission.id, ack: capMod.MAD_DB_ACK, cwd: root });
10
+ const cap = await capMod.createMadDbCapability(root, { missionId: mission.id, ack: capMod.MAD_DB_ACK, cwd: root, projectRef: 'fixture-project-ref', status: 'active' });
11
11
  await capMod.consumeMadDbCapability(root, mission.id, { consumedBy: 'fixture' });
12
12
  const consumed = await capMod.readMadDbCapability(root, mission.id);
13
- assertGate(capMod.isMadDbCapabilityActive(consumed) === false && consumed.consumed === true, 'Mad-DB capability must be inactive after consumption', consumed);
14
- assertGate(fs.existsSync(path.join(root, '.sneakoscope', 'missions', mission.id, 'mad-db-capability.consumed.json')), 'consumed proof artifact missing');
13
+ assertGate(capMod.isMadDbCapabilityActive(consumed) === false && consumed.status === 'closed' && Boolean(consumed.closed_at), 'Mad-DB capability must be inactive after close/consumption compatibility call', consumed);
14
+ assertGate(fs.existsSync(path.join(root, '.sneakoscope', 'missions', mission.id, 'mad-db-capability.closed.json')), 'closed proof artifact missing');
15
15
  emitGate('mad-db:one-cycle-consumption', { cycle_id: cap.cycle_id });
16
16
  //# sourceMappingURL=mad-db-one-cycle-consumption-check.js.map
@@ -6,21 +6,21 @@ import path from 'node:path';
6
6
  import { checkDbOperation, madDbLifecycleHookFromDecision } from '../core/db-safety.js';
7
7
  import { createMadDbCapability, MAD_DB_ACK } from '../core/mad-db/mad-db-capability.js';
8
8
  import { recordMadDbToolResult } from '../core/mad-db/mad-db-result-lifecycle.js';
9
- import { missionDir } from '../core/mission.js';
9
+ import { createMission, missionDir } from '../core/mission.js';
10
10
  import { assertGate, emitGate } from './sks-1-18-gate-lib.js';
11
11
  const root = await fs.mkdtemp(path.join(os.tmpdir(), 'sks-mad-db-lifecycle-blackbox-'));
12
- const missionId = 'M-mad-db-lifecycle-blackbox';
13
- await createMadDbCapability(root, { missionId, ack: MAD_DB_ACK, ttlMs: 60000 });
14
- const success = await checkDbOperation(root, { mission_id: missionId }, { tool_name: 'supabase.execute_sql', sql: 'insert into audit_log(id) values (1)' });
12
+ const mission = await createMission(root, { mode: 'mad-db', prompt: 'lifecycle blackbox fixture' });
13
+ await createMadDbCapability(root, { missionId: mission.id, ack: MAD_DB_ACK, ttlMs: 60000, projectRef: 'fixture-project-ref', status: 'active' });
14
+ const success = await checkDbOperation(root, { mission_id: mission.id }, { tool_name: 'supabase.execute_sql', tool_call_id: 'blackbox-success-call', sql: 'insert into audit_log(id) values (1)' });
15
15
  const successHook = madDbLifecycleHookFromDecision(success);
16
16
  assertGate(Boolean(successHook), 'success hook missing', success);
17
- await recordMadDbToolResult({ root, missionId, hook: successHook, ok: true, rowCount: 1 });
18
- const failure = await checkDbOperation(root, { mission_id: missionId }, { tool_name: 'supabase.execute_sql', sql: 'update users set flag = true where id = 1' });
17
+ await recordMadDbToolResult({ root, missionId: mission.id, hook: successHook, ok: true, rowCount: 1 });
18
+ const failure = await checkDbOperation(root, { mission_id: mission.id }, { tool_name: 'supabase.execute_sql', tool_call_id: 'blackbox-failure-call', sql: 'update users set flag = true where id = 1' });
19
19
  const failureHook = madDbLifecycleHookFromDecision(failure);
20
20
  assertGate(Boolean(failureHook), 'failure hook missing', failure);
21
- await recordMadDbToolResult({ root, missionId, hook: failureHook, ok: false, error: 'fixture failure' });
22
- const ledger = await fs.readFile(path.join(missionDir(root, missionId), 'mad-db-ledger.jsonl'), 'utf8');
23
- for (const token of ['db_operation.started', 'db_operation.allowed', 'db_operation.succeeded', 'db_operation.failed']) {
21
+ await recordMadDbToolResult({ root, missionId: mission.id, hook: failureHook, ok: false, error: 'fixture failure' });
22
+ const ledger = await fs.readFile(path.join(missionDir(root, mission.id), 'mad-db-ledger.jsonl'), 'utf8');
23
+ for (const token of ['db_operation.started', 'db_mutation.allowed', 'db_operation.succeeded', 'db_operation.failed']) {
24
24
  assertGate(ledger.includes(token), `Mad-DB ledger missing ${token}`, { ledger });
25
25
  }
26
26
  assertGate((ledger.match(/db_operation\.succeeded/g) || []).length === 1, 'success terminal event must be recorded exactly once', { ledger });
@@ -5,13 +5,13 @@ import os from 'node:os';
5
5
  import path from 'node:path';
6
6
  import { createMadDbCapability, MAD_DB_ACK } from '../core/mad-db/mad-db-capability.js';
7
7
  import { checkDbOperation } from '../core/db-safety.js';
8
- import { missionDir } from '../core/mission.js';
8
+ import { createMission, missionDir } from '../core/mission.js';
9
9
  import { assertGate, emitGate } from './sks-1-18-gate-lib.js';
10
10
  const root = await fs.mkdtemp(path.join(os.tmpdir(), 'sks-mad-db-ledger-'));
11
- const missionId = 'M-mad-db-ledger';
12
- await createMadDbCapability(root, { missionId, ack: MAD_DB_ACK, ttlMs: 60000 });
13
- await checkDbOperation(root, { mission_id: missionId }, { tool_name: 'supabase.execute_sql', sql: 'insert into audit_log(id) values (1)' });
14
- const ledger = await fs.readFile(path.join(missionDir(root, missionId), 'mad-db-ledger.jsonl'), 'utf8');
15
- assertGate(ledger.includes('db_operation.started') && ledger.includes('db_operation.allowed') && ledger.includes('unknown_pending_tool_result'), 'Mad-DB lifecycle ledger events missing', { ledger });
11
+ const mission = await createMission(root, { mode: 'mad-db', prompt: 'ledger fixture' });
12
+ await createMadDbCapability(root, { missionId: mission.id, ack: MAD_DB_ACK, ttlMs: 60000, projectRef: 'fixture-project-ref', status: 'active' });
13
+ await checkDbOperation(root, { mission_id: mission.id }, { tool_name: 'supabase.execute_sql', tool_call_id: 'ledger-call-1', sql: 'insert into audit_log(id) values (1)' });
14
+ const ledger = await fs.readFile(path.join(missionDir(root, mission.id), 'mad-db-ledger.jsonl'), 'utf8');
15
+ assertGate(ledger.includes('db_operation.reserved') && ledger.includes('db_operation.started') && ledger.includes('db_mutation.allowed') && !ledger.includes('unknown_pending_tool_result'), 'Mad-DB lifecycle ledger events missing or pending-latest fallback still present', { ledger });
16
16
  emitGate('mad-db:operation-lifecycle-ledger');
17
17
  //# sourceMappingURL=mad-db-operation-lifecycle-ledger-check.js.map
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'node:fs';
3
+ import os from 'node:os';
4
+ import path from 'node:path';
5
+ import { createMission } from '../core/mission.js';
6
+ import { createMadDbCapability, MAD_DB_ACK, readMadDbCapability } from '../core/mad-db/mad-db-capability.js';
7
+ import { reserveMadDbOperation, transitionMadDbOperation } from '../core/mad-db/mad-db-operation-store.js';
8
+ import { assertGate, emitGate } from './sks-1-18-gate-lib.js';
9
+ const root = fs.mkdtempSync(path.join(os.tmpdir(), 'sks-mad-db-parallel-lifecycle-'));
10
+ const mission = await createMission(root, { mode: 'mad-db', prompt: 'parallel lifecycle fixture' });
11
+ const cap = await createMadDbCapability(root, { missionId: mission.id, ack: MAD_DB_ACK, cwd: root, projectRef: 'fixture-project-ref', status: 'active' });
12
+ const [first, second] = await Promise.all([
13
+ reserveMadDbOperation({ root, missionId: mission.id, capability: cap, toolCallId: 'parallel-call-a', toolName: 'supabase.execute_sql', sql: 'insert into fixture values (1)', operationClasses: ['insert'] }),
14
+ reserveMadDbOperation({ root, missionId: mission.id, capability: cap, toolCallId: 'parallel-call-b', toolName: 'supabase.execute_sql', sql: 'update fixture set id = 2', operationClasses: ['all_row_update'] })
15
+ ]);
16
+ await Promise.all([
17
+ transitionMadDbOperation({ root, missionId: mission.id, toolCallId: 'parallel-call-b', state: 'failed', errorCode: 'fixture_parallel_failure' }),
18
+ transitionMadDbOperation({ root, missionId: mission.id, toolCallId: 'parallel-call-a', state: 'succeeded', result: { ok: true } })
19
+ ]);
20
+ const capAfter = await readMadDbCapability(root, mission.id);
21
+ assertGate(first.operation.operation_id !== second.operation.operation_id, 'parallel calls must not collide by tool name', { first, second });
22
+ assertGate(Boolean(capAfter) && capAfter.counters.reserved === 2 && capAfter.counters.succeeded === 1 && capAfter.counters.failed === 1, 'parallel lifecycle counters must track exact call ids', capAfter || {});
23
+ emitGate('mad-db:parallel-lifecycle', { first: first.operation.operation_id, second: second.operation.operation_id, counters: capAfter.counters });
24
+ //# sourceMappingURL=mad-db-parallel-lifecycle-check.js.map
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env node
2
+ import { MAD_DB_POLICY, isMadDbControlPlaneDeniedTool, isMadDbSqlPlaneToolName, madDbOperationClassesFromClassification } from '../core/mad-db/mad-db-policy.js';
3
+ import { assertGate, emitGate } from './sks-1-18-gate-lib.js';
4
+ for (const operation of ['drop', 'all_row_delete', 'truncate', 'migration_apply', 'direct_execute_sql']) {
5
+ assertGate(MAD_DB_POLICY.sql_plane_allowed.includes(operation), `policy missing ${operation}`, MAD_DB_POLICY);
6
+ }
7
+ assertGate(isMadDbSqlPlaneToolName('mcp__supabase_mad_db__execute_sql') === true, 'execute_sql variants must be SQL-plane tools');
8
+ assertGate(isMadDbSqlPlaneToolName('supabase.apply_migration') === true, 'apply_migration variants must be SQL-plane tools');
9
+ assertGate(isMadDbControlPlaneDeniedTool('supabase.delete_project') === true, 'project control-plane delete must remain denied');
10
+ assertGate(isMadDbControlPlaneDeniedTool('supabase.billing_update') === true, 'billing control-plane updates must remain denied');
11
+ const classes = madDbOperationClassesFromClassification({
12
+ toolName: 'supabase.execute_sql',
13
+ level: 'destructive',
14
+ sql: { reasons: ['truncate', 'delete_without_where', 'alter_table_drop'], statements: ['truncate public.fixture;', 'delete from public.fixture;', 'alter table public.fixture drop column old_col;'] }
15
+ });
16
+ for (const operation of ['direct_execute_sql', 'truncate', 'all_row_delete', 'drop']) {
17
+ assertGate(classes.includes(operation), `classification must map ${operation}`, { classes });
18
+ }
19
+ emitGate('mad-db:policy-v2', { classes });
20
+ //# sourceMappingURL=mad-db-policy-v2-check.js.map
@@ -11,10 +11,10 @@ const mission = await missionMod.createMission(root, { mode: 'mad-db', prompt: '
11
11
  const state = { mission_id: mission.id };
12
12
  const denied = await db.checkDbOperation(root, state, { tool_name: 'supabase.execute_sql', sql: 'drop table users;' });
13
13
  assertGate(denied.allowed === false, 'without Mad-DB capability destructive DB must be blocked', denied);
14
- await capMod.createMadDbCapability(root, { missionId: mission.id, ack: capMod.MAD_DB_ACK, cwd: root });
15
- const allowed = await db.checkDbOperation(root, state, { tool_name: 'supabase.execute_sql', sql: 'drop table users;' });
14
+ await capMod.createMadDbCapability(root, { missionId: mission.id, ack: capMod.MAD_DB_ACK, cwd: root, projectRef: 'fixture-project-ref', status: 'active' });
15
+ const allowed = await db.checkDbOperation(root, state, { tool_name: 'supabase.execute_sql', tool_call_id: 'priority-drop-table', sql: 'drop table users;' });
16
16
  assertGate(allowed.allowed === true && allowed.mad_db?.active === true, 'Mad-DB capability must allow destructive DB mutation with highest priority', allowed);
17
- const consumed = await capMod.readMadDbCapability(root, mission.id);
18
- assertGate(consumed.consumed === false && consumed.operation_count === 1, 'Mad-DB capability must remain active during bounded one-cycle after first operation', consumed);
19
- emitGate('mad-db:priority-resolver', { cycle_id: consumed.cycle_id });
17
+ const after = await capMod.readMadDbCapability(root, mission.id);
18
+ assertGate(after.status === 'active' && after.counters.reserved === 1, 'Mad-DB capability must remain active and reserve exactly one operation', after);
19
+ emitGate('mad-db:priority-resolver', { cycle_id: after.cycle_id, reserved: after.counters.reserved });
20
20
  //# sourceMappingURL=mad-db-priority-resolver-check.js.map
@@ -0,0 +1,166 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'node:fs/promises';
3
+ import os from 'node:os';
4
+ import path from 'node:path';
5
+ import { createMission } from '../core/mission.js';
6
+ import { MAD_DB_ACK, closeMadDbCycle, createMadDbCapability } from '../core/mad-db/mad-db-capability.js';
7
+ import { MadDbMcpExecutor } from '../core/mad-db/mad-db-executor.js';
8
+ import { createMadDbRuntimeProfile, closeMadDbRuntimeProfile } from '../core/mad-db/mad-db-runtime-profile.js';
9
+ import { emitGate } from './sks-1-18-gate-lib.js';
10
+ const requireReal = process.argv.includes('--require-real');
11
+ const projectRef = process.env.SKS_MAD_DB_E2E_PROJECT_REF || process.env.SKS_MAD_DB_PROJECT_REF || '';
12
+ const hasAuth = Boolean(process.env.SUPABASE_ACCESS_TOKEN || process.env.SKS_MAD_DB_SUPABASE_ACCESS_TOKEN);
13
+ if (!projectRef || !hasAuth) {
14
+ const detail = {
15
+ status: 'unverified',
16
+ require_real: requireReal,
17
+ missing_project_ref: !projectRef,
18
+ missing_supabase_access_token: !hasAuth,
19
+ required_env: ['SKS_MAD_DB_E2E_PROJECT_REF', 'SUPABASE_ACCESS_TOKEN or SKS_MAD_DB_SUPABASE_ACCESS_TOKEN']
20
+ };
21
+ console.error(JSON.stringify({ schema: 'sks.mad-db-real-e2e.v1', ok: false, ...detail }, null, 2));
22
+ process.exit(requireReal ? 2 : 0);
23
+ }
24
+ const root = await fs.mkdtemp(path.join(os.tmpdir(), 'sks-mad-db-real-e2e-'));
25
+ await fs.mkdir(path.join(root, '.codex'), { recursive: true });
26
+ await fs.writeFile(path.join(root, '.codex', 'config.toml'), `[mcp_servers.supabase]\nurl = "https://mcp.supabase.com/mcp?project_ref=${projectRef}&read_only=true"\n`);
27
+ const mission = await createMission(root, { mode: 'mad-db', prompt: 'real disposable Supabase MadDB E2E' });
28
+ const cycleId = `real-e2e-${Date.now().toString(36)}`;
29
+ const profile = await createMadDbRuntimeProfile({ root, missionId: mission.id, cycleId, projectRef, runtimeSessionId: 'real-e2e-session' });
30
+ await createMadDbCapability(root, {
31
+ missionId: mission.id,
32
+ ack: MAD_DB_ACK,
33
+ cwd: root,
34
+ cycleId,
35
+ projectRef,
36
+ runtimeSessionId: 'real-e2e-session',
37
+ profilePath: profile.profile_path,
38
+ profileSha256: profile.profile_sha256,
39
+ serverUrlRedacted: profile.server_url_redacted,
40
+ status: 'active'
41
+ });
42
+ const executor = new MadDbMcpExecutor(profile, { timeoutMs: Number(process.env.SKS_MAD_DB_E2E_TIMEOUT_MS || 120000) });
43
+ const suffix = Date.now().toString(36).replace(/[^a-z0-9]/g, '');
44
+ const table = `sks_mad_db_e2e_${suffix}`;
45
+ const migrationName = `sks_mad_db_e2e_migration_${suffix}`;
46
+ const steps = [
47
+ {
48
+ name: 'create_table',
49
+ tool: 'execute_sql',
50
+ sql: `create table public.${table} (id integer primary key, label text not null);`,
51
+ verify: `select case when to_regclass('public.${table}') is not null then 1 else 1/0 end as ok;`
52
+ },
53
+ {
54
+ name: 'add_column',
55
+ tool: 'execute_sql',
56
+ sql: `alter table public.${table} add column note text;`,
57
+ verify: `select case when exists (select 1 from information_schema.columns where table_schema='public' and table_name='${table}' and column_name='note') then 1 else 1/0 end as ok;`
58
+ },
59
+ {
60
+ name: 'insert',
61
+ tool: 'execute_sql',
62
+ sql: `insert into public.${table} (id, label, note) values (1, 'alpha', 'inserted');`,
63
+ verify: `select case when (select count(*) from public.${table}) = 1 then 1 else 1/0 end as ok;`
64
+ },
65
+ {
66
+ name: 'update',
67
+ tool: 'execute_sql',
68
+ sql: `update public.${table} set label = 'beta' where id = 1;`,
69
+ verify: `select case when exists (select 1 from public.${table} where id=1 and label='beta') then 1 else 1/0 end as ok;`
70
+ },
71
+ {
72
+ name: 'targeted_delete',
73
+ tool: 'execute_sql',
74
+ sql: `delete from public.${table} where id = 1;`,
75
+ verify: `select case when (select count(*) from public.${table}) = 0 then 1 else 1/0 end as ok;`
76
+ },
77
+ {
78
+ name: 'all_row_delete',
79
+ tool: 'execute_sql',
80
+ sql: `insert into public.${table} (id, label) values (2, 'two'), (3, 'three'); delete from public.${table};`,
81
+ verify: `select case when (select count(*) from public.${table}) = 0 then 1 else 1/0 end as ok;`
82
+ },
83
+ {
84
+ name: 'truncate',
85
+ tool: 'execute_sql',
86
+ sql: `insert into public.${table} (id, label) values (4, 'four'), (5, 'five'); truncate table public.${table};`,
87
+ verify: `select case when (select count(*) from public.${table}) = 0 then 1 else 1/0 end as ok;`
88
+ },
89
+ {
90
+ name: 'drop_column',
91
+ tool: 'execute_sql',
92
+ sql: `alter table public.${table} add column drop_me text; alter table public.${table} drop column drop_me;`,
93
+ verify: `select case when not exists (select 1 from information_schema.columns where table_schema='public' and table_name='${table}' and column_name='drop_me') then 1 else 1/0 end as ok;`
94
+ },
95
+ {
96
+ name: 'migration_apply',
97
+ tool: 'apply_migration',
98
+ sql: `alter table public.${table} add column migrated_flag boolean default false;`,
99
+ verify: `select case when exists (select 1 from information_schema.columns where table_schema='public' and table_name='${table}' and column_name='migrated_flag') then 1 else 1/0 end as ok;`
100
+ },
101
+ {
102
+ name: 'drop_table',
103
+ tool: 'execute_sql',
104
+ sql: `drop table public.${table};`,
105
+ verify: `select case when to_regclass('public.${table}') is null then 1 else 1/0 end as ok;`
106
+ }
107
+ ];
108
+ const timings = [];
109
+ const matrix = [];
110
+ let inventory = null;
111
+ let restoration = null;
112
+ let failure = null;
113
+ try {
114
+ inventory = await executor.inventory();
115
+ if (inventory.ok !== true)
116
+ throw failureDetail('real Supabase MCP inventory must expose execute_sql and apply_migration', inventory);
117
+ for (const step of steps) {
118
+ const started = Date.now();
119
+ const result = step.tool === 'apply_migration'
120
+ ? await executor.applyMigration(`${migrationName}_${step.name}`, step.sql)
121
+ : await executor.executeSql(step.sql);
122
+ const verify = await executor.executeSql(step.verify);
123
+ const elapsed = Date.now() - started;
124
+ timings.push(elapsed);
125
+ matrix.push({ name: step.name, tool: step.tool, execute_ok: result.ok, verify_ok: verify.ok, duration_ms: elapsed, result_digest: result.result_digest, verify_digest: verify.result_digest });
126
+ if (result.ok !== true || verify.ok !== true)
127
+ throw failureDetail(`real MadDB E2E step failed: ${step.name}`, matrix[matrix.length - 1]);
128
+ }
129
+ }
130
+ catch (err) {
131
+ failure = err?.detail || { message: err?.message || String(err) };
132
+ }
133
+ finally {
134
+ await executor.close();
135
+ restoration = await closeMadDbRuntimeProfile({ root, missionId: mission.id, profile, reason: 'real_e2e_finally' });
136
+ await closeMadDbCycle(root, mission.id, cycleId, 'real_e2e_finally');
137
+ }
138
+ if (failure) {
139
+ console.error(JSON.stringify({
140
+ schema: 'sks.mad-db-real-e2e.v1',
141
+ ok: false,
142
+ status: 'failed_real_supabase',
143
+ project_ref_hash: profile.project_ref_hash,
144
+ failure,
145
+ destructive_operation_matrix: matrix,
146
+ read_only_restoration: restoration
147
+ }, null, 2));
148
+ process.exit(1);
149
+ }
150
+ timings.sort((a, b) => a - b);
151
+ const percentile = (p) => timings.length ? timings[Math.min(timings.length - 1, Math.floor((timings.length - 1) * p))] : 0;
152
+ emitGate('mad-db:real-e2e', {
153
+ status: 'passed_real_supabase',
154
+ project_ref_hash: profile.project_ref_hash,
155
+ table_hash: table.slice(-10),
156
+ inventory: { execute_sql_available: inventory?.execute_sql_available === true, apply_migration_available: inventory?.apply_migration_available === true, tool_count: inventory?.tool_names?.length || 0 },
157
+ destructive_operation_matrix: matrix,
158
+ timings_ms: { p50: percentile(0.5), p95: percentile(0.95), max: timings[timings.length - 1] || 0 },
159
+ read_only_restoration: restoration
160
+ });
161
+ function failureDetail(message, detail) {
162
+ const err = new Error(message);
163
+ err.detail = { message, detail };
164
+ return err;
165
+ }
166
+ //# sourceMappingURL=mad-db-real-supabase-e2e.js.map