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
@@ -0,0 +1,64 @@
1
+ import path from 'node:path';
2
+ import { exists, readText, sha256 } from '../fsx.js';
3
+ export async function resolveMadDbTarget(root, input = {}) {
4
+ const args = input.args || [];
5
+ const explicit = input.projectRef || readOption(args, '--project-ref', '') || process.env.SKS_MAD_DB_PROJECT_REF || process.env.SKS_MAD_DB_E2E_PROJECT_REF || '';
6
+ const candidates = explicit ? [explicit] : await projectRefCandidates(root);
7
+ const projectRef = explicit || (candidates.length === 1 ? candidates[0] || '' : '');
8
+ const target = normalizeTarget(input.target || readOption(args, '--target', '') || process.env.SKS_MAD_DB_TARGET || process.env.SKS_MAD_DB_E2E_TARGET || 'production');
9
+ const allowedSchemas = input.allowedSchemas?.length
10
+ ? input.allowedSchemas
11
+ : splitCsv(readOption(args, '--schema', readOption(args, '--schemas', process.env.SKS_MAD_DB_SCHEMAS || 'public')));
12
+ const blockers = [];
13
+ if (!projectRef)
14
+ blockers.push(candidates.length > 1 ? 'mad_db_project_ref_ambiguous' : 'mad_db_project_ref_missing');
15
+ return {
16
+ schema: 'sks.mad-db-target.v1',
17
+ project_ref: projectRef || null,
18
+ project_ref_hash: projectRef ? sha256(projectRef).slice(0, 16) : null,
19
+ target_environment: target,
20
+ allowed_schemas: allowedSchemas.length ? allowedSchemas : ['public'],
21
+ source: explicit ? 'explicit_or_environment' : candidates.length === 1 ? 'managed_config_single_candidate' : 'unresolved',
22
+ blockers,
23
+ candidates: candidates.map((candidate) => `${sha256(candidate).slice(0, 8)}:${candidate.slice(0, 2)}...`)
24
+ };
25
+ }
26
+ export async function projectRootHash(root) {
27
+ return sha256(path.resolve(root)).slice(0, 24);
28
+ }
29
+ async function projectRefCandidates(root) {
30
+ const files = ['.codex/config.toml', '.mcp.json', 'mcp.json', '.cursor/mcp.json', '.vscode/mcp.json'];
31
+ const out = new Set();
32
+ for (const rel of files) {
33
+ const file = path.join(root, rel);
34
+ if (!(await exists(file)))
35
+ continue;
36
+ const text = await readText(file, '');
37
+ for (const match of String(text).matchAll(/project_ref=([a-z0-9_-]+)/gi))
38
+ out.add(match[1] || '');
39
+ for (const match of String(text).matchAll(/project_ref["']?\s*[:=]\s*["']([a-z0-9_-]+)["']/gi))
40
+ out.add(match[1] || '');
41
+ }
42
+ return [...out].filter(Boolean);
43
+ }
44
+ function normalizeTarget(value) {
45
+ const text = String(value || '').toLowerCase();
46
+ if (text === 'local')
47
+ return 'local';
48
+ if (text === 'branch')
49
+ return 'branch';
50
+ if (text === 'preview')
51
+ return 'preview';
52
+ return 'production';
53
+ }
54
+ function splitCsv(value) {
55
+ return String(value || '').split(',').map((entry) => entry.trim()).filter(Boolean);
56
+ }
57
+ function readOption(args, name, fallback) {
58
+ const index = args.indexOf(name);
59
+ if (index >= 0 && args[index + 1] && !String(args[index + 1]).startsWith('--'))
60
+ return String(args[index + 1]);
61
+ const prefixed = args.find((arg) => String(arg).startsWith(`${name}=`));
62
+ return prefixed ? prefixed.slice(name.length + 1) : fallback;
63
+ }
64
+ //# sourceMappingURL=mad-db-target.js.map
@@ -1,15 +1,15 @@
1
1
  import { REQUIRED_CODEX_MODEL } from '../codex-model-guard.js';
2
2
  export const MANAGED_ASSET_SCHEMA_VERSION = 1;
3
- export const MANAGED_ASSET_VERSION = '4.1.0';
3
+ export const MANAGED_ASSET_VERSION = '4.2.0';
4
4
  export const MANAGED_ASSET_MARKER = 'SKS-MANAGED-ASSET';
5
5
  export const MANAGED_AGENT_ROLES = Object.freeze([
6
6
  role('sks-explorer', 'analysis-scout.toml', 'analysis_scout', 'Read-only SKS analysis scout retained for stale Codex agent-role config repair.', 'read-only', ['analysis-scout', 'analysis_scout', 'native_agent']),
7
7
  role('sks-planner', 'team-consensus.toml', 'team_consensus', 'Planning and debate specialist for SKS Team mode.', 'read-only', ['team-consensus', 'team_consensus']),
8
8
  role('sks-implementer', 'implementation-worker.toml', 'implementation_worker', 'Implementation specialist for bounded SKS Team write sets.', 'workspace-write', ['implementation-worker', 'implementation_worker']),
9
9
  role('sks-checker', 'qa-reviewer.toml', 'qa_reviewer', 'Strict read-only verification reviewer for correctness, regressions, and final evidence.', 'read-only', ['qa-reviewer', 'qa_reviewer']),
10
- role('sks-release-verifier', 'native-agent-intake.toml', 'native_agent', 'Read-only Team native agent for repository/docs/tests/API/risk slices.', 'read-only', ['native-agent-intake', 'native_agent']),
11
- role('sks-zellij-ui-verifier', 'native-agent-intake.toml', 'native_agent', 'Read-only Team native agent for repository/docs/tests/API/risk slices.', 'read-only', ['native-agent-intake', 'native_agent']),
12
- role('sks-codex-probe-verifier', 'native-agent-intake.toml', 'native_agent', 'Read-only Team native agent for repository/docs/tests/API/risk slices.', 'read-only', ['native-agent-intake', 'native_agent']),
10
+ role('sks-release-verifier', 'sks-release-verifier.toml', 'sks_release_verifier', 'Read-only release verifier for repository, docs, tests, API, and risk slices.', 'read-only', ['native-agent-intake', 'native_agent', 'release-verifier']),
11
+ role('sks-zellij-ui-verifier', 'sks-zellij-ui-verifier.toml', 'sks_zellij_ui_verifier', 'Read-only Zellij UI verifier for session, pane, layout, and terminal evidence.', 'read-only', ['native-agent-intake', 'native_agent', 'zellij-ui-verifier']),
12
+ role('sks-codex-probe-verifier', 'sks-codex-probe-verifier.toml', 'sks_codex_probe_verifier', 'Read-only Codex probe verifier for CLI, App, SDK, MCP, and native capability evidence.', 'read-only', ['native-agent-intake', 'native_agent', 'codex-probe-verifier']),
13
13
  role('db-safety-reviewer', 'db-safety-reviewer.toml', 'db_safety_reviewer', 'Read-only database safety reviewer for SQL, migrations, Supabase, and rollback safety.', 'read-only', ['db-safety-reviewer', 'db_safety_reviewer'])
14
14
  ]);
15
15
  export const MANAGED_SKILLS = Object.freeze([
@@ -41,6 +41,7 @@ export const CONTEXT7_MANAGED_SERVER = Object.freeze({
41
41
  });
42
42
  export function managedAgentRoleByFile(filename) {
43
43
  const base = filename.split(/[\\/]/).pop() || filename;
44
+ assertUniqueManagedAgentRoleFilenames();
44
45
  return MANAGED_AGENT_ROLES.find((role) => role.filename === base) || null;
45
46
  }
46
47
  export function managedAgentRoleByName(name) {
@@ -87,6 +88,15 @@ export function managedAgentRoleOwnsText(text, role) {
87
88
  export function normalizeRoleName(name) {
88
89
  return String(name || '').trim().replace(/\.toml$/i, '').replace(/_/g, '-').toLowerCase();
89
90
  }
91
+ export function assertUniqueManagedAgentRoleFilenames() {
92
+ const seen = new Map();
93
+ for (const role of MANAGED_AGENT_ROLES) {
94
+ const existing = seen.get(role.filename);
95
+ if (existing)
96
+ throw new Error(`duplicate managed agent role filename: ${role.filename} for ${existing} and ${role.id}`);
97
+ seen.set(role.filename, role.id);
98
+ }
99
+ }
90
100
  function role(id, filename, codexName, description, sandbox, aliases) {
91
101
  return {
92
102
  id,
@@ -22,6 +22,7 @@ import { SPEED_LANE_POLICY } from '../proof-field.js';
22
22
  import { validateRouteCompletionProof } from '../proof/route-proof-gate.js';
23
23
  import { routeFromState, routeRequiresCompletionProof } from '../proof/route-proof-policy.js';
24
24
  import { permissionGateSummary } from '../permission-gates.js';
25
+ import { prepareMadDbMission } from '../mad-db/mad-db-coordinator.js';
25
26
  import { AGENT_INTAKE_STAGE_ID, AGENT_COUNT } from '../agents/agent-schema.js';
26
27
  import { normalizeAgentPolicy, routeRequiresAgentIntake, agentPipelineStage } from '../agents/agent-plan.js';
27
28
  import { readAgentGateStatus } from '../agents/agent-gate.js';
@@ -458,6 +459,8 @@ export function promptPipelineContext(prompt, route = null) {
458
459
  lines.push('AutoResearch route: load autoresearch-loop plus seo-geo-optimizer when SEO/GEO, discoverability, README, npm, GitHub stars, ranking, or AI-search visibility is relevant.');
459
460
  if (route?.id === 'DB')
460
461
  lines.push('DB route: scan/check database risk first; destructive DB operations remain forbidden.');
462
+ if (route?.id === 'MadDB')
463
+ lines.push('MadDB route: explicit invocation is the SQL-plane approval boundary. Use the mission-local write-capable Supabase MCP profile only for the bound cycle, verify execute_sql/apply_migration inventory before claiming ready, execute requested SQL-plane mutations, read back postconditions, then close the capability/profile and prove normal read-only restoration. Supabase project/account/billing/credential control-plane actions remain denied.');
461
464
  if (route?.id === 'GX')
462
465
  lines.push('GX route: use deterministic vgraph/beta render, validate, drift, and snapshot artifacts.');
463
466
  return lines.join('\n');
@@ -517,6 +520,8 @@ export async function prepareRoute(root, prompt, state = {}) {
517
520
  return withSkillDreamContext(await prepareGoal(root, route, task, routeNeedsContext7(route, cleanPrompt)), dreamContext);
518
521
  if (route.id === 'ImageUXReview')
519
522
  return withSkillDreamContext(await prepareImageUxReview(root, route, task, routeNeedsContext7(route, cleanPrompt)), dreamContext);
523
+ if (route.id === 'MadDB')
524
+ return withSkillDreamContext(await prepareMadDb(root, route, task, routeNeedsContext7(route, cleanPrompt)), dreamContext);
520
525
  const required = routeNeedsContext7(route, cleanPrompt);
521
526
  const reasoning = routeReasoning(route, cleanPrompt);
522
527
  const nativeSessionsRequired = routeRequiresSubagents(route, cleanPrompt);
@@ -1111,6 +1116,41 @@ async function prepareDb(root, route, task, required) {
1111
1116
  await setCurrent(root, routeState(id, route, 'DB_REVIEW_REQUIRED', required, { prompt: task, pipeline_plan_ready: validatePipelinePlan(pipelinePlan).ok, pipeline_plan_path: PIPELINE_PLAN_ARTIFACT }));
1112
1117
  return routeContext(route, id, task, required, 'Run sks db policy/scan/check as needed, keep DB operations read-only, record safe MCP policy, and pass db-review.json.');
1113
1118
  }
1119
+ async function prepareMadDb(root, route, task, required) {
1120
+ const prepared = await prepareMadDbMission({ root, task, verifyTools: false });
1121
+ const dir = missionDir(root, prepared.mission_id);
1122
+ const pipelinePlan = await writePipelinePlan(dir, {
1123
+ missionId: prepared.mission_id,
1124
+ route,
1125
+ task,
1126
+ required,
1127
+ ambiguity: { required: true, slots: 0, auto_sealed: true, passed: true, contract_hash: prepared.capability.operator_intent_hash }
1128
+ });
1129
+ await appendJsonl(path.join(dir, 'events.jsonl'), {
1130
+ ts: nowIso(),
1131
+ type: 'mad_db.route_prepared',
1132
+ mission_id: prepared.mission_id,
1133
+ cycle_id: prepared.cycle_id,
1134
+ blockers: prepared.blockers
1135
+ });
1136
+ await setCurrent(root, routeState(prepared.mission_id, route, prepared.ok ? 'MADDB_SQL_PLANE_CAPABILITY_ACTIVE' : 'MADDB_BLOCKED', required, {
1137
+ prompt: task,
1138
+ questions_allowed: false,
1139
+ implementation_allowed: prepared.ok,
1140
+ ambiguity_gate_required: true,
1141
+ ambiguity_gate_passed: true,
1142
+ mad_db_active: prepared.ok,
1143
+ mad_db_cycle_id: prepared.cycle_id,
1144
+ mad_db_runtime_session_id: prepared.capability.runtime_session_id,
1145
+ mad_db_profile_sha256: prepared.capability.transport.profile_sha256,
1146
+ mad_db_capability_mission_id: prepared.mission_id,
1147
+ mad_db_capability_file: 'mad-db-capability.json',
1148
+ stop_gate: 'mad-db-gate.json',
1149
+ pipeline_plan_ready: validatePipelinePlan(pipelinePlan).ok,
1150
+ pipeline_plan_path: PIPELINE_PLAN_ARTIFACT
1151
+ }));
1152
+ return routeContext(route, prepared.mission_id, task, required, `MadDB mission/capability/profile were created atomically for cycle ${prepared.cycle_id}. Verify Supabase MCP tool inventory exposes execute_sql and apply_migration before claiming ready; after execution require read-back proof, finally close the profile/capability and prove read-only restoration.`);
1153
+ }
1114
1154
  async function prepareGx(root, route, task, required) {
1115
1155
  const { id, dir } = await createMission(root, { mode: 'gx', prompt: task });
1116
1156
  await writeJsonAtomic(path.join(dir, 'gx-gate.json'), { passed: false, vgraph_beta_render: false, validation: false, drift_snapshot: false, context7_evidence: false });
@@ -13,6 +13,7 @@ import { runGlmDirectBenchCase } from './glm-direct-bench-runner.js';
13
13
  import { computeGlmBenchmarkComparison } from './glm-bench-comparison.js';
14
14
  import { buildGlmBenchModelLockProof } from './glm-bench-model-lock-proof.js';
15
15
  import { writeGlmBenchReport } from './glm-bench-report.js';
16
+ import { GLM_BENCHMARK_VERSION } from './glm-benchmark-types.js';
16
17
  const NARUTO_WORKER_COUNTS = [1, 4, 8, 12];
17
18
  export async function runGlmBenchmark(root, args = [], deps = {}) {
18
19
  const live = args.includes('--live');
@@ -130,7 +131,7 @@ export async function runGlmBenchmark(root, args = [], deps = {}) {
130
131
  };
131
132
  const result = {
132
133
  schema: 'sks.glm-benchmark-result.v1',
133
- version: '4.1.0',
134
+ version: GLM_BENCHMARK_VERSION,
134
135
  generated_at: nowIso(),
135
136
  status: 'live',
136
137
  model: GLM_52_OPENROUTER_MODEL,
@@ -157,7 +158,7 @@ export async function runGlmBenchmark(root, args = [], deps = {}) {
157
158
  function dryRunResult(root, startedMs) {
158
159
  return {
159
160
  schema: 'sks.glm-benchmark-result.v1',
160
- version: '4.1.0',
161
+ version: GLM_BENCHMARK_VERSION,
161
162
  generated_at: nowIso(),
162
163
  status: 'dry_run',
163
164
  model: GLM_52_OPENROUTER_MODEL,
@@ -180,7 +181,7 @@ function dryRunResult(root, startedMs) {
180
181
  function blockedResult(root, warnings) {
181
182
  return {
182
183
  schema: 'sks.glm-benchmark-result.v1',
183
- version: '4.1.0',
184
+ version: GLM_BENCHMARK_VERSION,
184
185
  generated_at: nowIso(),
185
186
  status: 'blocked',
186
187
  model: GLM_52_OPENROUTER_MODEL,
@@ -1,2 +1,2 @@
1
- export const GLM_BENCHMARK_VERSION = '4.1.0';
1
+ export const GLM_BENCHMARK_VERSION = '4.2.0';
2
2
  //# sourceMappingURL=glm-benchmark-types.js.map
@@ -28,15 +28,16 @@ export async function runReleaseGateDag(input) {
28
28
  const preset = input.preset || 'release';
29
29
  const manifest = loadReleaseGateManifest(root);
30
30
  const presetGates = selectReleaseGatePreset(manifest, preset);
31
- const triwikiGraph = input.triwiki !== false && (preset === 'affected' || preset === 'fast' || preset === 'confidence') && input.full !== true
32
- ? computeTriWikiAffectedGraph({ root, tier: preset === 'fast' ? 'affected' : 'confidence', changedSince: input.changedSince || 'auto', ...(input.changedFiles ? { changedFiles: input.changedFiles } : {}) })
33
- : null;
34
31
  const affected = (preset === 'affected' || preset === 'fast' || preset === 'confidence') && input.full !== true
35
32
  ? selectAffectedReleaseGates(root, manifest, presetGates, { changedSince: input.changedSince || 'auto', ...(input.changedFiles ? { changedFiles: input.changedFiles } : {}), preset })
36
33
  : selectAffectedReleaseGates(root, manifest, presetGates, { full: true, preset });
34
+ const rootReleaseSurfaceChanged = affected.selection.changed_files.some((file) => file === 'package.json' || file === 'package-lock.json' || file === 'release-gates.v2.json');
35
+ const triwikiGraph = input.triwiki !== false && !rootReleaseSurfaceChanged && (preset === 'affected' || preset === 'fast' || preset === 'confidence') && input.full !== true
36
+ ? computeTriWikiAffectedGraph({ root, tier: preset === 'fast' ? 'affected' : 'confidence', changedSince: input.changedSince || 'auto', ...(input.changedFiles ? { changedFiles: input.changedFiles } : {}) })
37
+ : null;
37
38
  const triwikiSelectionUsed = Boolean(triwikiGraph);
38
39
  const triwikiConservative = Boolean(triwikiGraph?.conservative_reason);
39
- const triwikiSelectedIds = new Set(triwikiGraph && !triwikiConservative ? triwikiGraph.gates : presetGates.map((gate) => gate.id));
40
+ const triwikiSelectedIds = new Set(triwikiGraph && !triwikiConservative ? triwikiGraph.gates : affected.gates.map((gate) => gate.id));
40
41
  const selected = triwikiGraph
41
42
  ? presetGates.filter((gate) => triwikiSelectedIds.has(gate.id))
42
43
  : affected.gates;
@@ -45,7 +46,7 @@ export async function runReleaseGateDag(input) {
45
46
  affected.selection.mode = 'affected';
46
47
  affected.selection.selected_gate_ids = selected.map((gate) => gate.id);
47
48
  affected.selection.skipped_gate_ids = triwikiSkippedGates;
48
- affected.selection.reasons = Object.fromEntries(selected.map((gate) => [gate.id, triwikiConservative ? `triwiki_conservative:${triwikiGraph.conservative_reason}` : 'triwiki-affected']));
49
+ affected.selection.reasons = Object.fromEntries(selected.map((gate) => [gate.id, triwikiConservative ? `triwiki_conservative_fallback:${triwikiGraph.conservative_reason}` : 'triwiki-affected']));
49
50
  }
50
51
  const selectedIds = new Set(selected.map((gate) => gate.id));
51
52
  const affectedExternalSatisfiedDeps = affected.selection.mode === 'affected'
@@ -231,7 +231,7 @@ export function stackCurrentDocsPolicy(commandPrefix = 'sks') {
231
231
  validate_command: `${prefix} wiki validate .sneakoscope/wiki/context-pack.json`,
232
232
  priority: 'must_precede_coding_style_defaults',
233
233
  examples: [
234
- 'Supabase hosted projects should prefer sb_publishable_ and sb_secret_ keys over legacy anon/service_role keys when current docs apply.',
234
+ 'Supabase hosted projects should prefer sb_publishable_ and sb_secret_ keys over legacy anon and service role keys when current docs apply.',
235
235
  'Next.js 16 deprecates the middleware file convention in favor of proxy.ts/proxy.js.',
236
236
  'Vercel Function duration limits, including the 300s default with Fluid Compute, are deployment constraints that must shape long-running server work.'
237
237
  ]
@@ -239,7 +239,7 @@ export function stackCurrentDocsPolicy(commandPrefix = 'sks') {
239
239
  }
240
240
  export function stackCurrentDocsPolicyText(commandPrefix = 'sks') {
241
241
  const policy = stackCurrentDocsPolicy(commandPrefix);
242
- return `Stack current-docs policy: whenever project tech stack is added or a framework/package/runtime/platform version changes, fetch current docs with Context7 (resolve-library-id then query-docs) or official vendor web docs before coding, record the syntax/limits/security guidance as high-priority TriWiki claims in ${policy.memory_path}, run "${policy.refresh_command}", then "${policy.validate_command}". Treat these claims as higher priority than model-memory defaults. Examples include Supabase publishable/secret keys replacing legacy anon/service_role guidance for hosted projects, Next.js 16 proxy.ts/proxy.js replacing the deprecated middleware file convention, avoiding stale webpack defaults when newer framework guidance says otherwise, and Vercel Function duration limits such as the 300s default under Fluid Compute.`;
242
+ return `Stack current-docs policy: whenever project tech stack is added or a framework/package/runtime/platform version changes, fetch current docs with Context7 (resolve-library-id then query-docs) or official vendor web docs before coding, record the syntax/limits/security guidance as high-priority TriWiki claims in ${policy.memory_path}, run "${policy.refresh_command}", then "${policy.validate_command}". Treat these claims as higher priority than model-memory defaults. Examples include Supabase publishable/secret keys replacing legacy anon and service role guidance for hosted projects, Next.js 16 proxy.ts/proxy.js replacing the deprecated middleware file convention, avoiding stale webpack defaults when newer framework guidance says otherwise, and Vercel Function duration limits such as the 300s default under Fluid Compute.`;
243
243
  }
244
244
  export function triwikiContextTrackingText(commandPrefix = 'sks') {
245
245
  const ctx = triwikiContextTracking(commandPrefix);
@@ -549,21 +549,34 @@ export const ROUTES = [
549
549
  cliEntrypoint: 'sks db scan',
550
550
  examples: ['$DB check this migration safely']
551
551
  },
552
+ {
553
+ id: 'MadDB',
554
+ command: '$MAD-DB',
555
+ mode: 'MADDB',
556
+ route: 'first-class MadDB SQL-plane execution',
557
+ description: 'Explicit one-cycle MadDB route. When invoked by $MAD-DB or sks mad-db run|exec|apply-migration, SQL-plane mutations such as CREATE, ALTER, table/schema DROP, column add/drop/rename, INSERT, UPDATE, DELETE including all-row mutations, TRUNCATE, execute_sql, and apply_migration are authorized for the bound Supabase project and must be executed with tool-result plus read-back proof. Supabase project/account/billing/credential control-plane actions remain denied.',
558
+ requiredSkills: ['mad-db', 'db-safety-guard', 'pipeline-runner', 'context7-docs', REFLECTION_SKILL_NAME, 'honest-mode'],
559
+ appSkillAliases: ['mad-db'],
560
+ lifecycle: ['explicit_invocation', 'single_mission_capability_v2', 'ephemeral_write_profile', 'tool_inventory', 'execute_sql_or_apply_migration', 'read_back_verification', 'close_and_read_only_restore', 'post_route_reflection', 'honest_mode'],
561
+ context7Policy: 'required',
562
+ reasoningPolicy: 'xhigh',
563
+ stopGate: 'mad-db-gate.json',
564
+ cliEntrypoint: 'sks mad-db run|exec|apply-migration|status|close|revoke|doctor',
565
+ examples: ['$MAD-DB public.users legacy_code 컬럼 삭제', '$MAD-DB truncate public.staging_events']
566
+ },
552
567
  {
553
568
  id: 'MadSKS',
554
569
  command: '$MAD-SKS',
555
570
  mode: 'MADSKS',
556
571
  route: 'explicit scoped permission-widening modifier',
557
- description: 'Explicit high-risk authorization modifier that can be combined with other $ commands to temporarily open approved target-project scopes such as files, shell, package installs, services, network, Computer Use/browser workflows, generated assets, file permissions, migrations, Supabase MCP DB writes, direct execute SQL, schema cleanup, and normal targeted DB writes for the active invocation, while preserving catastrophic wipe/all-row/project-management, credential-exfiltration, persistent security-weakening, and unrequested fallback safeguards.',
572
+ description: 'Explicit high-risk authorization modifier that can be combined with other $ commands to temporarily open approved target-project scopes such as files, shell, package installs, services, network, Computer Use/browser workflows, generated assets, file permissions, migrations, Supabase MCP DB writes, direct execute SQL, schema cleanup, and normal targeted DB writes for the active invocation, while preserving catastrophic wipe/all-row/project-management, credential-exfiltration, persistent security-weakening, and unrequested fallback safeguards. It is not the first-class MadDB destructive SQL-plane route.',
558
573
  requiredSkills: ['mad-sks', 'db-safety-guard', 'pipeline-runner', 'context7-docs', REFLECTION_SKILL_NAME, 'honest-mode'],
559
- dollarAliases: ['$MAD-DB'],
560
- appSkillAliases: ['mad-db'],
561
574
  lifecycle: ['explicit_invocation', 'auto_sealed_permission_scope', 'scoped_permission_override', 'catastrophic_guard', 'permission_deactivation', 'post_route_reflection', 'honest_mode'],
562
575
  context7Policy: 'required',
563
576
  reasoningPolicy: 'xhigh',
564
577
  stopGate: 'mad-sks-gate.json',
565
578
  cliEntrypoint: 'Codex App prompt route only: $MAD-SKS <task>',
566
- examples: ['$MAD-SKS $Team target project maintenance with package/service/file and DB scopes', '$DB Supabase 점검 $MAD-SKS', '$MAD-DB enable one-cycle DB break-glass only after explicit ack']
579
+ examples: ['$MAD-SKS $Team target project maintenance with package/service/file and DB scopes', '$DB Supabase 점검 $MAD-SKS']
567
580
  },
568
581
  {
569
582
  id: 'GX',
@@ -964,6 +977,8 @@ export function routeRequiresSubagents(route, prompt = '') {
964
977
  return false;
965
978
  if (route.id === 'ImageUXReview')
966
979
  return false;
980
+ if (route.id === 'MadDB')
981
+ return false;
967
982
  if (route.id === 'Research' || route.id === 'AutoResearch')
968
983
  return true;
969
984
  if (route.id === 'Goal')
@@ -996,7 +1011,7 @@ export function simpleGitOnlyRouteId(prompt = '') {
996
1011
  }
997
1012
  export function reflectionRequiredForRoute(route) {
998
1013
  const id = String(route?.id || route?.mode || route?.route || route || '').replace(/^\$/, '');
999
- return /^(team|naruto|shadowclone|shadow-clone|kagebunshin|kage-bunshin|qaloop|qa-loop|ppt|imageuxreview|image-ux-review|research|autoresearch|db|database|madsks|mad-sks|gx)$/i.test(id);
1014
+ return /^(team|naruto|shadowclone|shadow-clone|kagebunshin|kage-bunshin|qaloop|qa-loop|ppt|imageuxreview|image-ux-review|research|autoresearch|db|database|madsks|mad-sks|maddb|mad-db|gx)$/i.test(id);
1000
1015
  }
1001
1016
  export function looksLikeCodeChangingWork(prompt = '') {
1002
1017
  const text = String(prompt || '');
@@ -1038,7 +1053,7 @@ export function routeReasoning(route, prompt = '') {
1038
1053
  const base = ALLOWED_REASONING_EFFORTS.has(route?.reasoningPolicy) ? route.reasoningPolicy : 'medium';
1039
1054
  if (hasFromChatImgSignal(text))
1040
1055
  return reasoning('xhigh', 'from_chat_img_image_work_order_analysis');
1041
- if (/(?:^|\s)sks\s+--mad\b|(?:^|\s)--mad\b|\$MAD-SKS\b|\bmad-sks\b|\bmadsks\b/i.test(text))
1056
+ if (/(?:^|\s)sks\s+--mad\b|(?:^|\s)--mad\b|\$MAD-SKS\b|\$MAD-DB\b|\bmad-sks\b|\bmadsks\b|\bmad-db\b|\bmaddb\b/i.test(text))
1042
1057
  return reasoning('xhigh', 'mad_sks_or_mad_launch_default');
1043
1058
  if (route?.id === 'Team' || route?.id === 'Naruto')
1044
1059
  return teamRouteReasoning(text);