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.
Files changed (84) hide show
  1. package/README.md +13 -10
  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/core/auto-review.js +1 -1
  8. package/dist/core/codex-control/codex-app-server-v2-client.js +86 -2
  9. package/dist/core/codex-control/codex-reliability-shield.js +26 -5
  10. package/dist/core/codex-control/codex-task-runner.js +7 -1
  11. package/dist/core/codex-control/model-call-concurrency.js +1 -1
  12. package/dist/core/commands/mad-db-command.js +146 -51
  13. package/dist/core/commands/mad-sks-command.js +15 -31
  14. package/dist/core/commands/qa-loop-command.js +23 -7
  15. package/dist/core/db-safety.js +35 -37
  16. package/dist/core/doctor/supabase-mcp-repair.js +2 -2
  17. package/dist/core/feature-registry.js +1 -1
  18. package/dist/core/fsx.js +1 -1
  19. package/dist/core/hooks-runtime.js +1 -1
  20. package/dist/core/init.js +5 -4
  21. package/dist/core/mad-db/mad-db-capability.js +203 -74
  22. package/dist/core/mad-db/mad-db-coordinator.js +287 -0
  23. package/dist/core/mad-db/mad-db-executor.js +156 -0
  24. package/dist/core/mad-db/mad-db-ledger.js +1 -1
  25. package/dist/core/mad-db/mad-db-lock.js +40 -0
  26. package/dist/core/mad-db/mad-db-operation-store.js +140 -0
  27. package/dist/core/mad-db/mad-db-policy-resolver.js +42 -22
  28. package/dist/core/mad-db/mad-db-policy.js +195 -0
  29. package/dist/core/mad-db/mad-db-postconditions.js +30 -0
  30. package/dist/core/mad-db/mad-db-recovery.js +27 -0
  31. package/dist/core/mad-db/mad-db-result-lifecycle.js +31 -102
  32. package/dist/core/mad-db/mad-db-runtime-profile.js +121 -0
  33. package/dist/core/mad-db/mad-db-target.js +64 -0
  34. package/dist/core/managed-assets/managed-assets-manifest.js +1 -1
  35. package/dist/core/pipeline-internals/runtime-core.js +40 -0
  36. package/dist/core/providers/glm/bench/glm-benchmark-types.js +1 -1
  37. package/dist/core/qa-loop/qa-app-server-driver.js +134 -0
  38. package/dist/core/qa-loop/qa-contract-v2.js +231 -0
  39. package/dist/core/qa-loop/qa-gate-v2.js +132 -0
  40. package/dist/core/qa-loop/qa-runtime-artifacts.js +53 -0
  41. package/dist/core/qa-loop/qa-surface-router.js +114 -0
  42. package/dist/core/qa-loop/qa-types.js +18 -0
  43. package/dist/core/qa-loop.js +83 -26
  44. package/dist/core/release/gate-manifest.js +1 -0
  45. package/dist/core/release/release-gate-dag.js +6 -5
  46. package/dist/core/release/sla-scheduler.js +1 -1
  47. package/dist/core/routes.js +42 -12
  48. package/dist/core/triwiki/triwiki-affected-graph.js +3 -2
  49. package/dist/core/version.js +1 -1
  50. package/dist/core/zellij/zellij-slot-column-anchor.js +5 -1
  51. package/dist/scripts/check-dist-runtime.js +3 -2
  52. package/dist/scripts/codex-0142-manifest-check.js +2 -1
  53. package/dist/scripts/codex-control-all-pipelines-check.js +1 -0
  54. package/dist/scripts/codex-control-model-capacity-fallback-check.js +53 -0
  55. package/dist/scripts/config-managed-merge-callsite-coverage-check.js +7 -1
  56. package/dist/scripts/loop-directive-check-lib.js +78 -1
  57. package/dist/scripts/mad-db-capability-check.js +13 -2
  58. package/dist/scripts/mad-db-command-check.js +7 -5
  59. package/dist/scripts/mad-db-hook-idempotency-check.js +21 -0
  60. package/dist/scripts/mad-db-ledger-check.js +2 -1
  61. package/dist/scripts/mad-db-lifecycle-hook-decision-check.js +5 -4
  62. package/dist/scripts/mad-db-mad-command-check.js +29 -16
  63. package/dist/scripts/mad-db-mcp-result-lifecycle-check.js +11 -10
  64. package/dist/scripts/mad-db-one-cycle-bounded-check.js +15 -18
  65. package/dist/scripts/mad-db-one-cycle-consumption-check.js +3 -3
  66. package/dist/scripts/mad-db-operation-lifecycle-blackbox.js +9 -9
  67. package/dist/scripts/mad-db-operation-lifecycle-ledger-check.js +6 -6
  68. package/dist/scripts/mad-db-parallel-lifecycle-check.js +24 -0
  69. package/dist/scripts/mad-db-policy-v2-check.js +20 -0
  70. package/dist/scripts/mad-db-priority-resolver-check.js +5 -5
  71. package/dist/scripts/mad-db-real-supabase-e2e.js +166 -0
  72. package/dist/scripts/mad-db-route-identity-check.js +28 -0
  73. package/dist/scripts/mad-db-runtime-profile-lifecycle-check.js +24 -0
  74. package/dist/scripts/mad-db-safety-conflict-matrix-check.js +3 -3
  75. package/dist/scripts/mad-db-skill-policy-snapshot-check.js +15 -0
  76. package/dist/scripts/qa-loop-app-server-driver-check.js +74 -0
  77. package/dist/scripts/qa-loop-surface-router-check.js +49 -0
  78. package/dist/scripts/release-check-dynamic-execute.js +1 -1
  79. package/dist/scripts/release-dag-full-coverage-check.js +6 -0
  80. package/dist/scripts/release-triwiki-first-runner-blackbox.js +5 -1
  81. package/dist/scripts/runtime-ts-rust-boundary-check.js +1 -1
  82. package/dist/scripts/triwiki-affected-graph-check.js +2 -2
  83. package/package.json +18 -5
  84. package/schemas/mad-db/mad-db-capability.schema.json +92 -19
@@ -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';
@@ -203,38 +202,22 @@ export async function madHighCommand(args = [], deps = {}) {
203
202
  process.exitCode = 1;
204
203
  return glmRuntime;
205
204
  }
206
- const madDbCapability = madDbGrant.enabled
207
- ? await createMadDbCapability(madLaunch.root, { missionId: madLaunch.mission_id, ack: madDbGrant.ack, cwd: process.cwd() })
208
- : null;
209
- if (madDbCapability) {
205
+ if (madDbGrant.requested) {
210
206
  const grantReport = {
211
- schema: 'sks.mad-sks-launch-grants.v1',
207
+ schema: 'sks.mad-sks-launch-grants.v2',
212
208
  generated_at: nowIso(),
213
209
  mission_id: madLaunch.mission_id,
214
210
  mad_sks_active: true,
215
- mad_db_active: true,
216
- mad_db_default_grant: madDbGrant.source === 'sks_mad_default',
211
+ mad_db_active: false,
212
+ mad_db_default_grant: false,
217
213
  mad_db_grant_source: madDbGrant.source,
218
- mad_db_one_cycle_only: true,
219
- mad_db_capability_file: 'mad-db-capability.json',
220
- mad_db_cycle_id: madDbCapability.cycle_id,
221
- 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,
222
217
  standalone_mad_db_enable_still_requires_ack: true
223
218
  };
224
219
  await writeJsonAtomic(path.join(madLaunch.dir, 'mad-sks-launch-grants.json'), grantReport);
225
- await setCurrent(madLaunch.root, {
226
- mission_id: madLaunch.mission_id,
227
- mad_db_active: true,
228
- mad_db_cycle_id: madDbCapability.cycle_id,
229
- mad_db_capability_file: 'mad-db-capability.json',
230
- mad_db_break_glass: true,
231
- mad_db_default_grant: madDbGrant.source === 'sks_mad_default',
232
- mad_db_grant_source: madDbGrant.source,
233
- mad_db_one_cycle_only: true,
234
- mad_db_priority_override_active: true,
235
- mad_sks_launch_grants_file: 'mad-sks-launch-grants.json'
236
- });
237
- 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 });
238
221
  }
239
222
  const updateNotice = {
240
223
  schema: 'sks.update-notice.v1',
@@ -256,11 +239,11 @@ export async function madHighCommand(args = [], deps = {}) {
256
239
  console.log(`SKS MAD ready: ${glmRuntime?.profile?.profile_name || madHighProfileName()} | gate ${madLaunch.mission_id}`);
257
240
  if (glmRuntime?.profile)
258
241
  console.log(`GLM MAD launch active: ${glmRuntime.profile.model} via OpenRouter; GPT fallback blocked.`);
259
- if (madDbCapability)
260
- 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.');
261
244
  if (updateNotice.update_available === true)
262
245
  console.log(`SKS update notice: ${updateNotice.latest_version} available (non-blocking).`);
263
- 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.');
264
247
  const launchLb = lb.status === 'present' ? { ...lb, status: 'configured' } : lb;
265
248
  const madSksEnv = {
266
249
  SKS_PROTECTED_CORE_POLICY: madLaunch.gate.protected_core_policy,
@@ -411,10 +394,11 @@ function buildGlmMadLaunchOpts(cleanArgs = [], opts = {}) {
411
394
  }
412
395
  export function resolveMadLaunchMadDbGrant(args = []) {
413
396
  const list = (args || []).map((arg) => String(arg));
397
+ const requested = list.includes('--mad-db');
414
398
  return {
415
- enabled: true,
416
- source: list.includes('--mad-db') ? 'sks_mad_explicit_redundant_flag' : 'sks_mad_default',
417
- ack: MAD_DB_ACK,
399
+ enabled: false,
400
+ requested,
401
+ source: requested ? 'mad_db_first_class_route_required' : 'not_requested',
418
402
  one_cycle_only: true
419
403
  };
420
404
  }
@@ -17,6 +17,8 @@ import { runCodexAppHandoff, qaLoopShouldRequestAppHandoff } from '../codex-app/
17
17
  import { writeCodex0138CapabilityArtifacts } from '../codex-control/codex-0138-capability.js';
18
18
  import { writeCodexAccountUsageArtifacts } from '../usage/codex-account-usage.js';
19
19
  import { buildQaLoopBudgetPolicy, selectQaLoopEscalatedEffort } from '../qa-loop/qa-loop-budget-policy.js';
20
+ import { initializeQaRuntimeArtifacts } from '../qa-loop/qa-runtime-artifacts.js';
21
+ import { DEFAULT_QA_MAX_CYCLES, QA_SURFACE_SELECTION_ARTIFACT } from '../qa-loop/qa-types.js';
20
22
  import { writeCodexModelEffortCapabilityArtifact } from '../codex-control/codex-model-capabilities.js';
21
23
  import { discoverImageArtifactsInDir, writeImageArtifactPathContract } from '../image/image-artifact-path-contract.js';
22
24
  import { pluginAppTemplatePolicy } from '../codex-plugins/codex-plugin-json.js';
@@ -41,7 +43,7 @@ export async function qaLoopCommand(sub, args = []) {
41
43
  Usage:
42
44
  sks qa-loop prepare "target"
43
45
  sks qa-loop answer <mission-id|latest> <answers.json>
44
- sks qa-loop run <mission-id|latest> [--mock] [--max-cycles N] [--app-handoff] [--app-handoff-required] [--app-handoff-launch] [--app-handoff-artifact-only]
46
+ sks qa-loop run <mission-id|latest> [--mock] [--max-cycles N] [--surface auto|codex_in_app_browser|codex_chrome_extension|codex_computer_use] [--report-only] [--app-handoff] [--app-handoff-required] [--app-handoff-launch] [--app-handoff-artifact-only]
45
47
  sks qa-loop app-confirm <mission-id|latest> --verdict pass|fail --notes "..."
46
48
  sks qa-loop status <mission-id|latest> [--desktop]
47
49
  `);
@@ -126,6 +128,17 @@ async function qaLoopRun(args) {
126
128
  await writeQaLoopArtifacts(dir, mission, contract);
127
129
  else
128
130
  await ensureQaLoopVisualEvidenceContract(dir, mission, contract);
131
+ const requestedSurface = readFlagValue(args, '--surface', 'auto');
132
+ const reportOnly = flag(args, '--report-only');
133
+ await initializeQaRuntimeArtifacts(dir, {
134
+ ...contract,
135
+ prompt: mission.prompt || contract.prompt,
136
+ mission_id: id
137
+ }, {
138
+ missionId: id,
139
+ requestedSurface,
140
+ reportOnly
141
+ }).catch(() => null);
129
142
  const safetyScan = await scanDbSafety(root);
130
143
  if (!safetyScan.ok) {
131
144
  console.error('QA-LOOP cannot run: SKS safety scan found unsafe project data-tool configuration.');
@@ -133,7 +146,7 @@ async function qaLoopRun(args) {
133
146
  process.exitCode = 2;
134
147
  return;
135
148
  }
136
- const fallbackCycles = Number.parseInt(contract.answers?.MAX_QA_CYCLES, 10) || 8;
149
+ const fallbackCycles = Number.parseInt(contract.answers?.MAX_QA_CYCLES, 10) || DEFAULT_QA_MAX_CYCLES;
137
150
  const maxCycles = readMaxCycles(args, fallbackCycles);
138
151
  const requestedAgents = readBoundedIntegerFlag(args, '--agents', 3, 1, 20);
139
152
  const targetActiveSlots = readBoundedIntegerFlag(args, '--target-active-slots', requestedAgents, 1, 20);
@@ -141,15 +154,18 @@ async function qaLoopRun(args) {
141
154
  const minimumWorkItems = readBoundedIntegerFlag(args, '--minimum-work-items', targetActiveSlots, 1, 200);
142
155
  const maxQueueExpansion = readBoundedIntegerFlag(args, '--max-queue-expansion', 10, 0, 200);
143
156
  const profile = readFlagValue(args, '--profile', 'sks-logic-high') || 'sks-logic-high';
144
- const writeMode = readFlagValue(args, '--write-mode', flag(args, '--parallel-write') ? 'parallel' : 'off');
145
- const applyPatches = flag(args, '--apply-patches');
157
+ const mock = flag(args, '--mock');
158
+ const sourceFixesEnabled = !reportOnly;
159
+ const writeMode = readFlagValue(args, '--write-mode', sourceFixesEnabled && !mock ? (flag(args, '--parallel-write') ? 'parallel' : 'proof-safe') : 'off');
160
+ const applyPatches = sourceFixesEnabled && !mock && !flag(args, '--no-fix');
146
161
  const dryRunPatches = flag(args, '--dry-run-patches') || flag(args, '--dryrun-patches');
147
162
  const maxWriteAgents = readBoundedIntegerFlag(args, '--max-write-agents', Math.min(requestedAgents, 5), 1, 20);
148
- const mock = flag(args, '--mock');
149
163
  const qaGate = await readJson(path.join(dir, 'qa-gate.json'), {});
150
164
  const reportFile = qaGate.qa_report_file;
151
165
  const executionProfile = await readJson(path.join(dir, 'qa-loop', 'execution-profile.json'), null);
152
166
  const uiRequired = qaUiRequired(contract.answers || {});
167
+ const surfaceSelection = await readJson(path.join(dir, QA_SURFACE_SELECTION_ARTIFACT), null);
168
+ const selectedSurface = surfaceSelection?.selected_surface || null;
153
169
  const gptImage2ReviewRequired = qaGptImage2AnnotatedReviewRequired(contract, mission.prompt);
154
170
  const capabilityArtifact = await writeCodex0138CapabilityArtifacts(root, { missionId: id }).catch((err) => ({ error: err?.message || String(err), report: null }));
155
171
  const usageArtifact = await writeCodexAccountUsageArtifacts(root, { missionId: id }).catch((err) => ({ error: err?.message || String(err), snapshot: null }));
@@ -246,7 +262,7 @@ async function qaLoopRun(args) {
246
262
  return;
247
263
  }
248
264
  }
249
- if (uiRequired && !mock) {
265
+ if (uiRequired && !mock && selectedSurface === 'codex_chrome_extension') {
250
266
  const chrome = await codexChromeExtensionStatus();
251
267
  if (!chrome.ok) {
252
268
  const blockedGate = {
@@ -277,7 +293,7 @@ async function qaLoopRun(args) {
277
293
  await setCurrent(root, { mission_id: id, mode: 'QALOOP', phase: 'QALOOP_BLOCKED_CHROME_EXTENSION_SETUP_REQUIRED', questions_allowed: true });
278
294
  if (flag(args, '--json'))
279
295
  return console.log(JSON.stringify({ schema: 'sks.qa-loop-run.v1', ok: false, status: 'blocked', blocker: 'codex_chrome_extension_setup_required', mission_id: id, chrome_extension: chrome, gate: blockedGate }, null, 2));
280
- console.error('QA-LOOP blocked: install/enable the Codex Chrome Extension first, then tell SKS installation is complete before resuming.');
296
+ console.error('QA-LOOP blocked: this journey was routed to @Chrome, but the Codex Chrome Extension is not connected. Install/enable it, then resume.');
281
297
  console.error(chrome.docs_url);
282
298
  process.exitCode = 2;
283
299
  return;
@@ -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 = {}) {
@@ -40,8 +40,8 @@ export async function repairSupabaseMcp(input) {
40
40
  manual_required: manualRequired,
41
41
  next_action: manualRequired
42
42
  ? tokenEnvPresent
43
- ? 'Set Supabase MCP to read-only or explicitly approve write-scoped MCP use.'
44
- : 'Set SUPABASE_ACCESS_TOKEN only if Supabase write MCP features are required; otherwise keep Supabase MCP disabled/read-only.'
43
+ ? 'Set persistent Supabase MCP to read-only. Write-scoped Supabase MCP is allowed only through a mission-local MadDB runtime profile.'
44
+ : 'Set SUPABASE_ACCESS_TOKEN only when an explicit MadDB run needs Supabase MCP auth; otherwise keep persistent Supabase MCP disabled/read-only.'
45
45
  : null,
46
46
  blockers: readyBlocking ? ['supabase_mcp_write_access_not_safe_by_default'] : [],
47
47
  warnings: [
@@ -871,7 +871,7 @@ function routeKnownGaps(command) {
871
871
  if (command === '$MAD-SKS')
872
872
  return ['permission closed by owning gate'];
873
873
  if (command === '$MAD-DB')
874
- return ['one-cycle capability must be explicitly enabled, consumed, or revoked'];
874
+ return ['active cycle must execute requested SQL-plane work, read back postconditions, and close the mission-local write profile'];
875
875
  return [];
876
876
  }
877
877
  function checkRow(id, ok, blockers = []) {
package/dist/core/fsx.js CHANGED
@@ -5,7 +5,7 @@ import os from 'node:os';
5
5
  import crypto from 'node:crypto';
6
6
  import { spawn } from 'node:child_process';
7
7
  import { fileURLToPath } from 'node:url';
8
- export const PACKAGE_VERSION = '4.1.1';
8
+ export const PACKAGE_VERSION = '4.2.1';
9
9
  export const DEFAULT_PROCESS_TAIL_BYTES = 256 * 1024;
10
10
  export const DEFAULT_PROCESS_TIMEOUT_MS = 30 * 60 * 1000;
11
11
  export function nowIso() {
@@ -590,7 +590,7 @@ function clarificationAnswerToolAllowed(payload = {}) {
590
590
  return true;
591
591
  if (/\bpipeline\s+answer\b/i.test(command))
592
592
  return true;
593
- return !/\b(npm|git|selftest|packcheck|release:check|publish:dry|publish:npm|doctor|team|qa-loop|wiki|db|test)\b/i.test(command);
593
+ return !/\b(npm|git|selftest|packcheck|release:check|publish:dry|publish:ignore-scripts|publish:npm|doctor|team|qa-loop|wiki|db|test)\b/i.test(command);
594
594
  }
595
595
  function payloadMentionsAnswersJson(payload = {}) {
596
596
  try {
package/dist/core/init.js CHANGED
@@ -13,6 +13,7 @@ import { CODEX_HOOK_EVENT_STATE_KEYS } from './codex-compat/codex-hook-events.js
13
13
  import { codexCommandHookCurrentHash } from './codex-hooks/codex-hook-hash.js';
14
14
  import { buildSksCoreSkillManifest, isCoreSkillName } from './codex-native/core-skill-manifest.js';
15
15
  import { syncCoreSkillsIntegrity } from './codex-native/core-skill-integrity.js';
16
+ import { dbSafetyGuardSkillText, madDbSkillText } from './mad-db/mad-db-policy.js';
16
17
  const REFLECTION_MEMORY_PATH = '.sneakoscope/memory/q2_facts/post-route-reflection.md';
17
18
  const SKS_GENERATED_GIT_PATTERNS = [
18
19
  '.sneakoscope/missions/',
@@ -351,7 +352,7 @@ export async function initProject(root, opts = {}) {
351
352
  state: 'git-common-dir/sks-version-state.json'
352
353
  }
353
354
  },
354
- database_safety: 'default_safe; $MAD-SKS scoped permission profile is centralized in src/core/permission-gates.ts (emitted as dist/core/permission-gates.js) and keeps catastrophic safeguards active',
355
+ database_safety: 'default_safe; $MAD-SKS scoped permission profile keeps catastrophic safeguards active; first-class $MAD-DB is the explicit SQL-plane execution exception with mission-local write transport and read-back proof',
355
356
  gx_renderer: 'deterministic_svg_html'
356
357
  };
357
358
  await writeJsonAtomic(manifestPath, manifest);
@@ -826,7 +827,7 @@ export async function initProject(root, opts = {}) {
826
827
  // them relocated into the home config by the splitter, re-triggering the warning.
827
828
  {
828
829
  table: 'auto_review',
829
- text: '[auto_review]\npolicy = "In MAD launches, allow live-server work, normal DB writes, Supabase MCP DB writes, direct execute SQL, schema cleanup, and migration application for the active invocation. Deny only catastrophic database wipes, all-row value deletion/update, dangerous project or branch management, credential exfiltration, persistent security weakening, broad unrelated file deletion, and unrequested fallback implementation code."'
830
+ text: '[auto_review]\npolicy = "In MAD-SKS launches, allow only the scoped non-MadDB high-risk surfaces approved for the active invocation and keep catastrophic DB wipe/all-row safeguards active. In first-class MAD-DB cycles, the explicit $MAD-DB or sks mad-db run|exec|apply-migration invocation is the SQL-plane approval boundary: execute requested execute_sql/apply_migration mutations with mission-local write transport, read-back proof, and final read-only restoration. Supabase project/account/billing/credential control-plane actions remain denied."'
830
831
  }
831
832
  ];
832
833
  }
@@ -1058,7 +1059,7 @@ export async function installSkills(root) {
1058
1059
  'research': `---\nname: research\ndescription: Dollar-command route for $Research or $research frontier discovery workflows.\n---\n\nUse when the user invokes $Research/$research or asks for research, hypotheses, new mechanisms, falsification, or testable predictions. Prefer sks research prepare and sks research run. Research is not an implementation route: do not edit repository source, docs, package metadata, generated skills, or harness files; write only route-local mission artifacts under .sneakoscope/missions/<mission-id>/. Run the genius-lens agent council with named persona-inspired cognitive roles: Einstein Agent, Feynman Agent, Turing Agent, von Neumann Agent, and Skeptic Agent. These are lenses only; do not impersonate the historical people. Every Research agent ledger row must include display_name, persona, persona_boundary, effort=xhigh, reasoning_effort=xhigh, service_tier when available, one literal "Eureka!" idea, falsifiers, cheap_probes, and challenge_or_response before synthesis. This is not a fixed three-cycle route: repeat source gathering, Eureka ideas, evidence-bound debate, falsification, and synthesis pressure until every agent records final agreement, or until the explicit max-cycle safety cap pauses with an unpassed gate. Create research-source-skill.md as a route-local Skill Creator artifact, then maximize layered public web/source search across latest papers, official/government or leading-institution data, standards/primary docs, current news, public discourse, developer/practitioner sources, traditional background sources, and counterevidence before synthesis. Record research-source-skill.md, source-ledger.json, agent-ledger.json, debate-ledger.json, novelty-ledger.json, falsification-ledger.json, research-report.md, research-paper.md, genius-opinion-summary.md, and research-gate.json. debate-ledger.json must include consensus_iterations, unanimous_consensus, and per-agent agreements; research-gate.json cannot pass until unanimous_consensus=true with every agent agreement recorded. Context7 is optional and only needed when the research topic depends on external package/API/framework docs; do not use it as the default research evidence layer. Normal Research may take one or two hours when needed; favor real source collection, cross-layer comparison, falsification, and a concise paper manuscript over speed. Do not use --mock except for selftests or dry harness checks; if live source execution is unavailable, record a blocker and keep the gate unpassed. Do not use for ordinary code edits.\n`,
1059
1060
  'autoresearch': `---\nname: autoresearch\ndescription: Dollar-command route for $AutoResearch or $autoresearch iterative experiment loops.\n---\n\nUse for $AutoResearch, iterative improvement, SEO/GEO, ranking, workflow, benchmark, or experiments. Define program, hypothesis, experiment, metric, keep/discard, falsification, next step, and Honest Mode. Load seo-geo-optimizer for README/npm/GitHub/schema/AI-search work.\n`,
1060
1061
  'db': `---\nname: db\ndescription: Dollar-command route for $DB or $db database and Supabase safety checks.\n---\n\nUse when the user invokes $DB/$db or the task touches SQL, Supabase, Postgres, migrations, Prisma, Drizzle, Knex, MCP database tools, or production data. Run or follow sks db policy, sks db scan, sks db classify, and sks db check. Destructive database operations remain forbidden.\n`,
1061
- 'mad-db': `---\nname: mad-db\ndescription: One-cycle Mad-DB break-glass route alias for $MAD-DB and $mad-db database safety work.\n---\n\nUse only when the user explicitly invokes $MAD-DB/$mad-db or asks for Mad-DB visibility. Treat it as a DB safety route with one-cycle break-glass controls, not as a general permanent DB unlock. Prefer \`sks mad-db status --json\` for inspection, \`sks mad-db enable --ack "I AUTHORIZE ONE-CYCLE DB BREAK-GLASS" [--mission latest|new|M-...] --json\` only after explicit user authorization, and \`sks mad-db revoke --mission <id|latest> --json\` to close the cycle. Keep catastrophic safeguards active: whole database/schema/table removal, truncate, all-row delete/update, reset, dangerous project/branch management, credential exfiltration, persistent security weakening, and unrequested fallback implementation remain blocked. Pair with db-safety-guard, Context7 evidence when external DB/API docs are involved, route-local reflection, and Honest Mode.\n`,
1062
+ 'mad-db': `${madDbSkillText()}\n`,
1062
1063
  'mad-sks': `---\nname: mad-sks\ndescription: Explicit high-risk authorization modifier for $MAD-SKS scoped permission widening across approved target-project surfaces.\n---\n\nUse only when the user explicitly invokes $MAD-SKS or top-level sks --mad. It can be combined with another route, such as $MAD-SKS $Team or $DB ... $MAD-SKS; in that case the other command remains the primary workflow and MAD-SKS is only the temporary permission grant. The widened permission applies only while the active mission gate is open, must be deactivated when the task ends, and can open approved scopes such as target-project file writes, shell commands, package installs, local service control, network operations, browser/Computer Use workflows, generated assets, file permissions, migrations, Supabase MCP database writes, column/schema cleanup, direct execute SQL, and normal targeted DB writes. Keep catastrophic safeguards active: whole database/schema/table removal, truncate, all-row delete/update, reset, dangerous project/branch management, credential exfiltration, persistent security weakening, destructive delete without explicit confirmation, and unrequested fallback implementation remain blocked. Do not carry MAD-SKS permission into later prompts or routes. The permission profile source is centralized in src/core/permission-gates.ts and emitted as dist/core/permission-gates.js so skill/hook/MCP-style gates share one decision function.\n`,
1063
1064
  'gx': `---\nname: gx\ndescription: Dollar-command route for $GX or $gx deterministic GX visual context cartridges.\n---\n\nUse when the user invokes $GX/$gx or asks for architecture/context visualization through SKS. Prefer sks gx init, render, validate, drift, and snapshot. vgraph.json remains the source of truth.\n`,
1064
1065
  'help': `---\nname: help\ndescription: Dollar-command route for $Help or $help explaining installed SKS commands and workflows.\n---\n\nUse when the user invokes $Help/$help or asks what commands exist. Prefer concise output from sks commands, sks usage <topic>, sks quickstart, sks aliases, and sks codex-app.\n`,
@@ -1073,7 +1074,7 @@ export async function installSkills(root) {
1073
1074
  'autoresearch-loop': `---\nname: autoresearch-loop\ndescription: Iterative AutoResearch-style loop for open-ended improvement, discovery, prompt, ranking, SEO/GEO, and workflow-quality tasks.\n---\n\nUse for research, ranking, prompt/workflow improvement, benchmark gains, or repeated refinement. Loop: program, hypothesis, smallest falsifying experiment, metric, keep/discard, falsify, next step. Keep a ledger and do not claim improvement without evidence.\n`,
1074
1075
  'hproof-claim-ledger': `---\nname: hproof-claim-ledger\ndescription: Extract atomic claims and classify support status.\n---\n\nEvery factual statement must become an atomic claim. Unsupported critical claims cannot be used for implementation or final answer. Database claims require DB safety evidence.\n`,
1075
1076
  'hproof-evidence-bind': `---\nname: hproof-evidence-bind\ndescription: Bind claims to code, tests, decision contract, vgraph, beta, wiki, or GX render evidence.\n---\n\nEvidence priority: current code/tests, decision-contract.json, vgraph.json, beta.json, GX snapshot/render metadata, LLM Wiki coordinate index, user prompt. Database claims must respect .sneakoscope/db-safety.json. Wiki claims should carry id, hash, source path, and RGBA/trig coordinate anchors so they can be hydrated instead of treated as unsupported summaries.\n`,
1076
- 'db-safety-guard': `---\nname: db-safety-guard\ndescription: Enforce Sneakoscope Codex database safety before using SQL, Supabase MCP, Postgres, Prisma, Drizzle, Knex, or migration commands.\n---\n\nRules:\n- Never run DROP, TRUNCATE, mass DELETE/UPDATE, db reset, db push, project deletion, branch reset/merge/delete, or RLS-disabling operations.\n- Supabase MCP must be read-only and project-scoped by default.\n- Live writes through execute_sql are blocked; use migration files and only local/preview branches if explicitly allowed.\n- Production writes are forbidden.\n- If unsure, read-only only.\n`,
1077
+ 'db-safety-guard': `${dbSafetyGuardSkillText()}\n`,
1077
1078
  'gx-visual-generate': `---\nname: gx-visual-generate\ndescription: Render a deterministic SVG/HTML visual sheet from vgraph.json and beta.json.\n---\n\nUse sks gx render. vgraph.json is source of truth; renders embed source hash and RGBA wiki anchors.\n`,
1078
1079
  'gx-visual-read': `---\nname: gx-visual-read\ndescription: Read a Sneakoscope Codex deterministic visual sheet and produce context notes.\n---\n\nExtract nodes, edges, invariants, tests, risks, uncertainties, and RGBA anchors from source/render/snapshot. Do not infer hidden nodes.\n`,
1079
1080
  'gx-visual-validate': `---\nname: gx-visual-validate\ndescription: Validate render metadata against vgraph.json and beta.json.\n---\n\nRun sks gx validate and drift; fail stale or incomplete hashes, nodes, edges, invariants, or anchors.\n`,