sneakoscope 4.1.1 → 4.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -10
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/crates/sks-core/src/main.rs +1 -1
- package/dist/bin/sks.js +1 -1
- package/dist/cli/command-registry.js +1 -1
- package/dist/core/auto-review.js +1 -1
- package/dist/core/codex-control/codex-app-server-v2-client.js +86 -2
- package/dist/core/codex-control/codex-reliability-shield.js +26 -5
- package/dist/core/codex-control/codex-task-runner.js +7 -1
- package/dist/core/codex-control/model-call-concurrency.js +1 -1
- package/dist/core/commands/mad-db-command.js +146 -51
- package/dist/core/commands/mad-sks-command.js +15 -31
- package/dist/core/commands/qa-loop-command.js +23 -7
- package/dist/core/db-safety.js +35 -37
- package/dist/core/doctor/supabase-mcp-repair.js +2 -2
- package/dist/core/feature-registry.js +1 -1
- package/dist/core/fsx.js +1 -1
- package/dist/core/hooks-runtime.js +1 -1
- package/dist/core/init.js +5 -4
- package/dist/core/mad-db/mad-db-capability.js +203 -74
- package/dist/core/mad-db/mad-db-coordinator.js +287 -0
- package/dist/core/mad-db/mad-db-executor.js +156 -0
- package/dist/core/mad-db/mad-db-ledger.js +1 -1
- package/dist/core/mad-db/mad-db-lock.js +40 -0
- package/dist/core/mad-db/mad-db-operation-store.js +140 -0
- package/dist/core/mad-db/mad-db-policy-resolver.js +42 -22
- package/dist/core/mad-db/mad-db-policy.js +195 -0
- package/dist/core/mad-db/mad-db-postconditions.js +30 -0
- package/dist/core/mad-db/mad-db-recovery.js +27 -0
- package/dist/core/mad-db/mad-db-result-lifecycle.js +31 -102
- package/dist/core/mad-db/mad-db-runtime-profile.js +121 -0
- package/dist/core/mad-db/mad-db-target.js +64 -0
- package/dist/core/managed-assets/managed-assets-manifest.js +1 -1
- package/dist/core/pipeline-internals/runtime-core.js +40 -0
- package/dist/core/providers/glm/bench/glm-benchmark-types.js +1 -1
- package/dist/core/qa-loop/qa-app-server-driver.js +134 -0
- package/dist/core/qa-loop/qa-contract-v2.js +231 -0
- package/dist/core/qa-loop/qa-gate-v2.js +132 -0
- package/dist/core/qa-loop/qa-runtime-artifacts.js +53 -0
- package/dist/core/qa-loop/qa-surface-router.js +114 -0
- package/dist/core/qa-loop/qa-types.js +18 -0
- package/dist/core/qa-loop.js +83 -26
- package/dist/core/release/gate-manifest.js +1 -0
- package/dist/core/release/release-gate-dag.js +6 -5
- package/dist/core/release/sla-scheduler.js +1 -1
- package/dist/core/routes.js +42 -12
- package/dist/core/triwiki/triwiki-affected-graph.js +3 -2
- package/dist/core/version.js +1 -1
- package/dist/core/zellij/zellij-slot-column-anchor.js +5 -1
- package/dist/scripts/check-dist-runtime.js +3 -2
- package/dist/scripts/codex-0142-manifest-check.js +2 -1
- package/dist/scripts/codex-control-all-pipelines-check.js +1 -0
- package/dist/scripts/codex-control-model-capacity-fallback-check.js +53 -0
- package/dist/scripts/config-managed-merge-callsite-coverage-check.js +7 -1
- package/dist/scripts/loop-directive-check-lib.js +78 -1
- package/dist/scripts/mad-db-capability-check.js +13 -2
- package/dist/scripts/mad-db-command-check.js +7 -5
- package/dist/scripts/mad-db-hook-idempotency-check.js +21 -0
- package/dist/scripts/mad-db-ledger-check.js +2 -1
- package/dist/scripts/mad-db-lifecycle-hook-decision-check.js +5 -4
- package/dist/scripts/mad-db-mad-command-check.js +29 -16
- package/dist/scripts/mad-db-mcp-result-lifecycle-check.js +11 -10
- package/dist/scripts/mad-db-one-cycle-bounded-check.js +15 -18
- package/dist/scripts/mad-db-one-cycle-consumption-check.js +3 -3
- package/dist/scripts/mad-db-operation-lifecycle-blackbox.js +9 -9
- package/dist/scripts/mad-db-operation-lifecycle-ledger-check.js +6 -6
- package/dist/scripts/mad-db-parallel-lifecycle-check.js +24 -0
- package/dist/scripts/mad-db-policy-v2-check.js +20 -0
- package/dist/scripts/mad-db-priority-resolver-check.js +5 -5
- package/dist/scripts/mad-db-real-supabase-e2e.js +166 -0
- package/dist/scripts/mad-db-route-identity-check.js +28 -0
- package/dist/scripts/mad-db-runtime-profile-lifecycle-check.js +24 -0
- package/dist/scripts/mad-db-safety-conflict-matrix-check.js +3 -3
- package/dist/scripts/mad-db-skill-policy-snapshot-check.js +15 -0
- package/dist/scripts/qa-loop-app-server-driver-check.js +74 -0
- package/dist/scripts/qa-loop-surface-router-check.js +49 -0
- package/dist/scripts/release-check-dynamic-execute.js +1 -1
- package/dist/scripts/release-dag-full-coverage-check.js +6 -0
- package/dist/scripts/release-triwiki-first-runner-blackbox.js +5 -1
- package/dist/scripts/runtime-ts-rust-boundary-check.js +1 -1
- package/dist/scripts/triwiki-affected-graph-check.js +2 -2
- package/package.json +18 -5
- package/schemas/mad-db/mad-db-capability.schema.json +92 -19
|
@@ -41,7 +41,12 @@ export async function runLoopDirectiveCheck(id) {
|
|
|
41
41
|
process.env.SKS_LOOP_RUNTIME_FIXTURE = '1';
|
|
42
42
|
}
|
|
43
43
|
const fixtureMode = process.env.SKS_LOOP_RUNTIME_FIXTURE === '1' || process.env.SKS_LOOP_GATE_FIXTURE === '1';
|
|
44
|
-
const
|
|
44
|
+
const needsRuntime = loopDirectiveNeedsRuntime(id);
|
|
45
|
+
if (!needsRuntime)
|
|
46
|
+
await writeLightweightLoopArtifacts(root, missionId, plan);
|
|
47
|
+
const result = needsRuntime
|
|
48
|
+
? await runLoopPlan({ root, plan, parallelism: 'extreme', noMutation: fixtureMode ? true : !realRuntimeMode })
|
|
49
|
+
: { ok: true, proofs: [], graph_proof: await readJson(loopGraphProofPath(root, missionId)) };
|
|
45
50
|
const assertions = [];
|
|
46
51
|
const assert = (condition, message) => assertions.push({ ok: Boolean(condition), message });
|
|
47
52
|
assert(validateLoopPlan(plan).ok, 'loop plan validates');
|
|
@@ -321,6 +326,78 @@ export async function runLoopDirectiveCheck(id) {
|
|
|
321
326
|
if (failed.length)
|
|
322
327
|
process.exitCode = 1;
|
|
323
328
|
}
|
|
329
|
+
function loopDirectiveNeedsRuntime(id) {
|
|
330
|
+
return new Set([
|
|
331
|
+
'loop:runtime',
|
|
332
|
+
'loop:worker-runtime',
|
|
333
|
+
'loop:checker-freshness',
|
|
334
|
+
'loop:runtime-real-workers',
|
|
335
|
+
'loop:maker-checker-real',
|
|
336
|
+
'loop:gate-runner-real',
|
|
337
|
+
'loop:gate-artifacts',
|
|
338
|
+
'loop:worktree-runtime',
|
|
339
|
+
'loop:integration-merge',
|
|
340
|
+
'loop:integration-finalizer-real',
|
|
341
|
+
'loop:real-maker-checker-blackbox',
|
|
342
|
+
'naruto:loop-mesh-real-blackbox',
|
|
343
|
+
'goal:loop-runtime-real-blackbox',
|
|
344
|
+
'loop:integration-finalizer'
|
|
345
|
+
]).has(id);
|
|
346
|
+
}
|
|
347
|
+
async function writeLightweightLoopArtifacts(root, missionId, plan) {
|
|
348
|
+
const node = plan.graph.nodes.find((row) => row.loop_id === 'loop-zellij') || plan.graph.nodes[0];
|
|
349
|
+
if (!node)
|
|
350
|
+
return;
|
|
351
|
+
const stateFile = loopStatePath(root, missionId, node.loop_id);
|
|
352
|
+
const proofFile = loopProofPath(root, missionId, node.loop_id);
|
|
353
|
+
const graphFile = loopGraphProofPath(root, missionId);
|
|
354
|
+
await fs.mkdir(path.dirname(stateFile), { recursive: true });
|
|
355
|
+
await fs.writeFile(stateFile, JSON.stringify({
|
|
356
|
+
schema: 'sks.loop-state.v1',
|
|
357
|
+
mission_id: missionId,
|
|
358
|
+
loop_id: node.loop_id,
|
|
359
|
+
status: 'completed',
|
|
360
|
+
current_phase: 'static-fixture',
|
|
361
|
+
updated_at: new Date().toISOString()
|
|
362
|
+
}, null, 2));
|
|
363
|
+
await fs.writeFile(proofFile, JSON.stringify({
|
|
364
|
+
schema: 'sks.loop-proof.v1',
|
|
365
|
+
mission_id: missionId,
|
|
366
|
+
loop_id: node.loop_id,
|
|
367
|
+
status: 'completed',
|
|
368
|
+
iterations: 1,
|
|
369
|
+
owner_scope: node.owner_scope,
|
|
370
|
+
maker_result: { backend: 'static-fixture', worker_count: 0, artifacts: [], patch_candidates: [], changed_files: [], blockers: [], ok: true },
|
|
371
|
+
checker_result: { backend: 'static-fixture', worker_count: 0, artifacts: [], checker_findings: [], fresh_session: true, blockers: [], ok: true },
|
|
372
|
+
gate_result: { ok: true, selected_gates: [], passed_gates: [], failed_gates: [], skipped_gates: [], blockers: [] },
|
|
373
|
+
budget: { used: { iterations: 1 } },
|
|
374
|
+
handoff: { required: false, reason: null },
|
|
375
|
+
worktree: { id: null, path: null, branch: null },
|
|
376
|
+
changed_files: [],
|
|
377
|
+
patch_bytes: 0,
|
|
378
|
+
blockers: []
|
|
379
|
+
}, null, 2));
|
|
380
|
+
await fs.mkdir(path.dirname(graphFile), { recursive: true });
|
|
381
|
+
await fs.writeFile(graphFile, JSON.stringify({
|
|
382
|
+
schema: 'sks.loop-graph-proof.v1',
|
|
383
|
+
mission_id: missionId,
|
|
384
|
+
ok: true,
|
|
385
|
+
total_loops: plan.graph.nodes.length,
|
|
386
|
+
completed_loops: plan.graph.nodes.length,
|
|
387
|
+
blocked_loops: 0,
|
|
388
|
+
failed_loops: 0,
|
|
389
|
+
handoff_loops: 0,
|
|
390
|
+
parallelism: {
|
|
391
|
+
max_active_loops: Math.min(plan.graph.nodes.length, 4),
|
|
392
|
+
max_active_workers: 0,
|
|
393
|
+
wall_ms: 1,
|
|
394
|
+
sequential_estimate_ms: Math.max(1, plan.graph.nodes.length),
|
|
395
|
+
speedup_ratio: Math.max(1, plan.graph.nodes.length)
|
|
396
|
+
},
|
|
397
|
+
gates: { selected: [], passed: [], failed: [], skipped: [] },
|
|
398
|
+
blockers: []
|
|
399
|
+
}, null, 2));
|
|
400
|
+
}
|
|
324
401
|
async function exists(file) {
|
|
325
402
|
try {
|
|
326
403
|
await fs.access(file);
|
|
@@ -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, {
|
|
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.
|
|
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('
|
|
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-
|
|
9
|
-
assertGate(routeByDollarCommand('MAD-DB')?.command === '$MAD-
|
|
10
|
-
assertGate(routeByDollarCommand('mad-db')?.command === '$MAD-
|
|
11
|
-
|
|
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.
|
|
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
|
|
11
|
-
await createMadDbCapability(root, { missionId, ack: MAD_DB_ACK, ttlMs: 60000 });
|
|
12
|
-
const decision = await checkDbOperation(root, { mission_id:
|
|
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 ===
|
|
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.
|
|
57
|
-
assert.
|
|
58
|
-
assert.
|
|
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
|
-
|
|
61
|
-
|
|
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
|
-
|
|
64
|
+
tool_call_id: 'mad-sks-default-does-not-open-maddb',
|
|
65
|
+
sql: 'truncate sks_mad_db_probe;'
|
|
71
66
|
});
|
|
72
|
-
assertGate(decision.allowed ===
|
|
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
|
-
|
|
76
|
-
|
|
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
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
27
|
-
const ledger = await fs.readFile(path.join(missionDir(root,
|
|
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
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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.
|
|
14
|
-
assertGate(fs.existsSync(path.join(root, '.sneakoscope', 'missions', mission.id, 'mad-db-capability.
|
|
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
|
|
13
|
-
await createMadDbCapability(root, { missionId, ack: MAD_DB_ACK, ttlMs: 60000 });
|
|
14
|
-
const success = await checkDbOperation(root, { mission_id:
|
|
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:
|
|
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,
|
|
23
|
-
for (const token of ['db_operation.started', '
|
|
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
|
|
12
|
-
await createMadDbCapability(root, { missionId, ack: MAD_DB_ACK, ttlMs: 60000 });
|
|
13
|
-
await checkDbOperation(root, { mission_id:
|
|
14
|
-
const ledger = await fs.readFile(path.join(missionDir(root,
|
|
15
|
-
assertGate(ledger.includes('db_operation.
|
|
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
|
|
18
|
-
assertGate(
|
|
19
|
-
emitGate('mad-db:priority-resolver', { 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
|