MCPcopy Create free account
hub / github.com/SethGammon/Citadel / main

Function main

scripts/noop-ablate.js:151–274  ·  view source on GitHub ↗
()

Source from the content-addressed store, hash-verified

149// ── Main ──────────────────────────────────────────────────────────────────────
150
151function main() {
152 if (!skillFilter) {
153 console.error('Usage: node scripts/noop-ablate.js --skill <name> [--scenario <filter>] [--dry-run]');
154 process.exit(1);
155 }
156
157 const skillFile = path.join(SKILLS_DIR, skillFilter, 'SKILL.md');
158 if (!fs.existsSync(skillFile)) {
159 console.error(`No SKILL.md for "${skillFilter}".`);
160 process.exit(1);
161 }
162
163 const original = fs.readFileSync(skillFile, 'utf8');
164 const rawCandidates = detectNoOps(original).map(c => ({ ...c, skill: skillFilter }));
165 const verdicts = loadLatestVerdicts();
166 const edits = rawCandidates.map(c => resolveEdit(c, verdicts)).filter(e => e.action !== 'keep');
167
168 let scenarios = discoverScenarios().filter(s => s.skill === skillFilter && !s.skipExecute);
169 if (scenarioFilter) scenarios = scenarios.filter(s => s.name.includes(scenarioFilter));
170
171 if (rawCandidates.length === 0) {
172 console.log(`\nNo Tier 1 candidates in ${skillFilter}. Nothing to ablate.\n`);
173 process.exit(0);
174 }
175 if (edits.length === 0) {
176 console.log(`\nAll candidates in ${skillFilter} were judged "keep". Nothing to ablate.\n`);
177 process.exit(0);
178 }
179 if (scenarios.length === 0) {
180 console.log(`\n${skillFilter} has no runnable benchmark scenarios - cannot ablate empirically.`);
181 console.log('Add a scenario under skills/' + skillFilter + '/__benchmarks__/ to enable Tier 3.\n');
182 process.exit(0);
183 }
184
185 // ── Run-count math (the cost story) ───────────────────────────────────────
186 const S = scenarios.length;
187 const K = edits.length;
188 const bisectWorst = K > 1 ? S * Math.ceil(Math.log2(K)) * 2 : 0;
189 const planCalls = S /*baseline*/ + S /*batch*/ + bisectWorst;
190
191 console.log('\nNo-op Ablation (Tier 3, empirical)\n' + '='.repeat(44));
192 console.log(`Skill: ${skillFilter}`);
193 console.log(`Candidates: ${K} (${edits.map(e => `L${e.lineNo}:${e.action}`).join(', ')})`);
194 console.log(`Scenarios: ${S} (${scenarios.map(s => s.name).join(', ')})`);
195 console.log(`Plan: ${S} baseline + ${S} batched ablation` + (K > 1 ? ` + ≤${bisectWorst} bisect` : '') + ` = ≤${planCalls} model call(s)`);
196 console.log('Method: compare assertion outcome vectors; same vector => behavior unchanged => no-op confirmed.');
197
198 if (DRY_RUN) {
199 console.log('\n[dry-run] No model calls made. Re-run without --dry-run to execute.\n');
200 process.exit(0);
201 }
202
203 const cli = findClaudeCLI();
204 if (!cli) {
205 console.error('\nclaude CLI not found - cannot run ablation. Use --dry-run to see the plan.\n');
206 process.exit(1);
207 }
208

Callers 1

noop-ablate.jsFile · 0.70

Calls 9

detectNoOpsFunction · 0.85
loadLatestVerdictsFunction · 0.85
resolveEditFunction · 0.85
discoverScenariosFunction · 0.85
runAllFunction · 0.85
applyEditsFunction · 0.85
matchesBaselineFunction · 0.85
isolateFunction · 0.85
findClaudeCLIFunction · 0.70

Tested by

no test coverage detected