aiopt 0.3.4 → 0.3.5

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/dist/cli.js CHANGED
@@ -656,7 +656,7 @@ var require_package = __commonJS({
656
656
  "package.json"(exports2, module2) {
657
657
  module2.exports = {
658
658
  name: "aiopt",
659
- version: "0.3.4",
659
+ version: "0.3.5",
660
660
  description: "Pre-deploy LLM cost accident guardrail (serverless local CLI)",
661
661
  bin: {
662
662
  aiopt: "dist/cli.js"
@@ -1817,6 +1817,8 @@ async function startDashboard(cwd, opts) {
1817
1817
  const file = (name) => import_path12.default.join(outDir, name);
1818
1818
  let lastCollect = null;
1819
1819
  let lastCollectError = null;
1820
+ let lastAutoGen = null;
1821
+ let lastAutoGenError = null;
1820
1822
  function ensureUsageFile() {
1821
1823
  try {
1822
1824
  const usagePath = file("usage.jsonl");
@@ -1828,7 +1830,45 @@ async function startDashboard(cwd, opts) {
1828
1830
  lastCollectError = String(e?.message || e || "collect failed");
1829
1831
  }
1830
1832
  }
1833
+ function loadRateTable2() {
1834
+ const p = import_path12.default.join(__dirname, "..", "rates", "rate_table.json");
1835
+ return JSON.parse(import_fs11.default.readFileSync(p, "utf8"));
1836
+ }
1837
+ function readEvents(usagePath) {
1838
+ if (!import_fs11.default.existsSync(usagePath)) return [];
1839
+ return isCsvPath(usagePath) ? readCsv(usagePath) : readJsonl(usagePath);
1840
+ }
1841
+ function ensureScanAndGuard() {
1842
+ const did = [];
1843
+ try {
1844
+ const usagePath = file("usage.jsonl");
1845
+ const rt = loadRateTable2();
1846
+ const needScan = !import_fs11.default.existsSync(file("report.json")) || !import_fs11.default.existsSync(file("report.md"));
1847
+ if (needScan) {
1848
+ const events = readEvents(usagePath);
1849
+ const { analysis, savings, policy, meta } = analyze(rt, events);
1850
+ policy.generated_from.input = usagePath;
1851
+ writeOutputs(outDir, analysis, savings, policy, { ...meta, cwd, cliVersion: "dashboard" });
1852
+ did.push("scan");
1853
+ }
1854
+ const needGuard = !import_fs11.default.existsSync(file("guard-last.txt")) || !import_fs11.default.existsSync(file("guard-last.json"));
1855
+ if (needGuard) {
1856
+ const events = readEvents(usagePath);
1857
+ const r = runGuard(rt, { baselineEvents: events, candidate: {} });
1858
+ const ts = (/* @__PURE__ */ new Date()).toISOString();
1859
+ import_fs11.default.writeFileSync(file("guard-last.txt"), r.message);
1860
+ import_fs11.default.writeFileSync(file("guard-last.json"), JSON.stringify({ ts, exitCode: r.exitCode }, null, 2));
1861
+ import_fs11.default.appendFileSync(file("guard-history.jsonl"), JSON.stringify({ ts, exitCode: r.exitCode, mode: "dashboard", baseline: usagePath, candidate: null }) + "\n");
1862
+ did.push("guard");
1863
+ }
1864
+ if (did.length) lastAutoGen = { ts: (/* @__PURE__ */ new Date()).toISOString(), did };
1865
+ lastAutoGenError = null;
1866
+ } catch (e) {
1867
+ lastAutoGenError = String(e?.message || e || "auto-gen failed");
1868
+ }
1869
+ }
1831
1870
  ensureUsageFile();
1871
+ ensureScanAndGuard();
1832
1872
  function readOrNull(p) {
1833
1873
  try {
1834
1874
  if (!import_fs11.default.existsSync(p)) return null;
@@ -1914,7 +1954,11 @@ async function startDashboard(cwd, opts) {
1914
1954
  <div class="mini" id="baseDir">base: \u2014</div>
1915
1955
  <div class="mini" id="missingHint" style="margin-top:4px">checking files\u2026</div>
1916
1956
  </div>
1917
- <div class="pill"><span class="dot"></span> local-only \xB7 reads <span class="k">./aiopt-output</span> \xB7 <span id="live" class="muted">live: off</span></div>
1957
+ <div class="pill"><span class="dot"></span> local-only \xB7 reads <span class="k">./aiopt-output</span> \xB7 <span id="live" class="muted">live: off</span>
1958
+ <span class="muted">\xB7</span>
1959
+ <button id="btnRefresh" style="all:unset; cursor:pointer; padding:2px 8px; border:1px solid rgba(255,255,255,.16); border-radius:999px; background:rgba(255,255,255,.04); font-size:12px">Refresh</button>
1960
+ <button id="btnLive" style="all:unset; cursor:pointer; padding:2px 8px; border:1px solid rgba(255,255,255,.16); border-radius:999px; background:rgba(255,255,255,.04); font-size:12px">Live: Off</button>
1961
+ </div>
1918
1962
  </div>
1919
1963
 
1920
1964
  <div class="grid">
@@ -2096,7 +2140,13 @@ async function load(){
2096
2140
  const total = reportJson.summary && reportJson.summary.total_cost_usd;
2097
2141
  const sav = reportJson.summary && reportJson.summary.estimated_savings_usd;
2098
2142
  document.getElementById('totalCost').textContent = 'total: ' + money(total);
2099
- document.getElementById('savings').textContent = 'savings: ' + money(sav);
2143
+
2144
+ // UX: if savings is ~0, explicitly say it's normal (not broken).
2145
+ const sNum = Number(sav || 0);
2146
+ const savingsText = (Number.isFinite(sNum) && sNum <= 0.01)
2147
+ ? 'savings: $0 (no obvious waste found)'
2148
+ : ('savings: ' + money(sav));
2149
+ document.getElementById('savings').textContent = savingsText;
2100
2150
  renderBars(document.getElementById('byModel'), reportJson.top && reportJson.top.by_model);
2101
2151
  renderBars(document.getElementById('byFeature'), reportJson.top && reportJson.top.by_feature);
2102
2152
  document.getElementById('scanMeta').textContent = 'confidence=' + (reportJson.confidence || '\u2014') + ' \xB7 generated_at=' + (reportJson.generated_at || '\u2014');
@@ -2179,11 +2229,36 @@ async function load(){
2179
2229
  document.getElementById('scan').textContent = reportMd || '(no report.md yet \u2014 run: aiopt scan)';
2180
2230
  }
2181
2231
 
2182
- // Auto-refresh (simple polling): updates the dashboard as files change.
2232
+ // Default: no auto-refresh (resource-friendly). User can refresh on demand.
2233
+ let liveTimer = null;
2234
+
2235
+ function setLive(on){
2236
+ const btn = document.getElementById('btnLive');
2237
+ const liveEl = document.getElementById('live');
2238
+ if(!btn || !liveEl) return;
2239
+
2240
+ if(on){
2241
+ btn.textContent = 'Live: On';
2242
+ liveEl.textContent = 'live: on';
2243
+ if(liveTimer) clearInterval(liveTimer);
2244
+ liveTimer = setInterval(()=>{ load(); }, 5000);
2245
+ } else {
2246
+ btn.textContent = 'Live: Off';
2247
+ liveEl.textContent = 'live: off';
2248
+ if(liveTimer) clearInterval(liveTimer);
2249
+ liveTimer = null;
2250
+ }
2251
+ }
2252
+
2253
+ document.getElementById('btnRefresh')?.addEventListener('click', ()=>{ load(); });
2254
+ document.getElementById('btnLive')?.addEventListener('click', ()=>{
2255
+ const on = !liveTimer;
2256
+ setLive(on);
2257
+ load();
2258
+ });
2259
+
2260
+ setLive(false);
2183
2261
  load();
2184
- setInterval(()=>{ load(); }, 2000);
2185
- const liveEl = document.getElementById('live');
2186
- if(liveEl) liveEl.textContent = 'live: on (polling)';
2187
2262
  </script>
2188
2263
  </body>
2189
2264
  </html>`;
@@ -2198,10 +2273,11 @@ if(liveEl) liveEl.textContent = 'live: on (polling)';
2198
2273
  const name = url.replace("/api/", "");
2199
2274
  if (name === "_meta") {
2200
2275
  ensureUsageFile();
2276
+ ensureScanAndGuard();
2201
2277
  const expected = ["guard-last.txt", "guard-last.json", "report.json", "report.md", "usage.jsonl", "guard-history.jsonl"];
2202
2278
  const missing = expected.filter((f) => !import_fs11.default.existsSync(file(f)));
2203
2279
  res.writeHead(200, { "content-type": "application/json; charset=utf-8" });
2204
- res.end(JSON.stringify({ baseDir: cwd, outDir, missing, collect: lastCollect, collectError: lastCollectError }, null, 2));
2280
+ res.end(JSON.stringify({ baseDir: cwd, outDir, missing, collect: lastCollect, collectError: lastCollectError, autoGen: lastAutoGen, autoGenError: lastAutoGenError }, null, 2));
2205
2281
  return;
2206
2282
  }
2207
2283
  const allow = /* @__PURE__ */ new Set([
@@ -2215,6 +2291,7 @@ if(liveEl) liveEl.textContent = 'live: on (polling)';
2215
2291
  "live-60m.json"
2216
2292
  ]);
2217
2293
  if (name === "usage.jsonl" || name === "usage-summary.json" || name === "live-60m.json") ensureUsageFile();
2294
+ if (name === "report.json" || name === "report.md" || name === "guard-last.txt" || name === "guard-last.json" || name === "guard-history.jsonl") ensureScanAndGuard();
2218
2295
  if (!allow.has(name)) {
2219
2296
  res.writeHead(404, { "content-type": "text/plain; charset=utf-8" });
2220
2297
  res.end("not found");
@@ -2304,6 +2381,9 @@ var init_dashboard = __esm({
2304
2381
  import_fs11 = __toESM(require("fs"));
2305
2382
  import_path12 = __toESM(require("path"));
2306
2383
  init_collect();
2384
+ init_scan();
2385
+ init_io();
2386
+ init_guard();
2307
2387
  }
2308
2388
  });
2309
2389
 
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/io.ts","../src/cost.ts","../src/solutions.ts","../src/code-scan.ts","../src/sarif.ts","../src/scan.ts","../package.json","../src/install.ts","../src/doctor.ts","../src/license.ts","../src/gate.ts","../src/fix.ts","../src/guard.ts","../src/collect.ts","../src/dashboard.ts","../src/find-output.ts","../src/rates-util.ts","../src/quickstart.ts","../src/cli.ts"],"sourcesContent":["import fs from 'fs';\nimport path from 'path';\nimport { parse as parseCsv } from 'csv-parse/sync';\nimport { UsageEvent } from './types';\n\nexport function ensureDir(p: string) {\n fs.mkdirSync(p, { recursive: true });\n}\n\nexport function readJsonl(filePath: string): UsageEvent[] {\n const raw = fs.readFileSync(filePath, 'utf8');\n const lines = raw.split(/\\r?\\n/).filter(l => l.trim().length > 0);\n const out: UsageEvent[] = [];\n for (const line of lines) {\n const obj = JSON.parse(line);\n out.push(normalizeEvent(obj));\n }\n return out;\n}\n\nexport function readCsv(filePath: string): UsageEvent[] {\n const raw = fs.readFileSync(filePath, 'utf8');\n const records = parseCsv(raw, { columns: true, skip_empty_lines: true, trim: true });\n return records.map((r: any) => normalizeEvent(r));\n}\n\nfunction toNum(x: any, def = 0): number {\n const n = Number(x);\n return Number.isFinite(n) ? n : def;\n}\n\nfunction normalizeEvent(x: any): UsageEvent {\n // Supports two schemas:\n // 1) scan input schema: input_tokens/output_tokens/feature_tag/retries\n // 2) wrapper usage schema: prompt_tokens/completion_tokens/endpoint/attempt/trace_id/cost_usd\n\n const inputTokens = x.input_tokens ?? x.prompt_tokens;\n const outputTokens = x.output_tokens ?? x.completion_tokens;\n\n // feature_tag fallback: feature_tag -> meta.feature_tag -> endpoint\n const featureTag = x.feature_tag ?? x?.meta?.feature_tag ?? x.endpoint ?? '';\n\n // retries fallback: retries -> max(attempt-1,0)\n const retries = x.retries ?? (x.attempt !== undefined ? Math.max(0, toNum(x.attempt) - 1) : 0);\n\n // billed_cost fallback: billed_cost -> cost_usd\n const billed = x.billed_cost ?? x.cost_usd;\n\n return {\n ts: String(x.ts ?? ''),\n provider: String(x.provider ?? '').toLowerCase(),\n model: String(x.model ?? ''),\n input_tokens: toNum(inputTokens),\n output_tokens: toNum(outputTokens),\n feature_tag: String(featureTag ?? ''),\n retries: toNum(retries),\n status: String(x.status ?? ''),\n billed_cost: billed === undefined || billed === '' ? undefined : toNum(billed),\n\n trace_id: x.trace_id ? String(x.trace_id) : undefined,\n request_id: x.request_id ? String(x.request_id) : undefined,\n attempt: x.attempt === undefined ? undefined : toNum(x.attempt),\n endpoint: x.endpoint ? String(x.endpoint) : undefined\n };\n}\n\nexport function isCsvPath(p: string) {\n return path.extname(p).toLowerCase() === '.csv';\n}\n","import { RateTable, UsageEvent } from './types';\n\nexport type CostResult = {\n cost: number;\n used_rate: {\n kind: 'billed_cost' | 'official' | 'estimated';\n provider: string;\n model: string;\n input_per_m: number;\n output_per_m: number;\n };\n};\n\nexport function getRates(rt: RateTable, provider: string, model: string) {\n const prov = String(provider || '').toLowerCase();\n\n // local/offline LLM: treat cost as 0 (or user can add a provider rate later)\n if (prov === 'local' || prov === 'ollama' || prov === 'vllm') {\n return { kind: 'official' as const, input: 0, output: 0 };\n }\n\n const p = rt.providers[prov];\n if (!p) return null;\n const m = p.models[model];\n if (m) return { kind: 'official' as const, input: m.input, output: m.output };\n return { kind: 'estimated' as const, input: p.default_estimated.input, output: p.default_estimated.output };\n}\n\nexport function costOfEvent(rt: RateTable, ev: UsageEvent): CostResult {\n if (typeof ev.billed_cost === 'number' && Number.isFinite(ev.billed_cost)) {\n return {\n cost: ev.billed_cost,\n used_rate: {\n kind: 'billed_cost',\n provider: ev.provider,\n model: ev.model,\n input_per_m: 0,\n output_per_m: 0\n }\n };\n }\n\n const r = getRates(rt, ev.provider, ev.model);\n if (!r) {\n // Unknown provider: deterministic fallback estimate (kept stable for reproducibility)\n const input_per_m = 1.0;\n const output_per_m = 4.0;\n const cost = (ev.input_tokens / 1e6) * input_per_m + (ev.output_tokens / 1e6) * output_per_m;\n return {\n cost,\n used_rate: { kind: 'estimated', provider: String(ev.provider || '').toLowerCase(), model: ev.model, input_per_m, output_per_m }\n };\n }\n\n const cost = (ev.input_tokens / 1e6) * r.input + (ev.output_tokens / 1e6) * r.output;\n return {\n cost,\n used_rate: {\n kind: r.kind,\n provider: ev.provider,\n model: ev.model,\n input_per_m: r.input,\n output_per_m: r.output\n }\n };\n}\n","import fs from 'fs';\nimport path from 'path';\nimport { AnalysisJson, Savings } from './scan';\n\nexport type Fix = {\n id: string;\n title: string;\n impact_usd: number;\n why: string;\n what_to_change: string[];\n status: 'action' | 'no-issue';\n};\n\nconst EPS = 0.0001;\n\nexport function buildTopFixes(analysis: AnalysisJson, savings: Savings): Fix[] {\n const fixes: Fix[] = [];\n\n // Retry tuning\n fixes.push({\n id: 'fix-retry-tuning',\n title: 'Retry tuning',\n impact_usd: Number(savings.retry_waste || 0),\n status: Number(savings.retry_waste || 0) > EPS ? 'action' : 'no-issue',\n why: `Retry waste is estimated at $${round2(Number(savings.retry_waste || 0))}.`,\n what_to_change: [\n 'aiopt/policies/retry.json: lower max_attempts or adjust backoff_ms',\n 'Ensure idempotency keys are stable per trace_id',\n 'Log error_code to identify retryable classes'\n ]\n });\n\n // Output cap (use context_savings as proxy impact)\n fixes.push({\n id: 'fix-output-cap',\n title: 'Output cap',\n impact_usd: Number(savings.context_savings || 0),\n status: Number(savings.context_savings || 0) > EPS ? 'action' : 'no-issue',\n why: `Context savings estimate: $${round2(Number(savings.context_savings || 0))}. Output caps prevent runaway completions.`,\n what_to_change: [\n 'aiopt/policies/output.json: set max_output_tokens_default',\n 'aiopt/policies/output.json: set per_feature caps (summarize/classify/translate)'\n ]\n });\n\n // Routing\n const topFeature = analysis.by_feature_top?.[0]?.key;\n fixes.push({\n id: 'fix-routing',\n title: 'Routing rule',\n impact_usd: Number(savings.routing_savings || 0),\n status: Number(savings.routing_savings || 0) > EPS ? 'action' : 'no-issue',\n why: `Routing savings estimate: $${round2(Number(savings.routing_savings || 0))}.`,\n what_to_change: [\n 'aiopt/policies/routing.json: route summarize/classify/translate to cheap tier',\n `Consider adding feature_tag_in for top feature: ${topFeature || '(unknown)'}`\n ]\n });\n\n // sort by impact desc, deterministic tie-break\n fixes.sort((a, b) => (b.impact_usd - a.impact_usd) || a.id.localeCompare(b.id));\n return fixes;\n}\n\nfunction round2(n: number) {\n return Math.round(n * 100) / 100;\n}\n\nexport function writePatches(outDir: string, fixes: Fix[]) {\n const patchesDir = path.join(outDir, 'patches');\n fs.mkdirSync(patchesDir, { recursive: true });\n\n const readme = [\n '# AIOpt patches (MVP)',\n '',\n 'This folder contains suggested changes you can apply locally.',\n '',\n '## Top fixes',\n ...fixes.map((f, i) => `${i + 1}. ${f.title} — ${f.why}`),\n '',\n 'Files are stubs (human review required).',\n ''\n ].join('\\n');\n\n fs.writeFileSync(path.join(patchesDir, 'README.md'), readme);\n\n // Minimal stub files to satisfy DoD naming.\n fs.writeFileSync(path.join(patchesDir, 'policies.updated.routing.json'), JSON.stringify({ note: 'apply changes to aiopt/policies/routing.json', fixes: fixes.filter(f => f.id.includes('routing')) }, null, 2));\n fs.writeFileSync(path.join(patchesDir, 'policies.updated.retry.json'), JSON.stringify({ note: 'apply changes to aiopt/policies/retry.json', fixes: fixes.filter(f => f.id.includes('retry')) }, null, 2));\n fs.writeFileSync(path.join(patchesDir, 'policies.updated.output.json'), JSON.stringify({ note: 'apply changes to aiopt/policies/output.json', fixes: fixes.filter(f => f.id.includes('output')) }, null, 2));\n}\n","import fs from 'fs';\nimport path from 'path';\nimport { Finding } from './sarif';\n\nconst DEFAULT_EXCLUDES = new Set([\n '.git',\n 'node_modules',\n 'dist',\n 'aiopt-output',\n '.next',\n 'build',\n 'coverage'\n]);\n\nfunction isTextLike(p: string) {\n const ext = path.extname(p).toLowerCase();\n return ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.py', '.go', '.java', '.kt', '.rb', '.php'].includes(ext);\n}\n\nfunction walk(root: string, out: string[]) {\n const items = fs.readdirSync(root, { withFileTypes: true });\n for (const it of items) {\n if (DEFAULT_EXCLUDES.has(it.name)) continue;\n const full = path.join(root, it.name);\n if (it.isDirectory()) walk(full, out);\n else out.push(full);\n }\n}\n\nfunction findAllLines(content: string, re: RegExp): number[] {\n const lines: number[] = [];\n const parts = content.split(/\\r?\\n/);\n for (let i = 0; i < parts.length; i++) {\n const line = parts[i];\n if (re.test(line)) lines.push(i + 1);\n }\n return lines;\n}\n\nexport function runCodeScan(rootDir: string): Finding[] {\n // This is intentionally lightweight + heuristic:\n // We aim to generate PR annotations with file:line, not perfect static analysis.\n const files: string[] = [];\n walk(rootDir, files);\n\n const findings: Finding[] = [];\n\n for (const file of files) {\n if (!isTextLike(file)) continue;\n\n let st: fs.Stats;\n try { st = fs.statSync(file); } catch { continue; }\n if (!st.isFile()) continue;\n if (st.size > 1024 * 1024) continue; // skip huge files\n\n let content = '';\n try { content = fs.readFileSync(file, 'utf8'); } catch { continue; }\n\n // Rule 1: obvious high retry counts (hardcoded)\n // e.g. retry: 10, maxRetries: 8, attempts: 12\n for (const ln of findAllLines(content, /\\b(maxRetries|maximumRetries|retries|max_attempts|attempts)\\s*[:=]\\s*(\\d{2,}|[6-9])\\b/i)) {\n findings.push({\n ruleId: 'AIOPT.RETRY.EXPLOSION_RISK',\n level: 'warning',\n message: 'High retry/attempt count detected. Consider capping retries to prevent cost explosions.',\n file,\n line: ln,\n help: 'Cap retries (e.g. 2-3), add backoff, and fail fast on non-retriable errors.'\n });\n break; // one per file is enough\n }\n\n // Rule 2: hard-coded expensive model strings (heuristic)\n // Encourage cheap default + override routing.\n for (const ln of findAllLines(content, /(gpt-5\\.?2|gpt-4\\.?|o1-|o3-|claude-3|sonnet|opus)/i)) {\n findings.push({\n ruleId: 'AIOPT.MODEL.ROUTING.EXPENSIVE_DEFAULT',\n level: 'note',\n message: 'Possible expensive model hard-coded. Consider cheap default + explicit override for critical paths.',\n file,\n line: ln,\n help: 'Route cheap by default; allow overrides via env/config for high-impact tasks.'\n });\n break;\n }\n\n // Rule 3: missing timeout (very common cost/latency amplifier)\n // If openai client call exists but no timeout nearby.\n const hasOpenAI = /\\bopenai\\b|\\bOpenAI\\b|responses\\.create|chat\\.completions\\.create/i.test(content);\n const hasTimeout = /\\btimeout\\b|\\brequestTimeout\\b|\\bsignal\\b/i.test(content);\n if (hasOpenAI && !hasTimeout) {\n findings.push({\n ruleId: 'AIOPT.TIMEOUT.MISSING',\n level: 'note',\n message: 'OpenAI/LLM call detected without obvious timeout. Add a timeout to reduce hanging retries and cost waste.',\n file,\n line: 1,\n help: 'Add request timeout / AbortSignal and handle retryable errors explicitly.'\n });\n }\n }\n\n // Keep SARIF small/deterministic\n return findings.slice(0, 200);\n}\n","import path from 'path';\n\nexport type Finding = {\n ruleId: string;\n level: 'note' | 'warning' | 'error';\n message: string;\n file: string; // relative or absolute\n line: number; // 1-indexed\n help?: string;\n};\n\nfunction toUri(p: string) {\n // SARIF expects file:// URIs for local paths\n // Use path.resolve to normalize.\n const abs = path.resolve(p);\n // Windows drive handling: file:///C:/...\n const u = abs.replace(/\\\\/g, '/');\n return u.match(/^[A-Za-z]:\\//) ? `file:///${u}` : `file://${u}`;\n}\n\nexport function buildSarif(toolName: string, toolVersion: string, findings: Finding[]) {\n // Minimal SARIF v2.1.0 that GitHub code scanning can ingest.\n // We keep rule metadata tiny; details live in report/patch artifacts.\n const rulesMap = new Map<string, { id: string; shortDescription: string; help?: string }>();\n for (const f of findings) {\n if (!rulesMap.has(f.ruleId)) {\n rulesMap.set(f.ruleId, {\n id: f.ruleId,\n shortDescription: f.ruleId,\n help: f.help\n });\n }\n }\n\n const rules = [...rulesMap.values()].map(r => ({\n id: r.id,\n shortDescription: { text: r.shortDescription },\n help: r.help ? { text: r.help } : undefined\n })).map(x => {\n // drop undefined fields\n const y: any = { ...x };\n if (!y.help) delete y.help;\n return y;\n });\n\n const results = findings.map(f => ({\n ruleId: f.ruleId,\n level: f.level,\n message: { text: f.message },\n locations: [\n {\n physicalLocation: {\n artifactLocation: { uri: toUri(f.file) },\n region: { startLine: Math.max(1, Math.floor(f.line || 1)) }\n }\n }\n ]\n }));\n\n return {\n $schema: 'https://json.schemastore.org/sarif-2.1.0.json',\n version: '2.1.0',\n runs: [\n {\n tool: {\n driver: {\n name: toolName,\n version: toolVersion,\n informationUri: 'https://www.npmjs.com/package/aiopt',\n rules\n }\n },\n results\n }\n ]\n };\n}\n","import fs from 'fs';\nimport path from 'path';\nimport { RateTable, UsageEvent } from './types';\nimport { costOfEvent, getRates } from './cost';\nimport { buildTopFixes, writePatches } from './solutions';\nimport { runCodeScan } from './code-scan';\nimport { buildSarif } from './sarif';\n\nexport type AnalysisJson = {\n total_cost: number;\n by_model_top: Array<{ key: string; cost: number; events: number }>;\n by_feature_top: Array<{ key: string; cost: number; events: number }>;\n unknown_models: Array<{ provider: string; model: string; reason: string }>;\n rate_table_version: string;\n rate_table_date: string;\n};\n\nexport type Savings = {\n estimated_savings_total: number;\n routing_savings: number;\n context_savings: number;\n retry_waste: number;\n notes: [string, string, string];\n};\n\nexport type PolicyJson = {\n version: number;\n default_provider: string;\n rules: Array<any>;\n budgets: { currency: string; notes?: string };\n generated_from: { rate_table_version: string; input: string };\n};\n\nconst ROUTE_TO_CHEAP_FEATURES = new Set(['summarize', 'classify', 'translate']);\n\nfunction topN(map: Map<string, { cost: number; events: number }>, n: number) {\n return [...map.entries()]\n .map(([key, v]) => ({ key, cost: v.cost, events: v.events }))\n .sort((a, b) => b.cost - a.cost)\n .slice(0, n);\n}\n\nexport function analyze(rt: RateTable, events: UsageEvent[]): { analysis: AnalysisJson; savings: Savings; policy: PolicyJson; meta: { mode: 'attempt-log'|'legacy' } } {\n const byModel = new Map<string, { cost: number; events: number }>();\n const byFeature = new Map<string, { cost: number; events: number }>();\n const unknownModels: AnalysisJson['unknown_models'] = [];\n\n const perEventCosts: Array<{ ev: UsageEvent; cost: number }> = [];\n\n // Detect wrapper attempt-log mode: each JSONL line is an attempt (trace_id/attempt present)\n const isAttemptLog = events.some(e => (e.trace_id && String(e.trace_id).length > 0) || (e.attempt !== undefined && Number(e.attempt) > 0));\n\n let baseTotal = 0;\n let total = 0;\n for (const ev of events) {\n const cr = costOfEvent(rt, ev);\n\n baseTotal += cr.cost;\n\n if (isAttemptLog) {\n // Each event line is already one attempt; do NOT multiply by retries.\n total += cr.cost;\n } else {\n // Legacy aggregate mode: one line represents a request with retries count.\n const retries = Math.max(0, Number(ev.retries || 0));\n total += cr.cost * (1 + retries);\n }\n\n perEventCosts.push({ ev, cost: cr.cost });\n\n const mk = `${ev.provider}:${ev.model}`;\n const fk = ev.feature_tag || '(none)';\n\n const mv = byModel.get(mk) || { cost: 0, events: 0 };\n mv.cost += cr.cost; mv.events += 1;\n byModel.set(mk, mv);\n\n const fv = byFeature.get(fk) || { cost: 0, events: 0 };\n fv.cost += cr.cost; fv.events += 1;\n byFeature.set(fk, fv);\n\n const rr = getRates(rt, ev.provider, ev.model);\n if (!rr) {\n unknownModels.push({ provider: ev.provider, model: ev.model, reason: 'unknown provider (estimated)' });\n } else if (rr.kind === 'estimated') {\n unknownModels.push({ provider: ev.provider, model: ev.model, reason: 'unknown model (estimated)' });\n }\n }\n\n // --- Savings simulator (refactor): per-event before/after with caps + no double counting\n type Pot = { routing: number; context: number; retry: number; total: number; waste: number };\n const potByIdx: Pot[] = [];\n\n // Potential routing/context computed per event\n for (const { ev, cost } of perEventCosts) {\n const retries = Math.max(0, Number(ev.retries || 0));\n const attempt = Number(ev.attempt || 1);\n\n const total_i = isAttemptLog ? cost : cost * (1 + retries);\n // Retry waste:\n // - attempt-log mode: attempts >= 2 are retry waste\n // - legacy mode: base_cost * retries\n const waste_i = isAttemptLog ? (attempt >= 2 ? cost : 0) : cost * retries;\n\n let routing_i = 0;\n if (ROUTE_TO_CHEAP_FEATURES.has(String(ev.feature_tag || '').toLowerCase())) {\n const provider = ev.provider;\n const p = rt.providers[provider];\n if (p) {\n const entries = Object.entries(p.models);\n if (entries.length > 0) {\n const cheapest = entries\n .map(([name, r]) => ({ name, score: (r.input + r.output) / 2, r }))\n .sort((a, b) => a.score - b.score)[0];\n const currentRate = getRates(rt, provider, ev.model);\n if (currentRate && currentRate.kind !== 'estimated') {\n const currentCost = (ev.input_tokens / 1e6) * currentRate.input + (ev.output_tokens / 1e6) * currentRate.output;\n const cheapCost = (ev.input_tokens / 1e6) * cheapest.r.input + (ev.output_tokens / 1e6) * cheapest.r.output;\n const diff = (currentCost - cheapCost) * (1 + retries);\n routing_i = Math.max(0, diff);\n }\n }\n }\n }\n\n // context: top 20% rule is applied later by index set\n potByIdx.push({ routing: routing_i, context: 0, retry: waste_i, total: total_i, waste: waste_i });\n }\n\n // context potential assignment (deterministic): top 20% by input_tokens => 25% reduction\n // In attempt-log mode, only apply to attempt==1 to avoid overcounting retries.\n const sortedIdx = [...events.map((e, i) => ({ i, input: Number(e.input_tokens || 0), ok: !isAttemptLog || Number(e.attempt || 1) === 1 }))]\n .filter(x => x.ok)\n .sort((a, b) => b.input - a.input);\n const k = Math.max(1, Math.floor(sortedIdx.length * 0.2));\n const topIdx = new Set(sortedIdx.slice(0, k).map(x => x.i));\n for (let i = 0; i < events.length; i++) {\n if (!topIdx.has(i)) continue;\n const ev = events[i];\n const retries = Math.max(0, Number(ev.retries || 0));\n const r = getRates(rt, ev.provider, ev.model);\n if (!r) continue;\n const saveTokens = (Number(ev.input_tokens || 0)) * 0.25;\n const multiplier = isAttemptLog ? 1 : (1 + retries);\n const diff = (saveTokens / 1e6) * r.input * multiplier;\n potByIdx[i].context = Math.max(0, diff);\n }\n\n // Allocate savings without overlap (routing -> context -> retry), each capped by remaining cost.\n let routingSavings = 0;\n let contextSavings = 0;\n let retryWaste = 0;\n\n for (const p of potByIdx) {\n let remaining = p.total;\n\n const rSave = Math.min(p.routing, remaining);\n remaining -= rSave;\n routingSavings += rSave;\n\n const cSave = Math.min(p.context, remaining);\n remaining -= cSave;\n contextSavings += cSave;\n\n // Retry tuning can only save the waste portion, and cannot exceed remaining.\n const retrySave = Math.min(p.retry, remaining);\n retryWaste += retrySave;\n }\n\n const estimatedSavingsTotal = routingSavings + contextSavings + retryWaste;\n // Global guard\n const guardedSavingsTotal = Math.min(estimatedSavingsTotal, total);\n\n const analysis: AnalysisJson = {\n total_cost: round2(total),\n by_model_top: topN(byModel, 10).map(x => ({ ...x, cost: round2(x.cost) })),\n by_feature_top: topN(byFeature, 10).map(x => ({ ...x, cost: round2(x.cost) })),\n unknown_models: uniqUnknown(unknownModels),\n rate_table_version: rt.version,\n rate_table_date: rt.date\n };\n\n const savings: Savings = {\n estimated_savings_total: round2(guardedSavingsTotal),\n routing_savings: round2(routingSavings),\n context_savings: round2(contextSavings),\n retry_waste: round2(retryWaste),\n notes: [\n `a) 모델 라우팅 절감(추정): $${round2(routingSavings)}`,\n `b) 컨텍스트 감축(추정): $${round2(contextSavings)} (상위 20% input에 25% 감축 가정)` ,\n `c) 재시도/오류 낭비(상한 적용): $${round2(retryWaste)} (retries 기반)`\n ]\n };\n\n const policy: PolicyJson = buildPolicy(rt, events);\n\n return { analysis, savings, policy, meta: { mode: isAttemptLog ? 'attempt-log' : 'legacy' } };\n}\n\nfunction buildPolicy(rt: RateTable, events: UsageEvent[]): PolicyJson {\n // Default provider: most frequent\n const freq = new Map<string, number>();\n for (const ev of events) freq.set(ev.provider, (freq.get(ev.provider) || 0) + 1);\n const defaultProvider = [...freq.entries()].sort((a, b) => b[1] - a[1])[0]?.[0] || 'openai';\n\n // For cheap features: recommend cheapest known model per provider.\n const rules: any[] = [];\n for (const provider of Object.keys(rt.providers)) {\n const p = rt.providers[provider];\n const entries = Object.entries(p.models);\n if (entries.length === 0) continue;\n const cheapest = entries\n .map(([name, r]) => ({ name, score: (r.input + r.output) / 2, r }))\n .sort((a, b) => a.score - b.score)[0];\n\n rules.push({\n match: { provider, feature_tag_in: ['summarize', 'classify', 'translate'] },\n action: { recommend_model: cheapest.name, reason: 'cheap-feature routing' }\n });\n }\n\n // Unknown models: keep (no policy)\n rules.push({ match: { model_unknown: true }, action: { keep: true, reason: 'unknown model -> no policy applied' } });\n\n return {\n version: 1,\n default_provider: defaultProvider,\n rules,\n budgets: { currency: rt.currency, notes: 'MVP: budgets not enforced' },\n generated_from: { rate_table_version: rt.version, input: './aiopt-input/usage.jsonl' }\n };\n}\n\nfunction uniqUnknown(list: AnalysisJson['unknown_models']) {\n const seen = new Set<string>();\n const out: AnalysisJson['unknown_models'] = [];\n for (const x of list) {\n const k = `${x.provider}:${x.model}:${x.reason}`;\n if (seen.has(k)) continue;\n seen.add(k);\n out.push(x);\n }\n return out;\n}\n\nfunction round2(n: number) {\n return Math.round(n * 100) / 100;\n}\n\nexport function writeOutputs(outDir: string, analysis: AnalysisJson, savings: Savings, policy: PolicyJson, meta?: { mode?: 'attempt-log'|'legacy'; cwd?: string; cliVersion?: string }) {\n const mode = meta?.mode || 'legacy';\n\n fs.mkdirSync(outDir, { recursive: true });\n\n fs.writeFileSync(path.join(outDir, 'analysis.json'), JSON.stringify(analysis, null, 2));\n\n // report.json is the “one file to parse” summary for downstream tooling.\n const unknownCount = analysis.unknown_models?.length || 0;\n // confidence: downgrade if many unknowns; keep deterministic\n const confidence = unknownCount === 0 ? 'HIGH' : (unknownCount <= 3 ? 'MED' : 'LOW');\n const ratio = analysis.total_cost > 0 ? (savings.estimated_savings_total / analysis.total_cost) : 0;\n const warnings: string[] = [];\n if (ratio >= 0.9) warnings.push('estimated savings >= 90%');\n if (unknownCount > 0) warnings.push('unknown models/providers detected (estimated pricing used)');\n\n const reportJson = {\n version: 3,\n generated_at: new Date().toISOString(),\n confidence,\n warnings,\n assumptions: {\n no_double_counting: 'routing -> context -> retry allocation per-event with remaining-cost caps',\n retry_cost_model: mode === 'attempt-log'\n ? 'attempt-log mode: total_cost is sum of attempt lines; retry_waste is sum of attempts>=2'\n : 'legacy mode: total_cost includes retries as extra attempts (base_cost*(1+retries))',\n context_model: 'top 20% by input_tokens assume 25% input reduction',\n estimated_pricing_note: unknownCount > 0 ? 'some items use estimated rates; treat savings as a band' : 'all items used known rates'\n },\n summary: {\n total_cost_usd: analysis.total_cost,\n estimated_savings_usd: savings.estimated_savings_total,\n routing_savings_usd: savings.routing_savings,\n context_savings_usd: savings.context_savings,\n retry_waste_usd: savings.retry_waste\n },\n top: {\n by_model: analysis.by_model_top,\n by_feature: analysis.by_feature_top\n },\n unknown_models: analysis.unknown_models,\n notes: savings.notes\n };\n fs.writeFileSync(path.join(outDir, 'report.json'), JSON.stringify(reportJson, null, 2));\n\n // report.md: \"what to change\" guidance + confidence/assumptions (T4 DoD)\n const ratioMd = analysis.total_cost > 0 ? (savings.estimated_savings_total / analysis.total_cost) : 0;\n const warningsMd: string[] = [];\n if (ratioMd >= 0.9) warningsMd.push('WARNING: estimated savings >= 90% — check overlap/missing rate table');\n\n const reportMd = [\n '# AIOpt Report',\n '',\n `- Total cost: $${analysis.total_cost}`,\n `- Estimated savings: $${savings.estimated_savings_total} (guarded <= total_cost)`,\n `- Confidence: ${confidence}`,\n unknownCount > 0 ? `- Unknown models: ${unknownCount} (estimated pricing used)` : '- Unknown models: 0',\n ...warningsMd.map(w => `- ${w}`),\n '',\n '## ASSUMPTIONS',\n '- No double-counting: routing → context → retry savings allocated per-event with remaining-cost caps.',\n mode === 'attempt-log'\n ? '- Retry cost model: attempt-log mode (total_cost=sum attempts, retry_waste=sum attempt>=2).'\n : '- Retry cost model: legacy mode (total_cost=base_cost*(1+retries)).',\n '- Context savings: top 20% input_tokens events assume 25% input reduction.',\n '',\n '## WHAT TO CHANGE',\n '1) Retry tuning → edit `aiopt/policies/retry.json`',\n '2) Output cap → edit `aiopt/policies/output.json`',\n '3) Routing rule → edit `aiopt/policies/routing.json`',\n '',\n '## OUTPUTS',\n '- `aiopt-output/analysis.json`',\n '- `aiopt-output/report.json`',\n '- `aiopt-output/patches/*`',\n ''\n ].join('\\n');\n fs.writeFileSync(path.join(outDir, 'report.md'), reportMd);\n\n const reportTxt = [\n `총비용: $${analysis.total_cost}`,\n `절감 가능 금액(Estimated): $${savings.estimated_savings_total}`,\n `절감 근거 3줄:`,\n savings.notes[0],\n savings.notes[1],\n savings.notes[2],\n ''\n ].join('\\n');\n fs.writeFileSync(path.join(outDir, 'report.txt'), reportTxt);\n\n fs.writeFileSync(path.join(outDir, 'cost-policy.json'), JSON.stringify(policy, null, 2));\n\n // patches/*\n const fixes = buildTopFixes(analysis, savings);\n writePatches(outDir, fixes);\n\n // Optional: SARIF output for PR annotations (best-effort, compatibility-safe).\n // This uses lightweight code scanning heuristics to produce file:line findings.\n try {\n const cwd = meta?.cwd;\n const cliVersion = meta?.cliVersion || 'unknown';\n if (cwd && fs.existsSync(cwd)) {\n const findings = runCodeScan(cwd);\n const sarif = buildSarif('aiopt', cliVersion, findings);\n fs.writeFileSync(path.join(outDir, 'aiopt.sarif'), JSON.stringify(sarif, null, 2));\n }\n } catch {\n // ignore\n }\n}\n","{\n \"name\": \"aiopt\",\n \"version\": \"0.3.4\",\n \"description\": \"Pre-deploy LLM cost accident guardrail (serverless local CLI)\",\n \"bin\": {\n \"aiopt\": \"dist/cli.js\"\n },\n \"type\": \"commonjs\",\n \"main\": \"dist/cli.js\",\n \"files\": [\n \"dist\",\n \"rates\",\n \"samples\",\n \"README.md\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"node --enable-source-maps dist/cli.js\",\n \"prepack\": \"npm run build\",\n \"test:npx\": \"npm pack --silent && node -e \\\"const fs=require('fs');const p=fs.readdirSync('.').find(f=>/^aiopt-.*\\\\.tgz$/.test(f)); if(!p) throw new Error('tgz not found'); console.log('tgz',p);\\\" && npx --yes ./$(ls -1 aiopt-*.tgz | tail -n 1) install --force && npx --yes ./$(ls -1 aiopt-*.tgz | tail -n 1) doctor && npx --yes ./$(ls -1 aiopt-*.tgz | tail -n 1) scan && test -f ./aiopt-output/report.md && echo OK\",\n \"test:guard\": \"npm run build --silent && node scripts/test-guard.js\",\n \"test:license\": \"npm run build --silent && node scripts/test-license.js\",\n \"test:landing\": \"node scripts/test-landing.js\"\n },\n \"dependencies\": {\n \"commander\": \"^14.0.0\",\n \"csv-parse\": \"^6.1.0\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^24.0.0\",\n \"tsup\": \"^8.5.0\",\n \"typescript\": \"^5.9.2\"\n }\n}\n","import fs from 'fs';\nimport path from 'path';\n\nexport type InstallOptions = {\n force?: boolean;\n seedSample?: boolean;\n};\n\nfunction ensureDir(p: string) {\n fs.mkdirSync(p, { recursive: true });\n}\n\nfunction writeFile(filePath: string, content: string, force?: boolean) {\n if (!force && fs.existsSync(filePath)) return { wrote: false, reason: 'exists' as const };\n ensureDir(path.dirname(filePath));\n fs.writeFileSync(filePath, content);\n return { wrote: true as const };\n}\n\nexport function runInstall(cwd: string, opts: InstallOptions) {\n const force = Boolean(opts.force);\n\n const aioptDir = path.join(cwd, 'aiopt');\n const policiesDir = path.join(aioptDir, 'policies');\n const outDir = path.join(cwd, 'aiopt-output');\n\n ensureDir(aioptDir);\n ensureDir(policiesDir);\n ensureDir(outDir);\n\n const created: Array<{ path: string; status: 'created' | 'skipped' }> = [];\n\n // 1) aiopt/README.md\n const readme = `# AIOpt\n\nAIOpt는 **scan툴이 아니라 설치형 비용 가드레일이다.**\n\n## Quick start\n\\`\\`\\`bash\nnpx aiopt install --force\nnpx aiopt doctor\n# (your app runs, wrapper logs usage)\nnpx aiopt scan\n\\`\\`\\`\n\n- 서버/대시보드/계정/업로드/결제/프록시 없음\n- 로컬 파일 기반(정책 + usage.jsonl)\n- LLM 호출 금지(수학/룰 기반)\n\n## Wrapper usage (Node.js)\n\nAIOpt 설치 후, 앱 코드에서 wrapper를 불러서 사용량 JSONL을 자동 기록할 수 있습니다.\n\n\na) 최소 형태(토큰을 직접 넘김)\n\n\\`\\`\\`js\nconst { guardedCall } = require('./aiopt/aiopt-wrapper.js');\n\nawait guardedCall(process.cwd(), {\n provider: 'openai',\n model: 'gpt-5-mini',\n endpoint: 'responses.create',\n feature_tag: 'summarize',\n prompt_tokens: 1200,\n trace_id: 'my-trace'\n}, async (req) => {\n // req: { provider, model, endpoint, max_output_tokens, prompt_tokens, idempotency_key }\n // 여기서 실제 SDK 호출 후 결과를 반환\n return { status: 'ok', completion_tokens: 200 };\n});\n\\`\\`\\`\n\nb) OpenAI-style 응답(usage 자동 추출)\n\n\\`\\`\\`js\nreturn {\n status: 'ok',\n response: {\n usage: { prompt_tokens: 1200, completion_tokens: 200, total_tokens: 1400 }\n }\n};\n\\`\\`\\`\n`;\n\n const r1 = writeFile(path.join(aioptDir, 'README.md'), readme, force);\n created.push({ path: 'aiopt/README.md', status: r1.wrote ? 'created' : 'skipped' });\n\n // 2) aiopt/aiopt.config.json\n const config = {\n version: 1,\n installed_at: new Date().toISOString(),\n output_dir: './aiopt-output',\n usage_path: './aiopt-output/usage.jsonl',\n policies_dir: './aiopt/policies',\n rate_table: { path: './rates/rate_table.json' }\n };\n const r2 = writeFile(path.join(aioptDir, 'aiopt.config.json'), JSON.stringify(config, null, 2) + '\\n', force);\n created.push({ path: 'aiopt/aiopt.config.json', status: r2.wrote ? 'created' : 'skipped' });\n\n // 3) policies\n const routing = {\n version: 1,\n rules: [\n { match: { feature_tag_in: ['summarize', 'classify', 'translate'] }, action: { tier: 'cheap', reason: 'cheap feature routing' } },\n { match: { feature_tag_in: ['coding', 'reasoning'] }, action: { tier: 'default', reason: 'keep for quality' } }\n ]\n };\n const retry = {\n version: 1,\n max_attempts: 2,\n backoff_ms: [200, 500],\n retry_on_status: ['error', 'timeout'],\n notes: 'MVP deterministic retry tuning'\n };\n const output = {\n version: 1,\n max_output_tokens_default: 1024,\n per_feature: {\n summarize: 512,\n classify: 256,\n translate: 512\n }\n };\n const context = {\n version: 1,\n input_token_soft_cap: 12000,\n reduce_top_percentile: 0.2,\n assumed_reduction_ratio: 0.25\n };\n\n const p1 = writeFile(path.join(policiesDir, 'routing.json'), JSON.stringify(routing, null, 2) + '\\n', force);\n const p2 = writeFile(path.join(policiesDir, 'retry.json'), JSON.stringify(retry, null, 2) + '\\n', force);\n const p3 = writeFile(path.join(policiesDir, 'output.json'), JSON.stringify(output, null, 2) + '\\n', force);\n const p4 = writeFile(path.join(policiesDir, 'context.json'), JSON.stringify(context, null, 2) + '\\n', force);\n\n created.push({ path: 'aiopt/policies/routing.json', status: p1.wrote ? 'created' : 'skipped' });\n created.push({ path: 'aiopt/policies/retry.json', status: p2.wrote ? 'created' : 'skipped' });\n created.push({ path: 'aiopt/policies/output.json', status: p3.wrote ? 'created' : 'skipped' });\n created.push({ path: 'aiopt/policies/context.json', status: p4.wrote ? 'created' : 'skipped' });\n\n // 4) wrapper template (T2: real guardrails wrapper)\n const wrapperPath = path.join(aioptDir, 'aiopt-wrapper.js');\n const wrapper = \n`// AIOpt Wrapper (guardrails) — local-only (CommonJS)\n\nconst fs = require('fs');\n\nconst path = require('path');\n\nconst crypto = require('crypto');\n\nfunction readJson(p){ return JSON.parse(fs.readFileSync(p,'utf8')); }\nfunction ensureDir(p){ fs.mkdirSync(p,{recursive:true}); }\nfunction appendJsonl(filePath,obj){ ensureDir(path.dirname(filePath)); fs.appendFileSync(filePath, JSON.stringify(obj)+'\\\\n'); }\nfunction sleep(ms){ return new Promise(r=>setTimeout(r,ms)); }\n\nfunction loadConfig(cwd){ return readJson(path.join(cwd,'aiopt','aiopt.config.json')); }\nfunction loadPolicies(cwd,cfg){ const dir=path.isAbsolute(cfg.policies_dir)?cfg.policies_dir:path.join(cwd,cfg.policies_dir);\n return {\n retry: readJson(path.join(dir,'retry.json')) ,\n output: readJson(path.join(dir,'output.json'))\n };\n}\nfunction loadRates(cwd,cfg){\n const rp=path.isAbsolute(cfg.rate_table.path)?cfg.rate_table.path:path.join(cwd,cfg.rate_table.path);\n try{ return readJson(rp); }catch(e){\n // Fresh projects may not have a rates/ table yet. Fall back to a safe default.\n return { providers: {} };\n }\n}\n\nfunction costUsd(rt, provider, model, promptTokens, completionTokens){\n const p=rt.providers && rt.providers[provider];\n const r=(p && p.models && p.models[model]) || (p && p.default_estimated) || {input:1.0, output:4.0};\n return (promptTokens/1e6)*r.input + (completionTokens/1e6)*r.output;\n}\n\nfunction pickRoutedModel(rt, provider, featureTag, currentModel){\n const cheap=['summarize','classify','translate'];\n if(!cheap.includes(String(featureTag||'').toLowerCase())) return { model: currentModel, routed_from: null, hit: null };\n const p=rt.providers && rt.providers[provider];\n const entries=p && p.models ? Object.entries(p.models) : [];\n if(!entries.length) return { model: currentModel, routed_from: null, hit: null };\n const cheapest=entries.map(([name,r])=>({name,score:(r.input+r.output)/2})).sort((a,b)=>a.score-b.score)[0];\n if(!cheapest || cheapest.name===currentModel) return { model: currentModel, routed_from: null, hit: null };\n return { model: cheapest.name, routed_from: currentModel, hit: 'routing:cheap-feature' };\n}\n\nfunction outputCap(outputPolicy, featureTag, requested){\n const per=(outputPolicy && outputPolicy.per_feature) || {};\n const cap=per[String(featureTag||'').toLowerCase()] ?? (outputPolicy.max_output_tokens_default || 1024);\n const req=requested ?? cap;\n return Math.min(req, cap);\n}\n\nconst IDEMPOTENCY=new Map();\n\nfunction normalizeResult(out, input){\n // Accept either normalized return or provider raw.\n const o = (out && out.response) ? out.response : out;\n const status = (out && out.status) || o.status || (o.error ? 'error' : 'ok');\n const usage = o.usage || (o.data && o.data.usage) || null;\n\n const prompt_tokens = Number(\n (out && out.prompt_tokens) ??\n (o && o.prompt_tokens) ??\n (usage && usage.prompt_tokens) ??\n input.prompt_tokens ??\n 0\n );\n const completion_tokens = Number(\n (out && out.completion_tokens) ??\n (o && o.completion_tokens) ??\n (usage && usage.completion_tokens) ??\n 0\n );\n const total_tokens = Number(\n (out && out.total_tokens) ??\n (o && o.total_tokens) ??\n (usage && usage.total_tokens) ??\n (prompt_tokens + completion_tokens)\n );\n\n const error_code = status === 'ok' ? null : String((out && out.error_code) || (o && o.error_code) || (o && o.error && (o.error.code || o.error.type)) || status);\n const cost_usd = (out && typeof out.cost_usd === 'number') ? out.cost_usd : null;\n\n return { status, prompt_tokens, completion_tokens, total_tokens, error_code, cost_usd };\n}\n\n/**\n * guardedCall(cwd, input, fn)\n *\n * fn(req) can return either:\n * 1) Normalized shape:\n * { status: 'ok'|'error'|'timeout', prompt_tokens?, completion_tokens?, total_tokens?, cost_usd?, error_code? }\n * 2) Provider raw response (OpenAI-style), e.g.:\n * { status:'ok', response:{ usage:{prompt_tokens, completion_tokens, total_tokens} } }\n * { usage:{prompt_tokens, completion_tokens, total_tokens} }\n *\n * If token fields are missing, AIOpt will fall back to input.prompt_tokens and/or 0.\n */\nasync function guardedCall(cwd, input, fn){\n const cfg=loadConfig(cwd);\n const pol=loadPolicies(cwd,cfg);\n const rt=loadRates(cwd,cfg);\n\n const request_id=crypto.randomUUID();\n const trace_id=input.trace_id || request_id;\n const idem=input.idempotency_key || trace_id;\n if(IDEMPOTENCY.has(idem)) return IDEMPOTENCY.get(idem);\n\n const routed=pickRoutedModel(rt, input.provider, input.feature_tag, input.model);\n const maxOut=outputCap(pol.output, input.feature_tag, input.max_output_tokens);\n const usagePath=path.isAbsolute(cfg.usage_path)?cfg.usage_path:path.join(cwd,cfg.usage_path);\n\n const maxAttempts=Math.max(1, Number(pol.retry.max_attempts||1));\n const backoffs=pol.retry.backoff_ms || [200];\n const retryOn=new Set(pol.retry.retry_on_status || ['error','timeout']);\n\n let last={status:'error', completion_tokens:0, error_code:'unknown'};\n\n for(let attempt=1; attempt<=maxAttempts; attempt++){\n const t0=Date.now();\n const policy_hits=[];\n if(routed.hit) policy_hits.push(routed.hit);\n policy_hits.push('outputcap:'+maxOut);\n try{\n const out=await fn({ provider: input.provider, model: routed.model, endpoint: input.endpoint, max_output_tokens: maxOut, prompt_tokens: input.prompt_tokens, idempotency_key: idem });\n const latency_ms=Date.now()-t0;\n const norm=normalizeResult(out, input);\n const cost_usd=(typeof norm.cost_usd==='number') ? norm.cost_usd : costUsd(rt, input.provider, routed.model, norm.prompt_tokens, norm.completion_tokens);\n const feature_tag = input.feature_tag || input.endpoint || 'unknown';\n appendJsonl(usagePath, { ts:new Date().toISOString(), request_id, trace_id, attempt, status: norm.status, error_code: norm.error_code, provider: input.provider, model: routed.model, endpoint: input.endpoint, prompt_tokens: norm.prompt_tokens, completion_tokens: norm.completion_tokens, total_tokens: norm.total_tokens, cost_usd, latency_ms, meta:{ feature_tag, routed_from: routed.routed_from, policy_hits } });\n last={ status: norm.status, completion_tokens: norm.completion_tokens, error_code: norm.error_code };\n if(norm.status==='ok'){ IDEMPOTENCY.set(idem,out); return out; }\n if(retryOn.has(norm.status) && attempt<maxAttempts){ await sleep(Number(backoffs[Math.min(attempt-1, backoffs.length-1)]||200)); continue; }\n IDEMPOTENCY.set(idem,out); return out;\n }catch(e){\n const latency_ms=Date.now()-t0;\n const out={ status:'error', completion_tokens:0, error_code:String(e && (e.code||e.name) || 'exception') };\n const feature_tag = input.feature_tag || input.endpoint || 'unknown';\n appendJsonl(usagePath, { ts:new Date().toISOString(), request_id, trace_id, attempt, status: out.status, error_code: out.error_code, provider: input.provider, model: routed.model, endpoint: input.endpoint, prompt_tokens:Number(input.prompt_tokens||0), completion_tokens:0, total_tokens:Number(input.prompt_tokens||0), cost_usd:costUsd(rt, input.provider, routed.model, Number(input.prompt_tokens||0), 0), latency_ms, meta:{ feature_tag, routed_from: routed.routed_from, policy_hits:[routed.hit||'routing:none','outputcap:'+maxOut,'error:exception'] } });\n last=out;\n if(attempt<maxAttempts){ await sleep(Number(backoffs[Math.min(attempt-1, backoffs.length-1)]||200)); continue; }\n IDEMPOTENCY.set(idem,out); return out;\n }\n }\n IDEMPOTENCY.set(idem,last);\n return last;\n}\n\nmodule.exports = { guardedCall };\n`;\n;\n const w = writeFile(wrapperPath, wrapper, force);\n created.push({ path: 'aiopt/aiopt-wrapper.js', status: w.wrote ? 'created' : 'skipped' });\n\n // 5) usage.jsonl\n const usagePath = path.join(outDir, 'usage.jsonl');\n if (force || !fs.existsSync(usagePath)) {\n // default: empty file (avoid mixing demo data into real user logs)\n fs.writeFileSync(usagePath, '');\n created.push({ path: 'aiopt-output/usage.jsonl', status: 'created' });\n\n if (opts.seedSample) {\n const sample = {\n ts: new Date().toISOString(),\n request_id: 'sample',\n trace_id: 'sample',\n attempt: 1,\n status: 'ok',\n error_code: null,\n provider: 'openai',\n model: 'gpt-5-mini',\n endpoint: 'demo',\n prompt_tokens: 12,\n completion_tokens: 3,\n total_tokens: 15,\n cost_usd: 0.0,\n latency_ms: 1,\n meta: { feature_tag: 'demo', routed_from: null, policy_hits: ['install-sample'] }\n };\n fs.appendFileSync(usagePath, JSON.stringify(sample) + '\\n');\n }\n } else {\n created.push({ path: 'aiopt-output/usage.jsonl', status: 'skipped' });\n }\n\n return { created };\n}\n","import fs from 'fs';\nimport path from 'path';\n\nfunction canWrite(dir: string) {\n try {\n fs.mkdirSync(dir, { recursive: true });\n const p = path.join(dir, `.aiopt-write-test-${Date.now()}`);\n fs.writeFileSync(p, 'ok');\n fs.unlinkSync(p);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction tailLines(filePath: string, n: number): string[] {\n try {\n const raw = fs.readFileSync(filePath, 'utf8');\n const lines = raw.split(/\\r?\\n/).filter(l => l.trim().length > 0);\n return lines.slice(Math.max(0, lines.length - n));\n } catch {\n return [];\n }\n}\n\nexport type DoctorResult = {\n ok: boolean;\n checks: Array<{ name: string; ok: boolean; detail?: string }>;\n last5: Array<{ status?: string; provider?: string; model?: string; endpoint?: string; attempt?: number }>;\n};\n\nexport function runDoctor(cwd: string): DoctorResult {\n const aioptDir = path.join(cwd, 'aiopt');\n const policiesDir = path.join(aioptDir, 'policies');\n const outDir = path.join(cwd, 'aiopt-output');\n const usagePath = path.join(outDir, 'usage.jsonl');\n\n const checks: DoctorResult['checks'] = [];\n\n checks.push({ name: 'aiopt/ exists', ok: fs.existsSync(aioptDir) });\n checks.push({ name: 'aiopt/policies exists', ok: fs.existsSync(policiesDir) });\n checks.push({ name: 'aiopt-output/ writable', ok: canWrite(outDir) });\n checks.push({ name: 'usage.jsonl exists', ok: fs.existsSync(usagePath), detail: usagePath });\n\n const last5raw = tailLines(usagePath, 5);\n const last5 = last5raw.length === 0 ? [{ status: '(empty usage.jsonl)' }] as any : last5raw.map(l => {\n try {\n const j = JSON.parse(l);\n return {\n status: j.status,\n provider: j.provider,\n model: j.model,\n endpoint: j.endpoint,\n attempt: j.attempt,\n feature_tag: j?.meta?.feature_tag\n };\n } catch {\n return {};\n }\n });\n\n // Feature-tag quality check (sample last 50 lines)\n const last50 = tailLines(usagePath, 50);\n let missing = 0;\n let total50 = 0;\n for (const l of last50) {\n total50++;\n try {\n const j = JSON.parse(l);\n const ft = j?.meta?.feature_tag;\n if (!ft || String(ft).trim() === '') missing++;\n } catch {\n missing++;\n }\n }\n if (total50 > 0 && missing > 0) {\n checks.push({ name: 'feature_tag quality (last50)', ok: false, detail: `${missing}/${total50} missing meta.feature_tag` });\n } else {\n checks.push({ name: 'feature_tag quality (last50)', ok: true, detail: 'meta.feature_tag present' });\n }\n\n const ok = checks.every(c => c.ok);\n return { ok, checks, last5 };\n}\n\n","import crypto from 'crypto';\nimport fs from 'fs';\nimport path from 'path';\n\nexport type LicensePayload = {\n sub: string; // customer id/email/etc\n plan: 'pro' | 'team' | 'trial' | string;\n iat: number; // issued at (unix seconds)\n exp: number; // expires at (unix seconds)\n features?: Record<string, boolean>;\n};\n\nexport type LicenseFile = {\n key: string;\n payload: LicensePayload;\n verified: boolean;\n verified_at: string;\n};\n\n// NOTE: Public key only. No servers.\n// Replace this with your own RSA public key in PEM (SPKI) format.\nexport const DEFAULT_PUBLIC_KEY_PEM = `-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz1LLE/pXIx5TloDa0LAf\njg9NSIW6STWhsAFP2ZzXgpWoQ3cCmW6xcB/4QNEmPpGlfMWhyRfkxsdKuhnjUMTg\n8MpMAcbjjF8JrGS9iLnW4yrLm7jzsOcndjkGO7pH+32GopZk98dVzmIRPok2Je76\n3MQRaxLi0jWytaCmacEB4R7HyuquOQlHPg0vD9NOEwrC/+br2GdQbD1lKPyLeLv3\nRidwAs8Iw2xx5g8G+BsVSM/HRC3jQT5GynfnuDsvMHCvGLRct/76ajiR71/NFZEP\nZ7liILNnZzCTlKGGZfZmG70t+zkg8HKdpRuWy8rZ0DPWyQg5MKm6TZOMV6dC0Rpg\nDwIDAQAB\n-----END PUBLIC KEY-----`;\n\nfunction b64urlDecodeToBuffer(s: string): Buffer {\n const padLen = (4 - (s.length % 4)) % 4;\n const padded = s.replace(/-/g, '+').replace(/_/g, '/') + '='.repeat(padLen);\n return Buffer.from(padded, 'base64');\n}\n\nfunction safeJsonParse(buf: Buffer): any {\n const txt = buf.toString('utf8');\n return JSON.parse(txt);\n}\n\nexport function parseLicenseKey(key: string): { payload: LicensePayload; signature: Buffer; payloadB64Url: string } {\n const parts = String(key).trim().split('.');\n if (parts.length !== 2) throw new Error('invalid license key format: expected <payloadB64Url>.<sigB64Url>');\n const [payloadB64Url, sigB64Url] = parts;\n const payloadBuf = b64urlDecodeToBuffer(payloadB64Url);\n const sigBuf = b64urlDecodeToBuffer(sigB64Url);\n const payload = safeJsonParse(payloadBuf) as LicensePayload;\n return { payload, signature: sigBuf, payloadB64Url };\n}\n\nexport function verifyLicenseKey(key: string, publicKeyPem: string): { ok: boolean; reason?: string; payload?: LicensePayload } {\n let parsed: { payload: LicensePayload; signature: Buffer; payloadB64Url: string };\n try {\n parsed = parseLicenseKey(key);\n } catch (e: any) {\n return { ok: false, reason: e?.message || 'parse error' };\n }\n\n const now = Math.floor(Date.now() / 1000);\n if (typeof parsed.payload?.exp !== 'number' || parsed.payload.exp < now) {\n return { ok: false, reason: 'expired', payload: parsed.payload };\n }\n\n try {\n const verifier = crypto.createVerify('RSA-SHA256');\n verifier.update(parsed.payloadB64Url);\n verifier.end();\n const ok = verifier.verify(publicKeyPem, parsed.signature);\n if (!ok) return { ok: false, reason: 'bad signature', payload: parsed.payload };\n return { ok: true, payload: parsed.payload };\n } catch (e: any) {\n return { ok: false, reason: e?.message || 'verify error', payload: parsed.payload };\n }\n}\n\nexport function defaultLicensePath(cwd: string): string {\n return path.join(cwd, 'aiopt', 'license.json');\n}\n\nexport function writeLicenseFile(p: string, key: string, payload: LicensePayload, verified: boolean) {\n const out: LicenseFile = {\n key,\n payload,\n verified,\n verified_at: new Date().toISOString()\n };\n fs.mkdirSync(path.dirname(p), { recursive: true });\n fs.writeFileSync(p, JSON.stringify(out, null, 2));\n}\n\nexport function readLicenseFile(p: string): LicenseFile {\n return JSON.parse(fs.readFileSync(p, 'utf8')) as LicenseFile;\n}\n","import fs from 'fs';\nimport path from 'path';\n\ntype Sarif = {\n runs?: Array<{\n results?: Array<{\n level?: string;\n locations?: Array<{\n physicalLocation?: {\n artifactLocation?: { uri?: string };\n region?: { startLine?: number };\n };\n }>;\n }>;\n }>;\n};\n\nfunction parseFileUri(uri: string): string {\n // SARIF uses file:// URIs. Convert to local path when possible.\n // Keep stable output: prefer relative paths when under cwd.\n try {\n if (!uri) return '';\n const u = uri.replace(/^file:\\/\\//, '');\n // Windows: /C:/path\n const norm = u.replace(/^\\/+/, '').replace(/%20/g, ' ');\n return norm;\n } catch {\n return uri;\n }\n}\n\nexport type GateResult = {\n violations: number;\n top3: Array<{ file: string; line: number }>;\n};\n\nexport function runGate(outDir: string, cwd: string): GateResult {\n const sarifPath = path.join(outDir, 'aiopt.sarif');\n if (!fs.existsSync(sarifPath)) {\n return { violations: 0, top3: [] };\n }\n\n let sarif: Sarif;\n try {\n sarif = JSON.parse(fs.readFileSync(sarifPath, 'utf8'));\n } catch {\n return { violations: 0, top3: [] };\n }\n\n const results = sarif.runs?.[0]?.results || [];\n\n const viol = results.filter(r => {\n const lvl = String(r.level || '').toLowerCase();\n return lvl === 'warning' || lvl === 'error';\n });\n\n const locs: Array<{ file: string; line: number }> = [];\n for (const r of viol) {\n const loc = r.locations?.[0]?.physicalLocation;\n const uri = loc?.artifactLocation?.uri || '';\n const line = Number(loc?.region?.startLine || 1);\n let file = parseFileUri(uri);\n // Best-effort: make relative to cwd for readable PR comments.\n try {\n const abs = path.isAbsolute(file) ? file : path.resolve(file);\n file = path.relative(cwd, abs) || file;\n } catch {\n // ignore\n }\n locs.push({ file, line: Number.isFinite(line) && line > 0 ? line : 1 });\n }\n\n const top3 = locs.slice(0, 3);\n return { violations: viol.length, top3 };\n}\n\nexport function formatGateStdout(r: GateResult, outDir: string): { text: string; exitCode: 0 | 1 } {\n const lines: string[] = [];\n if (r.violations <= 0) {\n lines.push('OK: no policy violations');\n lines.push(`Artifacts: ${path.join(outDir, 'report.md')} | ${path.join(outDir, 'aiopt.sarif')}`);\n return { text: lines.join('\\n'), exitCode: 0 };\n }\n\n lines.push(`FAIL: policy violations=${r.violations}`);\n lines.push('Top3:');\n for (const x of r.top3) lines.push(`- ${x.file}:${x.line}`);\n lines.push('See artifacts: aiopt-output/report.md | aiopt-output/aiopt.sarif | aiopt-output/patches/');\n\n // Keep <= 10 lines guarantee.\n const text = lines.slice(0, 10).join('\\n');\n return { text, exitCode: 1 };\n}\n","import fs from 'fs';\nimport path from 'path';\nimport os from 'os';\nimport { execSync } from 'child_process';\n\nconst DEFAULT_EXCLUDES = new Set([\n '.git',\n 'node_modules',\n 'dist',\n 'aiopt-output',\n '.next',\n 'build',\n 'coverage'\n]);\n\nfunction isTextLike(p: string) {\n const ext = path.extname(p).toLowerCase();\n return ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'].includes(ext);\n}\n\nfunction walk(root: string, out: string[]) {\n const items = fs.readdirSync(root, { withFileTypes: true });\n for (const it of items) {\n // skip hidden dirs/files and common build folders\n if (it.name.startsWith('.')) continue;\n if (DEFAULT_EXCLUDES.has(it.name)) continue;\n const full = path.join(root, it.name);\n if (it.isDirectory()) walk(full, out);\n else out.push(full);\n }\n}\n\nfunction insertModelConst(content: string): { changed: boolean; next: string } {\n if (/\\bAIOPT_MODEL\\b/.test(content)) return { changed: false, next: content };\n if (!/\\bprocess\\.env\\.AIOPT_MODEL\\b/.test(content)) {\n // We'll still allow override by injecting a const that reads env.\n }\n const line = \"const AIOPT_MODEL = process.env.AIOPT_MODEL || 'gpt-5.2-mini';\";\n\n const lines = content.split(/\\r?\\n/);\n let i = 0;\n // Skip shebang\n if (lines[0] && lines[0].startsWith('#!')) i++;\n // Skip import/require headers\n while (i < lines.length) {\n const t = lines[i].trim();\n if (t.startsWith('import ')) { i++; continue; }\n if (t.startsWith('const ') && t.includes(\"require(\")) { i++; continue; }\n if (t === '' || t.startsWith('//') || t.startsWith('/*')) { i++; continue; }\n break;\n }\n lines.splice(i, 0, line, '');\n return { changed: true, next: lines.join('\\n') };\n}\n\nfunction applyRetryCap(content: string): { changed: boolean; next: string } {\n let changed = false;\n let next = content;\n\n // Replace maxRetries: N (N>=4) -> 3\n next = next.replace(/\\b(maxRetries|maximumRetries|max_attempts|attempts)\\s*:\\s*(\\d+)\\b/gi, (m, key, num) => {\n const n = Number(num);\n if (!Number.isFinite(n) || n < 4) return m;\n changed = true;\n return `${key}: 3`;\n });\n\n // Replace retry: { retries: N } etc\n next = next.replace(/\\b(retries)\\s*:\\s*(\\d+)\\b/gi, (m, key, num) => {\n const n = Number(num);\n if (!Number.isFinite(n) || n < 4) return m;\n changed = true;\n return `${key}: 3`;\n });\n\n return { changed, next };\n}\n\nfunction applyModelRouting(content: string): { changed: boolean; next: string } {\n // Only target obvious \"model: AIOPT_MODEL\" patterns.\n let changed = false;\n let next = content;\n\n const re = /(\\bmodel\\s*[:=]\\s*)(['\"])gpt-5\\.2\\2/g;\n if (re.test(next)) {\n // ensure AIOPT_MODEL const exists\n const ins = insertModelConst(next);\n next = ins.next;\n\n next = next.replace(re, (_m, prefix) => {\n changed = true;\n return `${prefix}AIOPT_MODEL`;\n });\n\n // Also handle gpt-5.2-codex style names if present\n const re2 = /(\\bmodel\\s*[:=]\\s*)(['\"])openai-codex\\/gpt-5\\.2\\2/g;\n next = next.replace(re2, (_m, prefix) => {\n changed = true;\n // Keep provider prefix if caller expects it; allow override still.\n return `${prefix}(process.env.AIOPT_MODEL_FULL || 'openai-codex/gpt-5.2-mini')`;\n });\n }\n\n return { changed, next };\n}\n\nfunction tmpFilePath(original: string) {\n const base = path.basename(original);\n const rand = Math.random().toString(16).slice(2);\n return path.join(os.tmpdir(), `aiopt-fix-${base}-${rand}`);\n}\n\nfunction diffNoIndex(oldPath: string, newPath: string): string {\n try {\n // --no-index works even outside git repos.\n return execSync(`git diff --no-index -- ${JSON.stringify(oldPath)} ${JSON.stringify(newPath)}`, {\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'pipe']\n });\n } catch (e: any) {\n // git diff returns exit code 1 when diff exists; stdout is still present.\n const out = String(e?.stdout || '');\n return out;\n }\n}\n\nfunction normalizePatchPaths(diffText: string, rel: string): string {\n // Make patch apply-able inside the repo by rewriting file paths to the repo-relative path.\n // Convert:\n // diff --git a/<anything> b/<anything>\n // --- a/<anything>\n // +++ b/<anything>\n // into:\n // diff --git a/<rel> b/<rel>\n // --- a/<rel>\n // +++ b/<rel>\n // This keeps hunks intact.\n const raw = diffText.split(/\\r?\\n/);\n const lines: string[] = [];\n for (let i = 0; i < raw.length; i++) {\n const line = raw[i];\n // Avoid noisy mode diffs; they cause warnings and are not essential.\n if (line.startsWith('old mode ') || line.startsWith('new mode ')) continue;\n\n if (line.startsWith('diff --git ')) {\n lines.push(`diff --git a/${rel} b/${rel}`);\n continue;\n }\n if (line.startsWith('--- ')) {\n lines.push(`--- a/${rel}`);\n continue;\n }\n if (line.startsWith('+++ ')) {\n lines.push(`+++ b/${rel}`);\n continue;\n }\n lines.push(line);\n }\n return lines.join('\\n');\n}\n\nexport type FixOptions = {\n outDir: string;\n apply: boolean;\n};\n\nexport function runFix(cwd: string, opts: FixOptions) {\n const files: string[] = [];\n walk(cwd, files);\n\n const patches: string[] = [];\n const changedFiles: string[] = [];\n\n for (const file of files) {\n if (!isTextLike(file)) continue;\n\n let st: fs.Stats;\n try { st = fs.statSync(file); } catch { continue; }\n if (!st.isFile()) continue;\n if (st.size > 1024 * 1024) continue;\n\n let content = '';\n try { content = fs.readFileSync(file, 'utf8'); } catch { continue; }\n\n // Apply transforms (two required types):\n // 1) retry cap\n // 2) model routing (cheap default + env override)\n const r1 = applyRetryCap(content);\n const r2 = applyModelRouting(r1.next);\n\n const next = r2.next;\n if (next === content) continue;\n\n const tmp = tmpFilePath(file);\n fs.writeFileSync(tmp, next);\n\n const rel = path.relative(cwd, file).replace(/\\\\/g, '/');\n const d0 = diffNoIndex(file, tmp);\n const d = normalizePatchPaths(d0, rel);\n if (d && d.trim().length > 0) {\n patches.push(d);\n changedFiles.push(rel);\n }\n\n try { fs.unlinkSync(tmp); } catch {}\n\n // Keep patch sizes bounded\n if (patches.join('\\n').length > 500_000) break;\n }\n\n fs.mkdirSync(opts.outDir, { recursive: true });\n const patchPath = path.join(opts.outDir, 'aiopt.patch');\n\n const header = [\n '# AIOpt patch (generated)',\n '# - retry cap: reduce high retry/attempt counts to 3',\n '# - model routing: cheap default via AIOPT_MODEL env override',\n ''\n ].join('\\n');\n\n fs.writeFileSync(patchPath, header + patches.join('\\n'));\n\n if (opts.apply) {\n // Only attempt apply inside a git working tree.\n try {\n const inside = execSync('git rev-parse --is-inside-work-tree', { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim();\n if (inside !== 'true') {\n return { ok: false, applied: false, patchPath, changedFiles, hint: 'not inside a git work tree (run from your repo root, or omit --apply and apply manually)' };\n }\n } catch {\n return { ok: false, applied: false, patchPath, changedFiles, hint: 'git not available or not a git repo (omit --apply and apply manually)' };\n }\n\n try {\n execSync(`git apply ${JSON.stringify(patchPath)}`, { stdio: 'inherit' });\n return { ok: true, applied: true, patchPath, changedFiles };\n } catch {\n return { ok: false, applied: false, patchPath, changedFiles, hint: 'git apply failed. Ensure a clean working tree, then re-run; or open aiopt.patch and apply manually.' };\n }\n }\n\n return { ok: true, applied: false, patchPath, changedFiles };\n}\n","import { RateTable, UsageEvent } from './types';\nimport { analyze } from './scan';\nimport { costOfEvent } from './cost';\n\nexport type GuardInput = {\n // Required. Historical usage for comparison.\n baselineEvents: UsageEvent[];\n\n // Optional. If provided, guard compares two *actual* log sets.\n // When set, candidate transform knobs (model/context/retries multipliers) are ignored.\n candidateEvents?: UsageEvent[];\n\n candidate: {\n provider?: string;\n model?: string;\n contextMultiplier?: number; // multiplies input_tokens\n outputMultiplier?: number; // multiplies output_tokens\n retriesDelta?: number; // adds to retries\n callMultiplier?: number; // multiplies call volume\n budgetMonthlyUsd?: number; // absolute budget gate\n };\n};\n\nexport type GuardResult = {\n exitCode: 0 | 2 | 3;\n message: string;\n};\n\nfunction accidentRiskFromMonthly(monthly: number): 'Low' | 'Medium' | 'High' {\n if (!Number.isFinite(monthly)) return 'Medium';\n if (monthly >= 100) return 'High';\n if (monthly >= 10) return 'Medium';\n return 'Low';\n}\n\nfunction round2(n: number) {\n return Math.round(n * 100) / 100;\n}\n\nfunction windowDays(events: UsageEvent[]): number {\n let days = 1;\n try {\n const times = events\n .map(e => Date.parse(e.ts))\n .filter(t => Number.isFinite(t))\n .sort((a, b) => a - b);\n if (times.length >= 2) {\n const spanMs = Math.max(0, times[times.length - 1] - times[0]);\n const spanDays = spanMs / (1000 * 60 * 60 * 24);\n days = Math.max(1, spanDays);\n }\n } catch {\n days = 1;\n }\n return days;\n}\n\nfunction monthEstimate(delta: number, events: UsageEvent[]) {\n // Convert observed delta (over the sample window) into a monthly estimate.\n const days = windowDays(events);\n return (delta * 30) / days;\n}\n\nfunction applyCandidate(events: UsageEvent[], cand: GuardInput['candidate']): UsageEvent[] {\n const ctxM = cand.contextMultiplier ?? 1;\n const outM = cand.outputMultiplier ?? 1;\n const rDelta = cand.retriesDelta ?? 0;\n\n return events.map(ev => ({\n ...ev,\n provider: cand.provider ? String(cand.provider).toLowerCase() : ev.provider,\n model: cand.model ? String(cand.model) : ev.model,\n input_tokens: Math.max(0, Math.round((ev.input_tokens || 0) * ctxM)),\n output_tokens: Math.max(0, Math.round((ev.output_tokens || 0) * outM)),\n retries: Math.max(0, Math.round((ev.retries || 0) + rDelta)),\n // clear billed_cost so pricing recalculates for new model/provider\n billed_cost: undefined\n }));\n}\n\nfunction confidenceFromChange(cand: GuardInput['candidate']): { level: 'High'|'Medium'|'Low'; reasons: string[] } {\n const reasons: string[] = [];\n\n if (cand.retriesDelta && cand.retriesDelta !== 0) reasons.push('retries change');\n if (cand.model) reasons.push('model change');\n if (cand.provider) reasons.push('provider change');\n if (cand.contextMultiplier && cand.contextMultiplier !== 1) reasons.push('context length change');\n if (cand.outputMultiplier && cand.outputMultiplier !== 1) reasons.push('output length change');\n\n // Spec rule:\n // High: retries/failed/dup calls (we only model retries here)\n // Medium: model/provider change\n // Low: context trimming / prompt structure\n if (cand.retriesDelta && cand.retriesDelta !== 0) return { level: 'High', reasons };\n if (cand.model || cand.provider) return { level: 'Medium', reasons };\n if ((cand.contextMultiplier && cand.contextMultiplier !== 1) || (cand.outputMultiplier && cand.outputMultiplier !== 1)) {\n return { level: 'Low', reasons };\n }\n return { level: 'Medium', reasons: reasons.length ? reasons : ['unknown change'] };\n}\n\nfunction assessDataQuality(baselineEvents: UsageEvent[], base: ReturnType<typeof analyze>) {\n const reasons: string[] = [];\n\n // ts span\n const times = baselineEvents\n .map(e => Date.parse(e.ts))\n .filter(t => Number.isFinite(t))\n .sort((a, b) => a - b);\n if (times.length < 2) reasons.push('ts span unknown');\n else {\n const spanDays = Math.max(0, (times[times.length - 1] - times[0]) / (1000 * 60 * 60 * 24));\n if (spanDays < 0.25) reasons.push('ts span too short');\n }\n\n // feature tag coverage\n const missingFt = baselineEvents.filter(e => !e.feature_tag && !(e.meta && (e.meta as any).feature_tag)).length;\n if (missingFt / Math.max(1, baselineEvents.length) > 0.2) reasons.push('feature_tag missing >20%');\n\n // unknown model/provider\n const unknown = (base.analysis.unknown_models || []).length;\n if (unknown / Math.max(1, baselineEvents.length) > 0.2) reasons.push('unknown model/provider >20%');\n\n // Map to a confidence penalty.\n let penalty: 'none'|'low'|'medium' = 'none';\n if (reasons.length >= 2) penalty = 'medium';\n else if (reasons.length === 1) penalty = 'low';\n\n return { reasons, penalty };\n}\n\nfunction degrade(level: 'High'|'Medium'|'Low', penalty: 'none'|'low'|'medium'): 'High'|'Medium'|'Low' {\n if (penalty === 'none') return level;\n if (penalty === 'low') return level === 'High' ? 'Medium' : 'Low';\n // medium\n return 'Low';\n}\n\nexport function runGuard(rt: RateTable, input: GuardInput): GuardResult {\n if (!input.baselineEvents || input.baselineEvents.length === 0) {\n const conf = { level: 'Low' as const, reasons: ['baseline empty'] };\n const msg = [\n 'FAIL: baseline usage is empty (need aiopt-output/usage.jsonl)',\n 'Impact (monthly est): +$0 (insufficient baseline)',\n `Accident risk: ${accidentRiskFromMonthly(100)}`,\n `Confidence: ${conf.level} (${(conf.reasons.length ? conf.reasons.join(', ') : 'baseline empty')})`,\n 'Recommendation: run the wrapper to collect baseline usage before using guard.'\n ].join('\\n');\n return { exitCode: 3, message: msg };\n }\n\n // For fair comparison, ignore billed_cost/cost_usd and recompute both sides from rate table.\n const baselineEvents = input.baselineEvents.map(e => ({ ...e, billed_cost: undefined }));\n const base = analyze(rt, baselineEvents);\n\n const candidateEvents = (input.candidateEvents && input.candidateEvents.length > 0)\n ? input.candidateEvents.map(e => ({ ...e, billed_cost: undefined }))\n : applyCandidate(baselineEvents, input.candidate);\n\n const cand = analyze(rt, candidateEvents);\n\n const baseCost = base.analysis.total_cost;\n let candCost = cand.analysis.total_cost;\n\n // call volume multiplier (traffic spike)\n const callMult = input.candidate.callMultiplier && input.candidate.callMultiplier > 0 ? input.candidate.callMultiplier : 1;\n if (callMult !== 1) {\n candCost = candCost * callMult;\n }\n\n // attempt-log baseline: retriesDelta should be interpreted as \"extra attempts\".\n const attemptLog = baselineEvents.some(e => (e.trace_id && String(e.trace_id).length > 0) || (e.attempt !== undefined && Number(e.attempt) > 0));\n if (attemptLog && input.candidate.retriesDelta && input.candidate.retriesDelta > 0) {\n // More accurate deterministic approximation:\n // - If baseline already has retry attempts (attempt>=2), use their average cost as retry unit.\n // - Else fall back to avg baseline attempt cost.\n let retryUnit = 0;\n let retryCount = 0;\n for (const ev of baselineEvents) {\n const attempt = Number(ev.attempt || 1);\n if (attempt >= 2) {\n retryUnit += costOfEvent(rt, ev).cost;\n retryCount += 1;\n }\n }\n if (retryCount > 0) {\n retryUnit = retryUnit / retryCount;\n } else {\n retryUnit = baseCost / Math.max(1, baselineEvents.length);\n }\n candCost += retryUnit * input.candidate.retriesDelta;\n }\n\n const delta = candCost - baseCost;\n\n const days = windowDays(baselineEvents);\n const baselineMonthly = (baseCost * 30) / days;\n const candidateMonthly = (candCost * 30) / days;\n\n const changeConf = input.candidateEvents\n ? ({ level: 'High' as const, reasons: ['actual logs diff (--baseline/--candidate)'] })\n : confidenceFromChange(input.candidate);\n\n const dq = assessDataQuality(baselineEvents, base);\n const conf = { level: degrade(changeConf.level, dq.penalty), reasons: [...changeConf.reasons, ...dq.reasons.map(r => `data: ${r}`)] };\n\n // Guard logic:\n // - Warning if delta > 0 and monthEstimate(delta) >= $10\n // - Fail if delta > 0 and monthEstimate(delta) >= $100 (merge-blocking)\n const monthly = monthEstimate(Math.max(0, delta), baselineEvents);\n const monthlyRounded = round2(monthly);\n\n let exitCode: 0 | 2 | 3 = 0;\n let headline = 'OK: no cost accident risk detected';\n\n if (monthly >= 100) { exitCode = 3; headline = 'FAIL: high risk of LLM cost accident'; }\n else if (monthly >= 10) { exitCode = 2; headline = 'WARN: possible LLM cost accident'; }\n\n // Budget gate: absolute monthly cost ceiling for candidate.\n const budget = input.candidate.budgetMonthlyUsd;\n if (budget && Number.isFinite(budget) && budget > 0 && candidateMonthly > budget) {\n exitCode = 3;\n headline = 'FAIL: candidate exceeds monthly budget';\n }\n\n const reasons = conf.reasons.length ? conf.reasons.join(', ') : 'n/a';\n\n function topCauses(): string[] {\n const out: string[] = [];\n\n // transform mode causes\n if (!input.candidateEvents) {\n if (callMult !== 1) out.push('traffic spike (call-mult)');\n if (input.candidate.retriesDelta && input.candidate.retriesDelta !== 0) out.push('retry spike (retries-delta)');\n if (input.candidate.model || input.candidate.provider) out.push('model/provider change');\n if (input.candidate.contextMultiplier && input.candidate.contextMultiplier !== 1) out.push('context length change');\n if (input.candidate.outputMultiplier && input.candidate.outputMultiplier !== 1) out.push('output length change');\n } else {\n // diff mode heuristic causes\n if (candidateEvents.length !== baselineEvents.length) out.push('traffic/call volume changed');\n const bTop = base.analysis.by_model_top?.[0]?.key;\n const cTop = cand.analysis.by_model_top?.[0]?.key;\n if (bTop && cTop && bTop !== cTop) out.push('model mix changed');\n if ((cand.savings?.retry_waste_usd || 0) > (base.savings?.retry_waste_usd || 0)) out.push('retry waste increased');\n }\n\n // budget\n if (budget && Number.isFinite(budget) && budget > 0) out.push(`budget gate: $${round2(budget)}/mo`);\n\n return out.slice(0, 3);\n }\n\n const causes = topCauses();\n\n function sumTokens(events: UsageEvent[]) {\n let input = 0;\n let output = 0;\n for (const e of events) {\n input += Number(e.input_tokens || 0);\n output += Number(e.output_tokens || 0);\n }\n return { input, output, total: input + output };\n }\n\n function topDeltas(kind: 'model' | 'feature') {\n const b = kind === 'model' ? (base.analysis.by_model_top || []) : (base.analysis.by_feature_top || []);\n const c = kind === 'model' ? (cand.analysis.by_model_top || []) : (cand.analysis.by_feature_top || []);\n const bm = new Map<string, { cost: number; events: number }>();\n const cm = new Map<string, { cost: number; events: number }>();\n for (const x of b) bm.set(String(x.key), { cost: Number(x.cost || 0), events: Number(x.events || 0) });\n for (const x of c) cm.set(String(x.key), { cost: Number(x.cost || 0), events: Number(x.events || 0) });\n const keys = new Set<string>([...bm.keys(), ...cm.keys()]);\n const deltas = [...keys].map(k => {\n const bb = bm.get(k) || { cost: 0, events: 0 };\n const cc = cm.get(k) || { cost: 0, events: 0 };\n return { key: k, deltaCost: cc.cost - bb.cost, deltaEvents: cc.events - bb.events };\n });\n return deltas\n .sort((a, b2) => Math.abs(b2.deltaCost) - Math.abs(a.deltaCost))\n .slice(0, 3)\n .filter(x => Math.abs(x.deltaCost) > 1e-9);\n }\n\n const tokB = sumTokens(baselineEvents);\n const tokC = sumTokens(candidateEvents);\n\n const msg = [\n headline,\n `Summary: baseline=$${round2(baseCost)} → candidate=$${round2(candCost)} (Δ=$${round2(delta)})`,\n `Monthly est: baseline=$${round2(baselineMonthly)} → candidate=$${round2(candidateMonthly)}${budget ? ` (budget=$${round2(budget)})` : ''}`,\n input.candidateEvents ? `Tokens: input ${tokB.input}→${tokC.input} (Δ ${tokC.input - tokB.input}), output ${tokB.output}→${tokC.output} (Δ ${tokC.output - tokB.output})` : null,\n callMult !== 1 ? `Call volume multiplier: x${callMult}` : null,\n causes.length ? `Top causes: ${causes.join(' | ')}` : null,\n input.candidateEvents ? (topDeltas('model').length ? `Top model deltas: ${topDeltas('model').map(x => `${x.key} (${round2(x.deltaCost)})`).join(' | ')}` : null) : null,\n input.candidateEvents ? (topDeltas('feature').length ? `Top feature deltas: ${topDeltas('feature').map(x => `${x.key} (${round2(x.deltaCost)})`).join(' | ')}` : null) : null,\n `Impact (monthly est): +$${monthlyRounded}`,\n `Accident risk: ${accidentRiskFromMonthly(monthly)}`,\n `Confidence: ${conf.level} (${reasons})`,\n 'Recommendation: review model/provider/retry/context changes before deploy.'\n ].filter(Boolean).join('\\n');\n\n return { exitCode, message: msg };\n}\n","import fs from 'fs';\nimport path from 'path';\nimport os from 'os';\n\nexport type UsageEventV2 = {\n ts: string;\n provider: string;\n model: string;\n input_tokens: number;\n output_tokens: number;\n retries: number;\n status: string;\n feature_tag?: string;\n // optional\n trace_id?: string;\n request_id?: string;\n attempt?: number;\n endpoint?: string;\n cost_usd?: number;\n meta?: Record<string, any>;\n};\n\nfunction exists(p: string) {\n try { return fs.existsSync(p); } catch { return false; }\n}\n\nfunction safeReadJsonl(p: string): any[] {\n const out: any[] = [];\n try {\n const txt = fs.readFileSync(p, 'utf8');\n for (const line of txt.split(/\\r?\\n/)) {\n if (!line.trim()) continue;\n try { out.push(JSON.parse(line)); } catch {}\n }\n } catch {}\n return out;\n}\n\nfunction listJsonlFiles(dir: string): string[] {\n const out: string[] = [];\n try {\n for (const name of fs.readdirSync(dir)) {\n const full = path.join(dir, name);\n let st: fs.Stats;\n try { st = fs.statSync(full); } catch { continue; }\n if (st.isFile() && name.endsWith('.jsonl')) out.push(full);\n }\n } catch {}\n return out;\n}\n\nfunction findOpenClawSessionLogs(): string[] {\n // OpenClaw stores per-session JSONL logs under ~/.openclaw/agents/*/sessions/*.jsonl\n const home = os.homedir();\n const root = path.join(home, '.openclaw', 'agents');\n if (!exists(root)) return [];\n\n const found: string[] = [];\n let agents: string[] = [];\n try { agents = fs.readdirSync(root); } catch { agents = []; }\n\n for (const a of agents) {\n const sessDir = path.join(root, a, 'sessions');\n if (!exists(sessDir)) continue;\n for (const f of listJsonlFiles(sessDir)) found.push(f);\n }\n return found;\n}\n\nfunction parseOpenClawSessionFile(p: string): UsageEventV2[] {\n const rows = safeReadJsonl(p);\n const events: UsageEventV2[] = [];\n\n for (const r of rows) {\n if (r && r.type === 'message' && r.message && typeof r.message === 'object') {\n const m = r.message;\n const u = m.usage;\n if (!u) continue;\n\n // Expected shape observed:\n // usage: { input, output, cacheRead, cacheWrite, totalTokens, cost: { total, input, output, cacheRead, cacheWrite } }\n const input = Number(u.input ?? u.prompt ?? u.prompt_tokens ?? 0);\n const output = Number(u.output ?? u.completion ?? u.completion_tokens ?? 0);\n const costTotal = u.cost && typeof u.cost === 'object' ? Number(u.cost.total ?? u.costTotal ?? u.cost_usd) : undefined;\n\n // OpenClaw stores timestamps as ms (number-like string). Normalize to ISO for downstream tools.\n let tsRaw: any = m.timestamp || r.timestamp || new Date().toISOString();\n let ts = String(tsRaw);\n if (String(tsRaw).match(/^\\d{10,}$/)) {\n try { ts = new Date(Number(tsRaw)).toISOString(); } catch {}\n }\n const provider = String(m.provider || r.provider || 'openclaw');\n const model = String(m.model || r.modelId || 'unknown');\n\n if (!Number.isFinite(input) && !Number.isFinite(output) && !Number.isFinite(costTotal as any)) continue;\n\n events.push({\n ts,\n provider,\n model,\n input_tokens: Number.isFinite(input) ? input : 0,\n output_tokens: Number.isFinite(output) ? output : 0,\n retries: 0,\n status: 'ok',\n cost_usd: Number.isFinite(costTotal as any) ? Number(costTotal) : undefined,\n meta: {\n source: 'openclaw-session',\n session_file: p,\n cache_read_tokens: u.cacheRead,\n cache_write_tokens: u.cacheWrite,\n total_tokens: u.totalTokens\n }\n });\n }\n }\n\n return events;\n}\n\nfunction stableKey(e: UsageEventV2) {\n // best-effort de-dup key\n return `${e.ts}|${e.provider}|${e.model}|${e.input_tokens}|${e.output_tokens}|${e.cost_usd ?? ''}`;\n}\n\nexport type CollectResult = {\n outPath: string;\n sources: Array<{ name: string; files: number; events: number }>;\n eventsWritten: number;\n};\n\nexport function collectToUsageJsonl(outPath: string): CollectResult {\n const all: UsageEventV2[] = [];\n const sources: CollectResult['sources'] = [];\n\n // OpenClaw\n const ocFiles = findOpenClawSessionLogs();\n let ocEvents = 0;\n for (const f of ocFiles) {\n const evs = parseOpenClawSessionFile(f);\n ocEvents += evs.length;\n all.push(...evs);\n }\n sources.push({ name: 'openclaw', files: ocFiles.length, events: ocEvents });\n\n // Future: cursor, claude-code, etc. (best-effort adapters)\n\n // De-dup + sort by ts\n const seen = new Set<string>();\n const uniq: UsageEventV2[] = [];\n for (const e of all) {\n const k = stableKey(e);\n if (seen.has(k)) continue;\n seen.add(k);\n uniq.push(e);\n }\n uniq.sort((a, b) => Date.parse(a.ts) - Date.parse(b.ts));\n\n fs.mkdirSync(path.dirname(outPath), { recursive: true });\n const lines = uniq.map(e => JSON.stringify(e)).join('\\n') + (uniq.length ? '\\n' : '');\n fs.writeFileSync(outPath, lines);\n\n return { outPath, sources, eventsWritten: uniq.length };\n}\n","import http from 'http';\nimport fs from 'fs';\nimport path from 'path';\nimport { collectToUsageJsonl } from './collect';\n\nexport async function startDashboard(cwd: string, opts: { port: number }) {\n const host = '127.0.0.1';\n const port = opts.port || 3010;\n\n const outDir = path.join(cwd, 'aiopt-output');\n const file = (name: string) => path.join(outDir, name);\n\n // Auto-collect (best-effort): if usage.jsonl is missing, try to derive it from known local sources.\n let lastCollect: null | { ts: string; outPath: string; sources: any; eventsWritten: number } = null;\n let lastCollectError: null | string = null;\n\n function ensureUsageFile() {\n try {\n const usagePath = file('usage.jsonl');\n if (fs.existsSync(usagePath)) return;\n const r = collectToUsageJsonl(usagePath);\n lastCollect = { ts: new Date().toISOString(), outPath: r.outPath, sources: r.sources, eventsWritten: r.eventsWritten };\n lastCollectError = null;\n } catch (e: any) {\n lastCollectError = String(e?.message || e || 'collect failed');\n }\n }\n\n ensureUsageFile();\n\n function readOrNull(p: string) {\n try {\n if (!fs.existsSync(p)) return null;\n return fs.readFileSync(p, 'utf8');\n } catch {\n return null;\n }\n }\n\n function statOrNull(p: string): null | { size: number; mtimeMs: number } {\n try {\n const st = fs.statSync(p);\n return { size: st.size, mtimeMs: st.mtimeMs };\n } catch {\n return null;\n }\n }\n\n const indexHtml = `<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\"/>\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"/>\n <title>AIOpt Local Dashboard</title>\n <style>\n :root{\n --bg:#070b16; --card:#0b1222; --card2:#0e1730; --txt:#e7eaf2; --muted:#a3acc2;\n --border:rgba(255,255,255,.10);\n --ok:#34d399; --warn:#fbbf24; --fail:#fb7185;\n --shadow:0 18px 70px rgba(0,0,0,.35);\n }\n *{box-sizing:border-box}\n body{margin:0; font-family: ui-sans-serif,system-ui,-apple-system,Segoe UI,Roboto; background:var(--bg); color:var(--txt)}\n a{color:#bfffe3; text-decoration:none} a:hover{text-decoration:underline}\n .wrap{max-width:1100px; margin:0 auto; padding:18px}\n .top{display:flex; align-items:center; justify-content:space-between; gap:10px; flex-wrap:wrap}\n .h1{font-size:22px; font-weight:950; letter-spacing:-.02em}\n .pill{display:inline-flex; align-items:center; gap:8px; padding:7px 10px; border-radius:999px; border:1px solid var(--border);\n background:rgba(255,255,255,.03); color:var(--muted); font-size:12px; line-height:1}\n .dot{width:8px;height:8px;border-radius:99px;background:linear-gradient(90deg,#60a5fa,#34d399)}\n\n .grid{display:grid; grid-template-columns:repeat(12,1fr); gap:12px; margin-top:12px}\n .card{grid-column: span 12; background:linear-gradient(180deg, rgba(255,255,255,.03), rgba(255,255,255,0)), var(--card);\n border:1px solid var(--border); border-radius:18px; padding:14px; box-shadow: var(--shadow)}\n @media(min-width: 920px){\n .c6{grid-column: span 6}\n .c4{grid-column: span 4}\n .c8{grid-column: span 8}\n }\n\n .k{padding:2px 6px; border-radius:8px; border:1px solid var(--border); font-family: ui-monospace; font-size:12px; color:#d7def2; background:rgba(255,255,255,.03)}\n .muted{color:var(--muted)}\n .row{display:flex; gap:10px; flex-wrap:wrap; align-items:center}\n\n .badge{display:inline-flex; align-items:center; gap:8px; padding:8px 10px; border-radius:14px; border:1px solid var(--border);\n background:rgba(255,255,255,.03); font-weight:900}\n .badge.ok{border-color:rgba(52,211,153,.35)}\n .badge.warn{border-color:rgba(251,191,36,.35)}\n .badge.fail{border-color:rgba(251,113,133,.35)}\n .badge .b{width:10px;height:10px;border-radius:99px}\n .badge.ok .b{background:var(--ok)}\n .badge.warn .b{background:var(--warn)}\n .badge.fail .b{background:var(--fail)}\n\n pre{margin:0; white-space:pre-wrap; word-break:break-word; background: rgba(3,6,14,.65);\n border:1px solid rgba(255,255,255,.12);\n padding:12px; border-radius:14px;\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\"; font-size:13px; line-height:1.55}\n\n .bars{display:flex; flex-direction:column; gap:8px; margin-top:8px}\n .bar{display:grid; grid-template-columns: 1fr 64px; gap:10px; align-items:center}\n .track{height:10px; border-radius:999px; background:rgba(255,255,255,.08); overflow:hidden; border:1px solid rgba(255,255,255,.10)}\n .fill{height:100%; border-radius:999px; background:linear-gradient(90deg,#60a5fa,#34d399)}\n .label{font-size:13px}\n .val{font-family: ui-monospace; font-size:12px; color:#d7def2; text-align:right}\n\n .mini{font-size:12px; color:var(--muted)}\n </style>\n</head>\n<body>\n <div class=\"wrap\">\n <div class=\"top\">\n <div>\n <div class=\"h1\">AIOpt Local Dashboard</div>\n <div class=\"mini\" id=\"baseDir\">base: —</div>\n <div class=\"mini\" id=\"missingHint\" style=\"margin-top:4px\">checking files…</div>\n </div>\n <div class=\"pill\"><span class=\"dot\"></span> local-only · reads <span class=\"k\">./aiopt-output</span> · <span id=\"live\" class=\"muted\">live: off</span></div>\n </div>\n\n <div class=\"grid\">\n <div class=\"card c6\">\n <div class=\"row\" style=\"justify-content:space-between\">\n <div style=\"font-weight:950\">Guard verdict</div>\n <div class=\"mini\" id=\"guardMeta\">—</div>\n </div>\n <div style=\"height:8px\"></div>\n <div id=\"guardBadge\" class=\"badge\"><span class=\"b\"></span><span id=\"guardBadgeText\">loading…</span></div>\n <div style=\"height:10px\"></div>\n <pre id=\"guard\">loading… (if this stays, it usually means required files are missing — see the top “missing” line)</pre>\n <div style=\"height:10px\"></div>\n <div class=\"row\">\n <a href=\"/api/guard-last.txt\" target=\"_blank\">raw txt</a>\n <span class=\"muted\">·</span>\n <a href=\"/api/guard-last.json\" target=\"_blank\">raw json</a>\n <span class=\"muted\">·</span>\n <a href=\"/api/guard-history.jsonl\" target=\"_blank\">history</a>\n </div>\n\n <div style=\"height:12px\"></div>\n <div style=\"font-weight:900\">Recent guard runs</div>\n <pre id=\"guardHist\" style=\"max-height:220px; overflow:auto\">loading…</pre>\n <div class=\"mini\" style=\"margin-top:8px\">\n Quick actions (copy/paste):\n <div style=\"margin-top:6px; display:flex; flex-wrap:wrap; gap:8px\">\n <span class=\"k\">aiopt quickstart --demo</span>\n <span class=\"k\">aiopt guard --help</span>\n <span class=\"k\">aiopt scan</span>\n </div>\n </div>\n </div>\n\n <div class=\"card c6\">\n <div class=\"row\" style=\"justify-content:space-between\">\n <div style=\"font-weight:950\">Scan summary</div>\n <div class=\"mini\"><a href=\"/api/report.json\" target=\"_blank\">report.json</a> · <a href=\"/api/report.md\" target=\"_blank\">report.md</a></div>\n </div>\n <div style=\"height:8px\"></div>\n <div class=\"row\">\n <div class=\"badge\" id=\"totalCostBadge\"><span class=\"b\" style=\"background:#60a5fa\"></span><span id=\"totalCost\">total: —</span></div>\n <div class=\"badge\" id=\"savingsBadge\"><span class=\"b\" style=\"background:#a78bfa\"></span><span id=\"savings\">savings: —</span></div>\n </div>\n\n <div style=\"height:12px\"></div>\n <div class=\"row\" style=\"justify-content:space-between\">\n <div style=\"font-weight:900\">Live usage (last 60m)</div>\n <div class=\"mini\"><a href=\"/api/usage.jsonl\" target=\"_blank\">usage.jsonl</a></div>\n </div>\n <div id=\"liveSvg\" style=\"margin-top:8px\"></div>\n <pre id=\"liveText\" style=\"margin-top:8px\">loading…</pre>\n\n <div style=\"height:12px\"></div>\n <div class=\"row\" style=\"justify-content:space-between\">\n <div style=\"font-weight:900\">Cost trend (last 7d)</div>\n <div class=\"mini\">(from usage.jsonl)</div>\n </div>\n <div id=\"trendSvg\" style=\"margin-top:8px\"></div>\n <pre id=\"trend\" style=\"margin-top:8px\">loading…</pre>\n\n <div style=\"height:12px\"></div>\n <div style=\"font-weight:900\">Cost by model</div>\n <div id=\"byModel\" class=\"bars\"></div>\n\n <div style=\"height:12px\"></div>\n <div style=\"font-weight:900\">Cost by feature</div>\n <div id=\"byFeature\" class=\"bars\"></div>\n\n <div style=\"height:10px\"></div>\n <div class=\"mini\" id=\"scanMeta\">—</div>\n </div>\n\n <div class=\"card\">\n <div class=\"row\" style=\"justify-content:space-between\">\n <div style=\"font-weight:950\">Latest report.md</div>\n <div class=\"mini\">Tip: run <span class=\"k\">aiopt scan</span> after collecting baseline</div>\n </div>\n <div style=\"height:8px\"></div>\n <pre id=\"scan\">loading…</pre>\n </div>\n </div>\n </div>\n\n<script>\nfunction money(x){\n if (x === null || x === undefined || Number.isNaN(Number(x))) return '—';\n return '$' + (Math.round(Number(x)*100)/100);\n}\nfunction renderBars(el, items){\n el.innerHTML='';\n if(!items || items.length===0){ el.innerHTML='<div class=\"mini\">(no data)</div>'; return; }\n const max = Math.max(...items.map(i=>Number(i.cost)||0), 0.000001);\n for(const it of items.slice(0,8)){\n const w = Math.max(2, Math.round(((Number(it.cost)||0)/max)*100));\n const row = document.createElement('div');\n row.className='bar';\n row.innerHTML =\n '<div>'+\n '<div class=\"label\">'+ String(it.key) +'</div>'+\n '<div class=\"track\"><div class=\"fill\" style=\"width:'+ w +'%\"></div></div>'+\n '</div>'+\n '<div class=\"val\">'+ money(it.cost) +'</div>';\n el.appendChild(row);\n }\n}\n\nlet __live = false;\nlet __tick = 0;\n\nasync function load(){\n __tick++;\n // If fetch hangs / fails, do not leave “loading…” forever.\n const timer = setTimeout(()=>{\n const el = document.getElementById('missingHint');\n if(el && el.textContent && el.textContent.includes('checking')){\n el.textContent = 'still loading… (if this doesn\\'t change, refresh. If it persists: run aiopt quickstart --demo or aiopt scan)';\n }\n }, 1500);\n\n let meta = null;\n try{\n meta = await fetch('/api/_meta', { cache: 'no-store' }).then(r=>r.ok?r.json():null);\n }catch{}\n clearTimeout(timer);\n\n if(meta && meta.baseDir){\n document.getElementById('baseDir').textContent = 'base: ' + meta.baseDir;\n }\n\n const miss = (meta && meta.missing) ? meta.missing : null;\n const hint = document.getElementById('missingHint');\n if(miss && miss.length){\n hint.textContent = 'missing: ' + miss.join(', ') + ' → not broken. Run: aiopt quickstart --demo (or aiopt scan)';\n } else if(miss && miss.length===0){\n hint.textContent = 'missing: (none)';\n } else {\n hint.textContent = 'missing: (unknown — failed to load /api/_meta)';\n }\n\n const guardTxt = await fetch('/api/guard-last.txt', { cache: 'no-store' }).then(r=>r.ok?r.text():null).catch(()=>null);\n const guardMeta = await fetch('/api/guard-last.json', { cache: 'no-store' }).then(r=>r.ok?r.json():null).catch(()=>null);\n\n document.getElementById('guard').textContent = guardTxt || '(no guard-last.txt yet — run: aiopt guard)';\n if(guardMeta){\n document.getElementById('guardMeta').textContent = 'exit=' + guardMeta.exitCode + ' · ' + guardMeta.ts;\n const badge = document.getElementById('guardBadge');\n const t = document.getElementById('guardBadgeText');\n const code = Number(guardMeta.exitCode);\n badge.classList.remove('ok','warn','fail');\n if(code===0){badge.classList.add('ok'); t.textContent='OK (0)';}\n else if(code===2){badge.classList.add('warn'); t.textContent='WARN (2)';}\n else {badge.classList.add('fail'); t.textContent='FAIL (3)';}\n }\n\n const histTxt = await fetch('/api/guard-history.jsonl', { cache: 'no-store' }).then(r=>r.ok?r.text():null).catch(()=>null);\n if(histTxt){\n const lines = histTxt.trim().split('\\n').filter(Boolean).slice(-15).reverse();\n const pretty = [];\n for(const l of lines){\n try{\n const j = JSON.parse(l);\n const code = Number(j.exitCode);\n const badge = (code===0?'OK':(code===2?'WARN':'FAIL'));\n const mode = j.mode || '—';\n const ts = (j.ts || '').replace('T',' ').replace('Z','');\n pretty.push(badge.padEnd(5) + ' ' + mode.padEnd(9) + ' ' + ts);\n }catch{pretty.push(l)}\n }\n document.getElementById('guardHist').textContent = pretty.join('\\n');\n } else {\n document.getElementById('guardHist').textContent = '(no guard-history.jsonl yet — run: aiopt guard)';\n }\n\n const reportJson = await fetch('/api/report.json', { cache: 'no-store' }).then(r=>r.ok?r.json():null).catch(()=>null);\n if(reportJson){\n const total = reportJson.summary && reportJson.summary.total_cost_usd;\n const sav = reportJson.summary && reportJson.summary.estimated_savings_usd;\n document.getElementById('totalCost').textContent = 'total: ' + money(total);\n document.getElementById('savings').textContent = 'savings: ' + money(sav);\n renderBars(document.getElementById('byModel'), reportJson.top && reportJson.top.by_model);\n renderBars(document.getElementById('byFeature'), reportJson.top && reportJson.top.by_feature);\n document.getElementById('scanMeta').textContent = 'confidence=' + (reportJson.confidence || '—') + ' · generated_at=' + (reportJson.generated_at || '—');\n } else {\n document.getElementById('scanMeta').textContent = '(no report.json yet — run: aiopt scan)';\n }\n\n // Use computed JSON endpoints to avoid downloading/parsing huge usage.jsonl in the browser.\n const live60 = await fetch('/api/live-60m.json', { cache: 'no-store' }).then(r=>r.ok?r.json():null).catch(()=>null);\n const sum7d = await fetch('/api/usage-summary.json', { cache: 'no-store' }).then(r=>r.ok?r.json():null).catch(()=>null);\n\n if(live60 && live60.bins){\n const pts = (live60.bins || []).slice().reverse();\n const W=520, H=120, P=12;\n const max = Math.max(...pts.map(b=>Number(b.cost)||0), 0.000001);\n const xs = pts.map((_,i)=> P + (i*(W-2*P))/59);\n const ys = pts.map(b=> H-P - (((Number(b.cost)||0)/max)*(H-2*P)) );\n let d = '';\n for(let i=0;i<xs.length;i++) d += (i===0?'M':'L') + xs[i].toFixed(1)+','+ys[i].toFixed(1)+' ';\n const area = 'M'+xs[0].toFixed(1)+','+(H-P).toFixed(1)+' ' + d + 'L'+xs[xs.length-1].toFixed(1)+','+(H-P).toFixed(1)+' Z';\n const svg =\n '<svg viewBox=\"0 0 '+W+' '+H+'\" width=\"100%\" height=\"'+H+'\" xmlns=\"http://www.w3.org/2000/svg\" style=\"background:rgba(255,255,255,.02); border:1px solid rgba(255,255,255,.10); border-radius:14px\">'+\n '<path d=\"'+area+'\" fill=\"rgba(167,139,250,.10)\" />'+\n '<path d=\"'+d+'\" fill=\"none\" stroke=\"rgba(167,139,250,.95)\" stroke-width=\"2\" />'+\n '<text x=\"'+P+'\" y=\"'+(P+10)+'\" fill=\"rgba(229,231,235,.75)\" font-size=\"11\">max/min '+money(max)+'</text>'+\n '</svg>';\n document.getElementById('liveSvg').innerHTML = svg;\n\n const rows = pts.slice(-10).map((b,idx)=>{\n const mAgo = 9-idx;\n const label = (mAgo===0 ? 'now' : (mAgo+'m'));\n const dollars = ('$' + (Math.round((Number(b.cost)||0)*100)/100).toFixed(2));\n return String(label).padEnd(5) + ' ' + String(dollars).padStart(9) + ' (' + (b.calls||0) + ' calls)';\n });\n document.getElementById('liveText').textContent = rows.join('\\n');\n\n const liveEl = document.getElementById('live');\n if(liveEl){\n liveEl.textContent = 'live: on · last60m ' + money(live60.totalCostUsd || 0);\n }\n } else {\n document.getElementById('liveText').textContent = '(no live data yet)';\n document.getElementById('liveSvg').innerHTML = '';\n }\n\n if(sum7d && sum7d.dayBins){\n const bins = sum7d.dayBins || [];\n const W=520, H=120, P=12;\n const pts = bins.slice().reverse();\n const max = Math.max(...pts.map(b=>Number(b.cost)||0), 0.000001);\n const xs = pts.map((_,i)=> P + (i*(W-2*P))/6);\n const ys = pts.map(b=> H-P - (((Number(b.cost)||0)/max)*(H-2*P)) );\n let d = '';\n for(let i=0;i<xs.length;i++) d += (i===0?'M':'L') + xs[i].toFixed(1)+','+ys[i].toFixed(1)+' ';\n const area = 'M'+xs[0].toFixed(1)+','+(H-P).toFixed(1)+' ' + d + 'L'+xs[xs.length-1].toFixed(1)+','+(H-P).toFixed(1)+' Z';\n const circles = xs.map((x,i)=>'<circle cx=\"'+x.toFixed(1)+'\" cy=\"'+ys[i].toFixed(1)+'\" r=\"2.6\" fill=\"rgba(52,211,153,.9)\"/>').join('');\n const svg =\n '<svg viewBox=\"0 0 '+W+' '+H+'\" width=\"100%\" height=\"'+H+'\" xmlns=\"http://www.w3.org/2000/svg\" style=\"background:rgba(255,255,255,.02); border:1px solid rgba(255,255,255,.10); border-radius:14px\">'+\n '<path d=\"'+area+'\" fill=\"rgba(96,165,250,.12)\" />'+\n '<path d=\"'+d+'\" fill=\"none\" stroke=\"rgba(96,165,250,.95)\" stroke-width=\"2\" />'+\n circles+\n '<text x=\"'+P+'\" y=\"'+(P+10)+'\" fill=\"rgba(229,231,235,.75)\" font-size=\"11\">max '+money(max)+'</text>'+\n '</svg>';\n document.getElementById('trendSvg').innerHTML = svg;\n\n const rows = pts.map((b,idx)=>{\n const label = (idx===pts.length-1 ? 'd-6' : (idx===0 ? 'today' : ('d-'+idx)));\n const dollars = ('$' + (Math.round((Number(b.cost)||0)*100)/100).toFixed(2));\n return String(label).padEnd(7) + ' ' + String(dollars).padStart(9) + ' (' + (b.calls||0) + ' calls)';\n });\n document.getElementById('trend').textContent = rows.join('\\n');\n } else {\n document.getElementById('trend').textContent = '(no 7d data yet)';\n document.getElementById('trendSvg').innerHTML = '';\n }\n\n const reportMd = await fetch('/api/report.md').then(r=>r.ok?r.text():null).catch(()=>null);\n document.getElementById('scan').textContent = reportMd || '(no report.md yet — run: aiopt scan)';\n}\n\n// Auto-refresh (simple polling): updates the dashboard as files change.\nload();\nsetInterval(()=>{ load(); }, 2000);\nconst liveEl = document.getElementById('live');\nif(liveEl) liveEl.textContent = 'live: on (polling)';\n</script>\n</body>\n</html>`;\n\n const server = http.createServer((req, res) => {\n const url = req.url || '/';\n if (url === '/' || url === '/index.html') {\n res.writeHead(200, { 'content-type': 'text/html; charset=utf-8' });\n res.end(indexHtml);\n return;\n }\n\n if (url.startsWith('/api/')) {\n const name = url.replace('/api/', '');\n\n if (name === '_meta') {\n ensureUsageFile();\n const expected = ['guard-last.txt', 'guard-last.json', 'report.json', 'report.md', 'usage.jsonl', 'guard-history.jsonl'];\n const missing = expected.filter(f => !fs.existsSync(file(f)));\n res.writeHead(200, { 'content-type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ baseDir: cwd, outDir, missing, collect: lastCollect, collectError: lastCollectError }, null, 2));\n return;\n }\n\n const allow = new Set([\n 'guard-last.txt', 'guard-last.json', 'guard-history.jsonl',\n 'report.md', 'report.json',\n 'usage.jsonl',\n 'usage-summary.json',\n 'live-60m.json'\n ]);\n // auto-collect hook for anything that depends on usage\n if (name === 'usage.jsonl' || name === 'usage-summary.json' || name === 'live-60m.json') ensureUsageFile();\n if (!allow.has(name)) {\n res.writeHead(404, { 'content-type': 'text/plain; charset=utf-8' });\n res.end('not found');\n return;\n }\n\n // Computed endpoints to keep dashboard fast (avoid downloading/parsing huge usage.jsonl in the browser).\n if (name === 'live-60m.json' || name === 'usage-summary.json') {\n const usagePath = file('usage.jsonl');\n const st = statOrNull(usagePath);\n if (!st) {\n res.writeHead(404, { 'content-type': 'text/plain; charset=utf-8' });\n res.end('missing');\n return;\n }\n\n // cache by mtime\n (globalThis as any).__aioptDashCache = (globalThis as any).__aioptDashCache || {};\n const cache = (globalThis as any).__aioptDashCache;\n\n if (!cache.usage || cache.usage.mtimeMs !== st.mtimeMs) {\n const txt = fs.readFileSync(usagePath, 'utf8');\n const now = Date.now();\n\n const liveBins = Array.from({ length: 60 }, () => ({ cost: 0, calls: 0 }));\n const dayBins = Array.from({ length: 7 }, () => ({ cost: 0, calls: 0 }));\n\n for (const line of txt.split(/\\r?\\n/)) {\n if (!line.trim()) continue;\n try {\n const ev = JSON.parse(line);\n const t = Date.parse(ev.ts);\n if (!Number.isFinite(t)) continue;\n const cost = Number(ev.cost_usd);\n const c = Number.isFinite(cost) ? cost : 0;\n\n const dm = Math.floor((now - t) / 60000);\n if (dm >= 0 && dm < 60) {\n liveBins[dm].calls += 1;\n liveBins[dm].cost += c;\n }\n\n const dd = Math.floor((now - t) / 86400000);\n if (dd >= 0 && dd < 7) {\n dayBins[dd].calls += 1;\n dayBins[dd].cost += c;\n }\n } catch {\n // ignore\n }\n }\n\n cache.usage = {\n mtimeMs: st.mtimeMs,\n live60m: {\n bins: liveBins,\n totalCostUsd: Math.round(liveBins.reduce((a, b) => a + b.cost, 0) * 100) / 100\n },\n summary7d: {\n dayBins\n }\n };\n }\n\n const body = name === 'live-60m.json' ? cache.usage.live60m : cache.usage.summary7d;\n res.writeHead(200, { 'content-type': 'application/json; charset=utf-8', 'cache-control': 'no-store' });\n res.end(JSON.stringify(body, null, 2));\n return;\n }\n\n const p = file(name);\n const txt = readOrNull(p);\n if (txt === null) {\n res.writeHead(404, { 'content-type': 'text/plain; charset=utf-8' });\n res.end('missing');\n return;\n }\n\n const ct = name.endsWith('.json') ? 'application/json; charset=utf-8' : 'text/plain; charset=utf-8';\n res.writeHead(200, { 'content-type': ct, 'cache-control': 'no-store' });\n res.end(txt);\n return;\n }\n\n res.writeHead(404, { 'content-type': 'text/plain; charset=utf-8' });\n res.end('not found');\n });\n\n await new Promise<void>((resolve, reject) => {\n server.once('error', reject);\n server.listen(port, host, () => resolve());\n });\n\n console.log(`OK: dashboard http://${host}:${port}/`);\n console.log('Tip: run `aiopt guard ...` and `aiopt scan` to populate aiopt-output files.');\n\n // keep alive\n await new Promise(() => {});\n}\n","import fs from 'fs';\nimport path from 'path';\n\nexport function findAioptOutputDir(startCwd: string): { cwd: string; outDir: string } {\n let cur = path.resolve(startCwd);\n while (true) {\n const outDir = path.join(cur, 'aiopt-output');\n if (fs.existsSync(outDir)) {\n try {\n if (fs.statSync(outDir).isDirectory()) return { cwd: cur, outDir };\n } catch {}\n }\n const parent = path.dirname(cur);\n if (parent === cur) break;\n cur = parent;\n }\n\n // If not found in parents, try one-level-down scan (common when user runs from a workspace root)\n try {\n const base = path.resolve(startCwd);\n const children = fs.readdirSync(base, { withFileTypes: true })\n .filter(d => d.isDirectory())\n .map(d => path.join(base, d.name));\n for (const child of children) {\n const outDir = path.join(child, 'aiopt-output');\n if (fs.existsSync(outDir)) {\n try {\n if (fs.statSync(outDir).isDirectory()) return { cwd: child, outDir };\n } catch {}\n }\n }\n } catch {\n // ignore\n }\n\n return { cwd: path.resolve(startCwd), outDir: path.join(path.resolve(startCwd), 'aiopt-output') };\n}\n","import fs from 'fs';\nimport path from 'path';\nimport { RateTable } from './types';\n\nexport function loadRateTableFromDistPath(): RateTable {\n // Works both in src/tsup and dist runtime.\n const p = path.join(__dirname, '..', 'rates', 'rate_table.json');\n return JSON.parse(fs.readFileSync(p, 'utf8')) as RateTable;\n}\n","import fs from 'fs';\nimport path from 'path';\nimport { analyze } from './scan';\nimport { loadRateTableFromDistPath } from './rates-util';\nimport { runGuard } from './guard';\n\nexport function seedDemoUsage(outDir: string) {\n fs.mkdirSync(outDir, { recursive: true });\n const p = path.join(outDir, 'usage.jsonl');\n const now = Date.now();\n const lines: any[] = [];\n for (let i = 0; i < 60; i++) {\n lines.push({\n ts: new Date(now - i * 60_000).toISOString(),\n provider: 'openai',\n model: i % 4 === 0 ? 'gpt-5.2' : 'gpt-5-mini',\n endpoint: 'responses',\n attempt: 1,\n trace_id: 'demo-' + i,\n status: 'ok',\n prompt_tokens: 10_000 + (i % 10) * 1000,\n completion_tokens: 1200 + (i % 5) * 200,\n meta: { feature_tag: i % 2 ? 'summarize' : 'coding' }\n });\n }\n fs.writeFileSync(p, lines.map(x => JSON.stringify(x)).join('\\n') + '\\n');\n return p;\n}\n\nexport function runQuickstart(cwd: string, opts: { port: number; budgetMonthlyUsd?: number }) {\n const outDir = path.join(cwd, 'aiopt-output');\n const usagePath = seedDemoUsage(outDir);\n\n const rt = loadRateTableFromDistPath();\n // Use the same normalizer as CLI scan/guard.\n const { readJsonl } = require('./io');\n const events = readJsonl(usagePath);\n const { analysis, savings, policy, meta } = analyze(rt, events);\n\n // write outputs (re-use scan writer by requiring dist is heavy; keep minimal here)\n fs.writeFileSync(path.join(outDir, 'analysis.json'), JSON.stringify(analysis, null, 2));\n fs.writeFileSync(path.join(outDir, 'report.json'), JSON.stringify({\n version: 3,\n generated_at: new Date().toISOString(),\n confidence: analysis.unknown_models?.length ? 'MEDIUM' : 'HIGH',\n warnings: [],\n assumptions: { quickstart: true },\n summary: {\n total_cost_usd: analysis.total_cost,\n estimated_savings_usd: savings.estimated_savings_total,\n routing_savings_usd: savings.routing_savings,\n context_savings_usd: savings.context_savings,\n retry_waste_usd: savings.retry_waste\n },\n top: {\n by_model: analysis.by_model_top,\n by_feature: analysis.by_feature_top\n },\n unknown_models: analysis.unknown_models || [],\n notes: []\n }, null, 2));\n fs.writeFileSync(path.join(outDir, 'cost-policy.json'), JSON.stringify(policy, null, 2));\n fs.writeFileSync(path.join(outDir, 'report.md'), '# AIOpt quickstart demo\\n\\nThis is a demo report generated by `aiopt quickstart --demo`.\\n');\n\n // Run guard on the same log with traffic spike to show WARN\n const r = runGuard(rt, {\n baselineEvents: events,\n candidate: {\n contextMultiplier: 1.2,\n callMultiplier: 5,\n budgetMonthlyUsd: opts.budgetMonthlyUsd\n }\n });\n\n return { usagePath, outDir, guard: r, port: opts.port };\n}\n","#!/usr/bin/env node\n\nimport fs from 'fs';\nimport path from 'path';\nimport { Command } from 'commander';\nimport { ensureDir, isCsvPath, readCsv, readJsonl } from './io';\nimport { RateTable } from './types';\nimport { analyze, writeOutputs } from './scan';\n\nconst program = new Command();\n\nconst DEFAULT_INPUT = './aiopt-output/usage.jsonl';\nconst DEFAULT_OUTPUT_DIR = './aiopt-output';\n\nfunction loadRateTable(): RateTable {\n const p = path.join(__dirname, '..', 'rates', 'rate_table.json');\n return JSON.parse(fs.readFileSync(p, 'utf8'));\n}\n\nprogram\n .name('aiopt')\n .description('AI 비용 자동 절감 인프라 — 서버 없는 로컬 CLI MVP')\n // keep CLI version in sync with package.json\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n .version(require('../package.json').version);\n\nprogram\n .command('init')\n .description('aiopt-input/ 및 샘플 usage.jsonl, aiopt-output/ 생성')\n .action(() => {\n ensureDir('./aiopt-input');\n ensureDir('./aiopt-output');\n\n const sampleSrc = path.join(__dirname, '..', 'samples', 'sample_usage.jsonl');\n const dst = path.join('./aiopt-input', 'usage.jsonl');\n\n if (!fs.existsSync(dst)) {\n fs.copyFileSync(sampleSrc, dst);\n console.log('Created ./aiopt-input/usage.jsonl (sample)');\n } else {\n console.log('Exists ./aiopt-input/usage.jsonl (skip)');\n }\n\n console.log('Ready: ./aiopt-output/');\n });\n\nprogram\n .command('scan')\n .description('입력 로그(JSONL/CSV)를 분석하고 report.md/report.json + patches까지 생성')\n .option('--input <path>', 'input file path (default: ./aiopt-output/usage.jsonl)', DEFAULT_INPUT)\n .option('--out <dir>', 'output dir (default: ./aiopt-output)', DEFAULT_OUTPUT_DIR)\n .action(async (opts) => {\n const inputPath = String(opts.input);\n const outDir = String(opts.out);\n\n if (!fs.existsSync(inputPath)) {\n console.error(`Input not found: ${inputPath}`);\n process.exit(1);\n }\n\n const rt = loadRateTable();\n const events = isCsvPath(inputPath) ? readCsv(inputPath) : readJsonl(inputPath);\n\n const { analysis, savings, policy, meta } = analyze(rt, events);\n // For reproducibility: embed input path & rate table meta\n policy.generated_from.input = inputPath;\n\n // Pass cwd + cli version for optional SARIF generation (code scan)\n writeOutputs(outDir, analysis, savings, policy, { ...meta, cwd: process.cwd(), cliVersion: program.version() });\n\n // Console: Top Fix 3 (data-driven)\n const { buildTopFixes } = await import('./solutions');\n const fixes = buildTopFixes(analysis, savings).slice(0, 3);\n\n console.log('Top Fix 3:');\n fixes.forEach((f, i) => {\n const tag = f.status === 'no-issue' ? '(no issue detected)' : `($${Math.round(f.impact_usd * 100) / 100})`;\n console.log(`${i + 1}) ${f.title} ${tag}`);\n });\n console.log(`Report: ${path.join(outDir, 'report.md')}`);\n });\n\nprogram\n .command('policy')\n .description('마지막 scan 결과 기반으로 cost-policy.json만 재생성 (MVP: scan과 동일 로직)')\n .option('--input <path>', 'input file path (default: ./aiopt-input/usage.jsonl)', DEFAULT_INPUT)\n .option('--out <dir>', 'output dir (default: ./aiopt-output)', DEFAULT_OUTPUT_DIR)\n .action((opts) => {\n const inputPath = String(opts.input);\n const outDir = String(opts.out);\n const rt = loadRateTable();\n const events = isCsvPath(inputPath) ? readCsv(inputPath) : readJsonl(inputPath);\n const { policy } = analyze(rt, events);\n policy.generated_from.input = inputPath;\n\n ensureDir(outDir);\n fs.writeFileSync(path.join(outDir, 'cost-policy.json'), JSON.stringify(policy, null, 2));\n console.log(`OK: ${outDir}/cost-policy.json`);\n });\n\n// v0.2: install/doctor (no servers)\nprogram\n .command('install')\n .description('Install AIOpt guardrails: create aiopt/ + policies + usage.jsonl')\n .option('--force', 'overwrite existing files')\n .option('--seed-sample', 'seed 1 sample line into aiopt-output/usage.jsonl')\n .action(async (opts) => {\n const { runInstall } = await import('./install');\n const result = runInstall(process.cwd(), { force: Boolean(opts.force), seedSample: Boolean(opts.seedSample) });\n for (const c of result.created) {\n console.log(`${c.status === 'created' ? 'CREATED' : 'SKIP'}: ${c.path}`);\n }\n });\n\nprogram\n .command('doctor')\n .description('Check installation + print last 5 usage events')\n .action(async () => {\n const { runDoctor } = await import('./doctor');\n const r = runDoctor(process.cwd());\n console.log(r.ok ? 'OK: doctor' : 'WARN: doctor');\n for (const c of r.checks) {\n console.log(`${c.ok ? 'OK' : 'FAIL'}: ${c.name}${c.detail ? ` (${c.detail})` : ''}`);\n }\n console.log('--- last5 usage');\n for (const x of r.last5) {\n console.log(JSON.stringify(x));\n }\n });\n\n// Offline license (no servers)\nconst licenseCmd = program\n .command('license')\n .description('Offline license activate/verify (public key only; no server calls)');\n\nlicenseCmd\n .command('activate')\n .argument('<KEY>', 'license key (<payloadB64Url>.<sigB64Url>)')\n .option('--out <path>', 'output license.json path (default: ./aiopt/license.json)')\n .action(async (key, opts) => {\n const { DEFAULT_PUBLIC_KEY_PEM, defaultLicensePath, verifyLicenseKey, writeLicenseFile } = await import('./license');\n const outPath = opts.out ? String(opts.out) : defaultLicensePath(process.cwd());\n const pub = process.env.AIOPT_LICENSE_PUBKEY || DEFAULT_PUBLIC_KEY_PEM;\n const v = verifyLicenseKey(String(key), pub);\n if (!v.payload) {\n console.error(`FAIL: ${v.reason || 'invalid license'}`);\n process.exit(3);\n }\n writeLicenseFile(outPath, String(key), v.payload, v.ok);\n console.log(v.ok ? `OK: activated (${outPath})` : `WARN: saved but not verified (${v.reason}) (${outPath})`);\n process.exit(v.ok ? 0 : 2);\n });\n\nlicenseCmd\n .command('verify')\n .option('--path <path>', 'license.json path (default: ./aiopt/license.json)')\n .action(async (opts) => {\n const { DEFAULT_PUBLIC_KEY_PEM, defaultLicensePath, readLicenseFile, verifyLicenseKey } = await import('./license');\n const p = opts.path ? String(opts.path) : defaultLicensePath(process.cwd());\n const pub = process.env.AIOPT_LICENSE_PUBKEY || DEFAULT_PUBLIC_KEY_PEM;\n if (!fs.existsSync(p)) {\n console.error(`FAIL: license file not found: ${p}`);\n process.exit(3);\n }\n const f = readLicenseFile(p);\n const v = verifyLicenseKey(f.key, pub);\n if (v.ok) {\n console.log('OK: license verified');\n process.exit(0);\n }\n console.error(`FAIL: license invalid (${v.reason || 'unknown'})`);\n process.exit(3);\n });\n\nlicenseCmd\n .command('status')\n .option('--path <path>', 'license.json path (default: ./aiopt/license.json)')\n .action(async (opts) => {\n const { DEFAULT_PUBLIC_KEY_PEM, defaultLicensePath, readLicenseFile, verifyLicenseKey } = await import('./license');\n const p = opts.path ? String(opts.path) : defaultLicensePath(process.cwd());\n const pub = process.env.AIOPT_LICENSE_PUBKEY || DEFAULT_PUBLIC_KEY_PEM;\n if (!fs.existsSync(p)) {\n console.log('NO_LICENSE');\n process.exit(2);\n }\n const f = readLicenseFile(p);\n const v = verifyLicenseKey(f.key, pub);\n if (v.ok) {\n console.log(`OK: ${f.payload.plan} exp=${f.payload.exp}`);\n process.exit(0);\n }\n console.log(`INVALID: ${v.reason || 'unknown'}`);\n process.exit(3);\n });\n\n// vNext: guardrail mode (pre-deploy warning)\nprogram\n .command('gate')\n .description('Merge gate (CI-friendly): fail (exit 1) when policy violations are detected; prints <=10 lines')\n .option('--input <path>', 'input usage jsonl/csv (default: ./aiopt-output/usage.jsonl)', DEFAULT_INPUT)\n .option('--out <dir>', 'output dir (default: ./aiopt-output)', DEFAULT_OUTPUT_DIR)\n .action(async (opts) => {\n const inputPath = String(opts.input);\n const outDir = String(opts.out);\n\n // Ensure scan artifacts exist (report + sarif). Keep deterministic, no network.\n if (!fs.existsSync(inputPath)) {\n console.error(`FAIL: input not found: ${inputPath}`);\n process.exit(1);\n }\n\n const rt = loadRateTable();\n const events = isCsvPath(inputPath) ? readCsv(inputPath) : readJsonl(inputPath);\n const { analysis, savings, policy, meta } = analyze(rt, events);\n policy.generated_from.input = inputPath;\n writeOutputs(outDir, analysis, savings, policy, { ...meta, cwd: process.cwd(), cliVersion: program.version() });\n\n const { runGate, formatGateStdout } = await import('./gate');\n const r = runGate(outDir, process.cwd());\n const out = formatGateStdout(r, outDir);\n console.log(out.text);\n process.exit(out.exitCode);\n });\n\nprogram\n .command('fix')\n .description('Auto-fix suggestions: generate aiopt.patch (and optionally apply it via git apply)')\n .option('--out <dir>', 'output dir (default: ./aiopt-output)', DEFAULT_OUTPUT_DIR)\n .option('--apply', 'apply the generated patch via git apply')\n .action(async (opts) => {\n const outDir = String(opts.out);\n const { runFix } = await import('./fix');\n const r = runFix(process.cwd(), { outDir, apply: Boolean(opts.apply) });\n console.log(`Patch: ${r.patchPath}`);\n if (r.changedFiles.length) {\n console.log(`Files: ${r.changedFiles.slice(0, 10).join(', ')}${r.changedFiles.length > 10 ? ' ...' : ''}`);\n } else {\n console.log('No changes suggested.');\n }\n if (r.applied) {\n console.log('OK: patch applied');\n process.exit(0);\n }\n if (!r.ok) {\n console.error(`FAIL: could not apply patch${r.hint ? ` (${r.hint})` : ''}`);\n process.exit(1);\n }\n process.exit(0);\n });\n\nprogram\n .command('guard')\n .description('Pre-deploy guardrail: compare baseline usage vs candidate change (or diff two log sets) and print warnings (exit codes 0/2/3)')\n .option('--input <path>', 'baseline usage jsonl/csv (legacy alias for --baseline; default: ./aiopt-output/usage.jsonl)', DEFAULT_INPUT)\n .option('--baseline <path>', 'baseline usage jsonl/csv (diff mode when used with --candidate)')\n .option('--candidate <path>', 'candidate usage jsonl/csv (diff mode: compare two real log sets)')\n .option('--provider <provider>', 'candidate provider override (transform mode only)')\n .option('--model <model>', 'candidate model override (transform mode only)')\n .option('--context-mult <n>', 'multiply input_tokens by n (transform mode only)', (v) => Number(v))\n .option('--output-mult <n>', 'multiply output_tokens by n (transform mode only)', (v) => Number(v))\n .option('--retries-delta <n>', 'add n to retries (transform mode only)', (v) => Number(v))\n .option('--call-mult <n>', 'multiply call volume by n (traffic spike)', (v) => Number(v))\n .option('--budget-monthly <usd>', 'fail if estimated candidate monthly cost exceeds this budget', (v) => Number(v))\n .action(async (opts) => {\n const rt = loadRateTable();\n\n const baselinePath = String(opts.baseline || opts.input);\n const candidatePath = opts.candidate ? String(opts.candidate) : null;\n\n const diffMode = Boolean(opts.baseline || opts.candidate);\n if (diffMode && (!opts.baseline || !opts.candidate)) {\n console.error('FAIL: diff mode requires both --baseline and --candidate');\n process.exit(3);\n }\n\n if (!fs.existsSync(baselinePath)) {\n console.error(`FAIL: baseline not found: ${baselinePath}`);\n process.exit(3);\n }\n if (candidatePath && !fs.existsSync(candidatePath)) {\n console.error(`FAIL: candidate not found: ${candidatePath}`);\n process.exit(3);\n }\n\n const baselineEvents = isCsvPath(baselinePath) ? readCsv(baselinePath) : readJsonl(baselinePath);\n const candidateEvents = candidatePath\n ? (isCsvPath(candidatePath) ? readCsv(candidatePath) : readJsonl(candidatePath))\n : undefined;\n\n const { runGuard } = await import('./guard');\n const r = runGuard(rt, {\n baselineEvents,\n candidateEvents,\n candidate: {\n provider: opts.provider,\n model: opts.model,\n contextMultiplier: opts.contextMult,\n outputMultiplier: opts.outputMult,\n retriesDelta: opts.retriesDelta,\n callMultiplier: opts.callMult,\n budgetMonthlyUsd: opts.budgetMonthly\n }\n });\n\n console.log(r.message);\n\n // Persist last guard output + history for local dashboard / CI attachments\n try {\n const outDir = path.resolve(DEFAULT_OUTPUT_DIR);\n fs.mkdirSync(outDir, { recursive: true });\n const ts = new Date().toISOString();\n fs.writeFileSync(path.join(outDir, 'guard-last.txt'), r.message);\n fs.writeFileSync(path.join(outDir, 'guard-last.json'), JSON.stringify({ ts, exitCode: r.exitCode }, null, 2));\n const histLine = JSON.stringify({ ts, exitCode: r.exitCode, mode: candidateEvents ? 'diff' : 'transform', baseline: baselinePath, candidate: candidatePath }) + '\\n';\n fs.appendFileSync(path.join(outDir, 'guard-history.jsonl'), histLine);\n } catch {\n // ignore\n }\n\n process.exit(r.exitCode);\n });\n\n// Local-only dashboard (no auth; binds to 127.0.0.1)\nprogram\n .command('dashboard')\n .description('Local dashboard (localhost only): view last guard + last scan outputs')\n .option('--port <n>', 'port (default: 3010)', (v) => Number(v), 3010)\n .option('--dir <path>', 'base directory containing ./aiopt-output (default: cwd)')\n .option('--auto', 'auto-detect by searching parents (and one-level children) for aiopt-output')\n .action(async (opts) => {\n const { startDashboard } = await import('./dashboard');\n const base = opts.dir ? String(opts.dir) : process.cwd();\n if (opts.auto) {\n const { findAioptOutputDir } = await import('./find-output');\n const found = findAioptOutputDir(base);\n await startDashboard(found.cwd, { port: Number(opts.port || 3010) });\n return;\n }\n await startDashboard(base, { port: Number(opts.port || 3010) });\n });\n\nprogram\n .command('quickstart')\n .description('1-minute demo: generate sample usage, run scan+guard, and print dashboard URL')\n .option('--demo', 'run demo workflow (writes to ./aiopt-output)')\n .option('--port <n>', 'dashboard port (default: 3010)', (v) => Number(v), 3010)\n .option('--budget-monthly <usd>', 'optional budget gate for the demo guard', (v) => Number(v))\n .option('--serve', 'start the local dashboard after generating demo outputs')\n .option('--open', 'best-effort open browser to the dashboard URL')\n .action(async (opts) => {\n if (!opts.demo) {\n console.error('FAIL: quickstart requires --demo');\n process.exit(3);\n }\n const port = Number(opts.port || 3010);\n const { runQuickstart } = await import('./quickstart');\n const r = runQuickstart(process.cwd(), { port, budgetMonthlyUsd: opts.budgetMonthly });\n console.log('OK: demo usage written:', r.usagePath);\n console.log('--- guard ---');\n console.log(r.guard.message);\n\n // persist guard-last + append guard history for dashboard\n try {\n const fs = await import('fs');\n const path = await import('path');\n fs.mkdirSync(r.outDir, { recursive: true });\n const ts = new Date().toISOString();\n fs.writeFileSync(path.join(r.outDir, 'guard-last.txt'), r.guard.message);\n fs.writeFileSync(path.join(r.outDir, 'guard-last.json'), JSON.stringify({ ts, exitCode: r.guard.exitCode }, null, 2));\n const histLine = JSON.stringify({ ts, exitCode: r.guard.exitCode, mode: 'quickstart', baseline: r.usagePath, candidate: null }) + '\\n';\n fs.appendFileSync(path.join(r.outDir, 'guard-history.jsonl'), histLine);\n } catch {}\n\n console.log('--- next ---');\n console.log(`Open: http://127.0.0.1:${port}/`);\n\n if (opts.serve) {\n const { startDashboard } = await import('./dashboard');\n if (opts.open) {\n try {\n const { execSync } = await import('child_process');\n const url = `http://127.0.0.1:${port}/`;\n if (process.platform === 'darwin') execSync(`open \"${url}\"`);\n else if (process.platform === 'win32') execSync(`cmd.exe /c start \"\" \"${url}\"`);\n else execSync(`xdg-open \"${url}\"`);\n } catch {}\n }\n console.log('Serving dashboard. Press CTRL+C to stop.');\n await startDashboard(process.cwd(), { port });\n return;\n }\n\n console.log(`Run: npx aiopt dashboard --port ${port}`);\n process.exit(r.guard.exitCode);\n });\n\nprogram.parse(process.argv);\n"],"mappings":"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","names":["fs","parseCsv","path","cost","path","fs","import_fs","import_path","path","fs","import_fs","import_path","path","import_path","round2","fs","path","import_fs","import_path","exports","module","ensureDir","fs","path","import_fs","import_path","fs","path","import_fs","import_path","crypto","path","fs","import_fs","import_path","path","fs","import_fs","import_path","isTextLike","path","walk","fs","DEFAULT_EXCLUDES","os","import_fs","import_path","round2","conf","msg","input","fs","path","os","import_fs","import_path","import_os","path","fs","http","txt","import_fs","import_path","path","fs","import_fs","import_path","path","fs","import_fs","import_path","fs","path","readJsonl","import_fs","import_path","import_fs","import_path","path","fs","buildTopFixes","runInstall","runDoctor","DEFAULT_PUBLIC_KEY_PEM","defaultLicensePath","verifyLicenseKey","writeLicenseFile","readLicenseFile","runGate","formatGateStdout","runFix","runGuard","startDashboard","findAioptOutputDir","runQuickstart","execSync"]}
1
+ {"version":3,"sources":["../src/io.ts","../src/cost.ts","../src/solutions.ts","../src/code-scan.ts","../src/sarif.ts","../src/scan.ts","../package.json","../src/install.ts","../src/doctor.ts","../src/license.ts","../src/gate.ts","../src/fix.ts","../src/guard.ts","../src/collect.ts","../src/dashboard.ts","../src/find-output.ts","../src/rates-util.ts","../src/quickstart.ts","../src/cli.ts"],"sourcesContent":["import fs from 'fs';\nimport path from 'path';\nimport { parse as parseCsv } from 'csv-parse/sync';\nimport { UsageEvent } from './types';\n\nexport function ensureDir(p: string) {\n fs.mkdirSync(p, { recursive: true });\n}\n\nexport function readJsonl(filePath: string): UsageEvent[] {\n const raw = fs.readFileSync(filePath, 'utf8');\n const lines = raw.split(/\\r?\\n/).filter(l => l.trim().length > 0);\n const out: UsageEvent[] = [];\n for (const line of lines) {\n const obj = JSON.parse(line);\n out.push(normalizeEvent(obj));\n }\n return out;\n}\n\nexport function readCsv(filePath: string): UsageEvent[] {\n const raw = fs.readFileSync(filePath, 'utf8');\n const records = parseCsv(raw, { columns: true, skip_empty_lines: true, trim: true });\n return records.map((r: any) => normalizeEvent(r));\n}\n\nfunction toNum(x: any, def = 0): number {\n const n = Number(x);\n return Number.isFinite(n) ? n : def;\n}\n\nfunction normalizeEvent(x: any): UsageEvent {\n // Supports two schemas:\n // 1) scan input schema: input_tokens/output_tokens/feature_tag/retries\n // 2) wrapper usage schema: prompt_tokens/completion_tokens/endpoint/attempt/trace_id/cost_usd\n\n const inputTokens = x.input_tokens ?? x.prompt_tokens;\n const outputTokens = x.output_tokens ?? x.completion_tokens;\n\n // feature_tag fallback: feature_tag -> meta.feature_tag -> endpoint\n const featureTag = x.feature_tag ?? x?.meta?.feature_tag ?? x.endpoint ?? '';\n\n // retries fallback: retries -> max(attempt-1,0)\n const retries = x.retries ?? (x.attempt !== undefined ? Math.max(0, toNum(x.attempt) - 1) : 0);\n\n // billed_cost fallback: billed_cost -> cost_usd\n const billed = x.billed_cost ?? x.cost_usd;\n\n return {\n ts: String(x.ts ?? ''),\n provider: String(x.provider ?? '').toLowerCase(),\n model: String(x.model ?? ''),\n input_tokens: toNum(inputTokens),\n output_tokens: toNum(outputTokens),\n feature_tag: String(featureTag ?? ''),\n retries: toNum(retries),\n status: String(x.status ?? ''),\n billed_cost: billed === undefined || billed === '' ? undefined : toNum(billed),\n\n trace_id: x.trace_id ? String(x.trace_id) : undefined,\n request_id: x.request_id ? String(x.request_id) : undefined,\n attempt: x.attempt === undefined ? undefined : toNum(x.attempt),\n endpoint: x.endpoint ? String(x.endpoint) : undefined\n };\n}\n\nexport function isCsvPath(p: string) {\n return path.extname(p).toLowerCase() === '.csv';\n}\n","import { RateTable, UsageEvent } from './types';\n\nexport type CostResult = {\n cost: number;\n used_rate: {\n kind: 'billed_cost' | 'official' | 'estimated';\n provider: string;\n model: string;\n input_per_m: number;\n output_per_m: number;\n };\n};\n\nexport function getRates(rt: RateTable, provider: string, model: string) {\n const prov = String(provider || '').toLowerCase();\n\n // local/offline LLM: treat cost as 0 (or user can add a provider rate later)\n if (prov === 'local' || prov === 'ollama' || prov === 'vllm') {\n return { kind: 'official' as const, input: 0, output: 0 };\n }\n\n const p = rt.providers[prov];\n if (!p) return null;\n const m = p.models[model];\n if (m) return { kind: 'official' as const, input: m.input, output: m.output };\n return { kind: 'estimated' as const, input: p.default_estimated.input, output: p.default_estimated.output };\n}\n\nexport function costOfEvent(rt: RateTable, ev: UsageEvent): CostResult {\n if (typeof ev.billed_cost === 'number' && Number.isFinite(ev.billed_cost)) {\n return {\n cost: ev.billed_cost,\n used_rate: {\n kind: 'billed_cost',\n provider: ev.provider,\n model: ev.model,\n input_per_m: 0,\n output_per_m: 0\n }\n };\n }\n\n const r = getRates(rt, ev.provider, ev.model);\n if (!r) {\n // Unknown provider: deterministic fallback estimate (kept stable for reproducibility)\n const input_per_m = 1.0;\n const output_per_m = 4.0;\n const cost = (ev.input_tokens / 1e6) * input_per_m + (ev.output_tokens / 1e6) * output_per_m;\n return {\n cost,\n used_rate: { kind: 'estimated', provider: String(ev.provider || '').toLowerCase(), model: ev.model, input_per_m, output_per_m }\n };\n }\n\n const cost = (ev.input_tokens / 1e6) * r.input + (ev.output_tokens / 1e6) * r.output;\n return {\n cost,\n used_rate: {\n kind: r.kind,\n provider: ev.provider,\n model: ev.model,\n input_per_m: r.input,\n output_per_m: r.output\n }\n };\n}\n","import fs from 'fs';\nimport path from 'path';\nimport { AnalysisJson, Savings } from './scan';\n\nexport type Fix = {\n id: string;\n title: string;\n impact_usd: number;\n why: string;\n what_to_change: string[];\n status: 'action' | 'no-issue';\n};\n\nconst EPS = 0.0001;\n\nexport function buildTopFixes(analysis: AnalysisJson, savings: Savings): Fix[] {\n const fixes: Fix[] = [];\n\n // Retry tuning\n fixes.push({\n id: 'fix-retry-tuning',\n title: 'Retry tuning',\n impact_usd: Number(savings.retry_waste || 0),\n status: Number(savings.retry_waste || 0) > EPS ? 'action' : 'no-issue',\n why: `Retry waste is estimated at $${round2(Number(savings.retry_waste || 0))}.`,\n what_to_change: [\n 'aiopt/policies/retry.json: lower max_attempts or adjust backoff_ms',\n 'Ensure idempotency keys are stable per trace_id',\n 'Log error_code to identify retryable classes'\n ]\n });\n\n // Output cap (use context_savings as proxy impact)\n fixes.push({\n id: 'fix-output-cap',\n title: 'Output cap',\n impact_usd: Number(savings.context_savings || 0),\n status: Number(savings.context_savings || 0) > EPS ? 'action' : 'no-issue',\n why: `Context savings estimate: $${round2(Number(savings.context_savings || 0))}. Output caps prevent runaway completions.`,\n what_to_change: [\n 'aiopt/policies/output.json: set max_output_tokens_default',\n 'aiopt/policies/output.json: set per_feature caps (summarize/classify/translate)'\n ]\n });\n\n // Routing\n const topFeature = analysis.by_feature_top?.[0]?.key;\n fixes.push({\n id: 'fix-routing',\n title: 'Routing rule',\n impact_usd: Number(savings.routing_savings || 0),\n status: Number(savings.routing_savings || 0) > EPS ? 'action' : 'no-issue',\n why: `Routing savings estimate: $${round2(Number(savings.routing_savings || 0))}.`,\n what_to_change: [\n 'aiopt/policies/routing.json: route summarize/classify/translate to cheap tier',\n `Consider adding feature_tag_in for top feature: ${topFeature || '(unknown)'}`\n ]\n });\n\n // sort by impact desc, deterministic tie-break\n fixes.sort((a, b) => (b.impact_usd - a.impact_usd) || a.id.localeCompare(b.id));\n return fixes;\n}\n\nfunction round2(n: number) {\n return Math.round(n * 100) / 100;\n}\n\nexport function writePatches(outDir: string, fixes: Fix[]) {\n const patchesDir = path.join(outDir, 'patches');\n fs.mkdirSync(patchesDir, { recursive: true });\n\n const readme = [\n '# AIOpt patches (MVP)',\n '',\n 'This folder contains suggested changes you can apply locally.',\n '',\n '## Top fixes',\n ...fixes.map((f, i) => `${i + 1}. ${f.title} — ${f.why}`),\n '',\n 'Files are stubs (human review required).',\n ''\n ].join('\\n');\n\n fs.writeFileSync(path.join(patchesDir, 'README.md'), readme);\n\n // Minimal stub files to satisfy DoD naming.\n fs.writeFileSync(path.join(patchesDir, 'policies.updated.routing.json'), JSON.stringify({ note: 'apply changes to aiopt/policies/routing.json', fixes: fixes.filter(f => f.id.includes('routing')) }, null, 2));\n fs.writeFileSync(path.join(patchesDir, 'policies.updated.retry.json'), JSON.stringify({ note: 'apply changes to aiopt/policies/retry.json', fixes: fixes.filter(f => f.id.includes('retry')) }, null, 2));\n fs.writeFileSync(path.join(patchesDir, 'policies.updated.output.json'), JSON.stringify({ note: 'apply changes to aiopt/policies/output.json', fixes: fixes.filter(f => f.id.includes('output')) }, null, 2));\n}\n","import fs from 'fs';\nimport path from 'path';\nimport { Finding } from './sarif';\n\nconst DEFAULT_EXCLUDES = new Set([\n '.git',\n 'node_modules',\n 'dist',\n 'aiopt-output',\n '.next',\n 'build',\n 'coverage'\n]);\n\nfunction isTextLike(p: string) {\n const ext = path.extname(p).toLowerCase();\n return ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.py', '.go', '.java', '.kt', '.rb', '.php'].includes(ext);\n}\n\nfunction walk(root: string, out: string[]) {\n const items = fs.readdirSync(root, { withFileTypes: true });\n for (const it of items) {\n if (DEFAULT_EXCLUDES.has(it.name)) continue;\n const full = path.join(root, it.name);\n if (it.isDirectory()) walk(full, out);\n else out.push(full);\n }\n}\n\nfunction findAllLines(content: string, re: RegExp): number[] {\n const lines: number[] = [];\n const parts = content.split(/\\r?\\n/);\n for (let i = 0; i < parts.length; i++) {\n const line = parts[i];\n if (re.test(line)) lines.push(i + 1);\n }\n return lines;\n}\n\nexport function runCodeScan(rootDir: string): Finding[] {\n // This is intentionally lightweight + heuristic:\n // We aim to generate PR annotations with file:line, not perfect static analysis.\n const files: string[] = [];\n walk(rootDir, files);\n\n const findings: Finding[] = [];\n\n for (const file of files) {\n if (!isTextLike(file)) continue;\n\n let st: fs.Stats;\n try { st = fs.statSync(file); } catch { continue; }\n if (!st.isFile()) continue;\n if (st.size > 1024 * 1024) continue; // skip huge files\n\n let content = '';\n try { content = fs.readFileSync(file, 'utf8'); } catch { continue; }\n\n // Rule 1: obvious high retry counts (hardcoded)\n // e.g. retry: 10, maxRetries: 8, attempts: 12\n for (const ln of findAllLines(content, /\\b(maxRetries|maximumRetries|retries|max_attempts|attempts)\\s*[:=]\\s*(\\d{2,}|[6-9])\\b/i)) {\n findings.push({\n ruleId: 'AIOPT.RETRY.EXPLOSION_RISK',\n level: 'warning',\n message: 'High retry/attempt count detected. Consider capping retries to prevent cost explosions.',\n file,\n line: ln,\n help: 'Cap retries (e.g. 2-3), add backoff, and fail fast on non-retriable errors.'\n });\n break; // one per file is enough\n }\n\n // Rule 2: hard-coded expensive model strings (heuristic)\n // Encourage cheap default + override routing.\n for (const ln of findAllLines(content, /(gpt-5\\.?2|gpt-4\\.?|o1-|o3-|claude-3|sonnet|opus)/i)) {\n findings.push({\n ruleId: 'AIOPT.MODEL.ROUTING.EXPENSIVE_DEFAULT',\n level: 'note',\n message: 'Possible expensive model hard-coded. Consider cheap default + explicit override for critical paths.',\n file,\n line: ln,\n help: 'Route cheap by default; allow overrides via env/config for high-impact tasks.'\n });\n break;\n }\n\n // Rule 3: missing timeout (very common cost/latency amplifier)\n // If openai client call exists but no timeout nearby.\n const hasOpenAI = /\\bopenai\\b|\\bOpenAI\\b|responses\\.create|chat\\.completions\\.create/i.test(content);\n const hasTimeout = /\\btimeout\\b|\\brequestTimeout\\b|\\bsignal\\b/i.test(content);\n if (hasOpenAI && !hasTimeout) {\n findings.push({\n ruleId: 'AIOPT.TIMEOUT.MISSING',\n level: 'note',\n message: 'OpenAI/LLM call detected without obvious timeout. Add a timeout to reduce hanging retries and cost waste.',\n file,\n line: 1,\n help: 'Add request timeout / AbortSignal and handle retryable errors explicitly.'\n });\n }\n }\n\n // Keep SARIF small/deterministic\n return findings.slice(0, 200);\n}\n","import path from 'path';\n\nexport type Finding = {\n ruleId: string;\n level: 'note' | 'warning' | 'error';\n message: string;\n file: string; // relative or absolute\n line: number; // 1-indexed\n help?: string;\n};\n\nfunction toUri(p: string) {\n // SARIF expects file:// URIs for local paths\n // Use path.resolve to normalize.\n const abs = path.resolve(p);\n // Windows drive handling: file:///C:/...\n const u = abs.replace(/\\\\/g, '/');\n return u.match(/^[A-Za-z]:\\//) ? `file:///${u}` : `file://${u}`;\n}\n\nexport function buildSarif(toolName: string, toolVersion: string, findings: Finding[]) {\n // Minimal SARIF v2.1.0 that GitHub code scanning can ingest.\n // We keep rule metadata tiny; details live in report/patch artifacts.\n const rulesMap = new Map<string, { id: string; shortDescription: string; help?: string }>();\n for (const f of findings) {\n if (!rulesMap.has(f.ruleId)) {\n rulesMap.set(f.ruleId, {\n id: f.ruleId,\n shortDescription: f.ruleId,\n help: f.help\n });\n }\n }\n\n const rules = [...rulesMap.values()].map(r => ({\n id: r.id,\n shortDescription: { text: r.shortDescription },\n help: r.help ? { text: r.help } : undefined\n })).map(x => {\n // drop undefined fields\n const y: any = { ...x };\n if (!y.help) delete y.help;\n return y;\n });\n\n const results = findings.map(f => ({\n ruleId: f.ruleId,\n level: f.level,\n message: { text: f.message },\n locations: [\n {\n physicalLocation: {\n artifactLocation: { uri: toUri(f.file) },\n region: { startLine: Math.max(1, Math.floor(f.line || 1)) }\n }\n }\n ]\n }));\n\n return {\n $schema: 'https://json.schemastore.org/sarif-2.1.0.json',\n version: '2.1.0',\n runs: [\n {\n tool: {\n driver: {\n name: toolName,\n version: toolVersion,\n informationUri: 'https://www.npmjs.com/package/aiopt',\n rules\n }\n },\n results\n }\n ]\n };\n}\n","import fs from 'fs';\nimport path from 'path';\nimport { RateTable, UsageEvent } from './types';\nimport { costOfEvent, getRates } from './cost';\nimport { buildTopFixes, writePatches } from './solutions';\nimport { runCodeScan } from './code-scan';\nimport { buildSarif } from './sarif';\n\nexport type AnalysisJson = {\n total_cost: number;\n by_model_top: Array<{ key: string; cost: number; events: number }>;\n by_feature_top: Array<{ key: string; cost: number; events: number }>;\n unknown_models: Array<{ provider: string; model: string; reason: string }>;\n rate_table_version: string;\n rate_table_date: string;\n};\n\nexport type Savings = {\n estimated_savings_total: number;\n routing_savings: number;\n context_savings: number;\n retry_waste: number;\n notes: [string, string, string];\n};\n\nexport type PolicyJson = {\n version: number;\n default_provider: string;\n rules: Array<any>;\n budgets: { currency: string; notes?: string };\n generated_from: { rate_table_version: string; input: string };\n};\n\nconst ROUTE_TO_CHEAP_FEATURES = new Set(['summarize', 'classify', 'translate']);\n\nfunction topN(map: Map<string, { cost: number; events: number }>, n: number) {\n return [...map.entries()]\n .map(([key, v]) => ({ key, cost: v.cost, events: v.events }))\n .sort((a, b) => b.cost - a.cost)\n .slice(0, n);\n}\n\nexport function analyze(rt: RateTable, events: UsageEvent[]): { analysis: AnalysisJson; savings: Savings; policy: PolicyJson; meta: { mode: 'attempt-log'|'legacy' } } {\n const byModel = new Map<string, { cost: number; events: number }>();\n const byFeature = new Map<string, { cost: number; events: number }>();\n const unknownModels: AnalysisJson['unknown_models'] = [];\n\n const perEventCosts: Array<{ ev: UsageEvent; cost: number }> = [];\n\n // Detect wrapper attempt-log mode: each JSONL line is an attempt (trace_id/attempt present)\n const isAttemptLog = events.some(e => (e.trace_id && String(e.trace_id).length > 0) || (e.attempt !== undefined && Number(e.attempt) > 0));\n\n let baseTotal = 0;\n let total = 0;\n for (const ev of events) {\n const cr = costOfEvent(rt, ev);\n\n baseTotal += cr.cost;\n\n if (isAttemptLog) {\n // Each event line is already one attempt; do NOT multiply by retries.\n total += cr.cost;\n } else {\n // Legacy aggregate mode: one line represents a request with retries count.\n const retries = Math.max(0, Number(ev.retries || 0));\n total += cr.cost * (1 + retries);\n }\n\n perEventCosts.push({ ev, cost: cr.cost });\n\n const mk = `${ev.provider}:${ev.model}`;\n const fk = ev.feature_tag || '(none)';\n\n const mv = byModel.get(mk) || { cost: 0, events: 0 };\n mv.cost += cr.cost; mv.events += 1;\n byModel.set(mk, mv);\n\n const fv = byFeature.get(fk) || { cost: 0, events: 0 };\n fv.cost += cr.cost; fv.events += 1;\n byFeature.set(fk, fv);\n\n const rr = getRates(rt, ev.provider, ev.model);\n if (!rr) {\n unknownModels.push({ provider: ev.provider, model: ev.model, reason: 'unknown provider (estimated)' });\n } else if (rr.kind === 'estimated') {\n unknownModels.push({ provider: ev.provider, model: ev.model, reason: 'unknown model (estimated)' });\n }\n }\n\n // --- Savings simulator (refactor): per-event before/after with caps + no double counting\n type Pot = { routing: number; context: number; retry: number; total: number; waste: number };\n const potByIdx: Pot[] = [];\n\n // Potential routing/context computed per event\n for (const { ev, cost } of perEventCosts) {\n const retries = Math.max(0, Number(ev.retries || 0));\n const attempt = Number(ev.attempt || 1);\n\n const total_i = isAttemptLog ? cost : cost * (1 + retries);\n // Retry waste:\n // - attempt-log mode: attempts >= 2 are retry waste\n // - legacy mode: base_cost * retries\n const waste_i = isAttemptLog ? (attempt >= 2 ? cost : 0) : cost * retries;\n\n let routing_i = 0;\n if (ROUTE_TO_CHEAP_FEATURES.has(String(ev.feature_tag || '').toLowerCase())) {\n const provider = ev.provider;\n const p = rt.providers[provider];\n if (p) {\n const entries = Object.entries(p.models);\n if (entries.length > 0) {\n const cheapest = entries\n .map(([name, r]) => ({ name, score: (r.input + r.output) / 2, r }))\n .sort((a, b) => a.score - b.score)[0];\n const currentRate = getRates(rt, provider, ev.model);\n if (currentRate && currentRate.kind !== 'estimated') {\n const currentCost = (ev.input_tokens / 1e6) * currentRate.input + (ev.output_tokens / 1e6) * currentRate.output;\n const cheapCost = (ev.input_tokens / 1e6) * cheapest.r.input + (ev.output_tokens / 1e6) * cheapest.r.output;\n const diff = (currentCost - cheapCost) * (1 + retries);\n routing_i = Math.max(0, diff);\n }\n }\n }\n }\n\n // context: top 20% rule is applied later by index set\n potByIdx.push({ routing: routing_i, context: 0, retry: waste_i, total: total_i, waste: waste_i });\n }\n\n // context potential assignment (deterministic): top 20% by input_tokens => 25% reduction\n // In attempt-log mode, only apply to attempt==1 to avoid overcounting retries.\n const sortedIdx = [...events.map((e, i) => ({ i, input: Number(e.input_tokens || 0), ok: !isAttemptLog || Number(e.attempt || 1) === 1 }))]\n .filter(x => x.ok)\n .sort((a, b) => b.input - a.input);\n const k = Math.max(1, Math.floor(sortedIdx.length * 0.2));\n const topIdx = new Set(sortedIdx.slice(0, k).map(x => x.i));\n for (let i = 0; i < events.length; i++) {\n if (!topIdx.has(i)) continue;\n const ev = events[i];\n const retries = Math.max(0, Number(ev.retries || 0));\n const r = getRates(rt, ev.provider, ev.model);\n if (!r) continue;\n const saveTokens = (Number(ev.input_tokens || 0)) * 0.25;\n const multiplier = isAttemptLog ? 1 : (1 + retries);\n const diff = (saveTokens / 1e6) * r.input * multiplier;\n potByIdx[i].context = Math.max(0, diff);\n }\n\n // Allocate savings without overlap (routing -> context -> retry), each capped by remaining cost.\n let routingSavings = 0;\n let contextSavings = 0;\n let retryWaste = 0;\n\n for (const p of potByIdx) {\n let remaining = p.total;\n\n const rSave = Math.min(p.routing, remaining);\n remaining -= rSave;\n routingSavings += rSave;\n\n const cSave = Math.min(p.context, remaining);\n remaining -= cSave;\n contextSavings += cSave;\n\n // Retry tuning can only save the waste portion, and cannot exceed remaining.\n const retrySave = Math.min(p.retry, remaining);\n retryWaste += retrySave;\n }\n\n const estimatedSavingsTotal = routingSavings + contextSavings + retryWaste;\n // Global guard\n const guardedSavingsTotal = Math.min(estimatedSavingsTotal, total);\n\n const analysis: AnalysisJson = {\n total_cost: round2(total),\n by_model_top: topN(byModel, 10).map(x => ({ ...x, cost: round2(x.cost) })),\n by_feature_top: topN(byFeature, 10).map(x => ({ ...x, cost: round2(x.cost) })),\n unknown_models: uniqUnknown(unknownModels),\n rate_table_version: rt.version,\n rate_table_date: rt.date\n };\n\n const savings: Savings = {\n estimated_savings_total: round2(guardedSavingsTotal),\n routing_savings: round2(routingSavings),\n context_savings: round2(contextSavings),\n retry_waste: round2(retryWaste),\n notes: [\n `a) 모델 라우팅 절감(추정): $${round2(routingSavings)}`,\n `b) 컨텍스트 감축(추정): $${round2(contextSavings)} (상위 20% input에 25% 감축 가정)` ,\n `c) 재시도/오류 낭비(상한 적용): $${round2(retryWaste)} (retries 기반)`\n ]\n };\n\n const policy: PolicyJson = buildPolicy(rt, events);\n\n return { analysis, savings, policy, meta: { mode: isAttemptLog ? 'attempt-log' : 'legacy' } };\n}\n\nfunction buildPolicy(rt: RateTable, events: UsageEvent[]): PolicyJson {\n // Default provider: most frequent\n const freq = new Map<string, number>();\n for (const ev of events) freq.set(ev.provider, (freq.get(ev.provider) || 0) + 1);\n const defaultProvider = [...freq.entries()].sort((a, b) => b[1] - a[1])[0]?.[0] || 'openai';\n\n // For cheap features: recommend cheapest known model per provider.\n const rules: any[] = [];\n for (const provider of Object.keys(rt.providers)) {\n const p = rt.providers[provider];\n const entries = Object.entries(p.models);\n if (entries.length === 0) continue;\n const cheapest = entries\n .map(([name, r]) => ({ name, score: (r.input + r.output) / 2, r }))\n .sort((a, b) => a.score - b.score)[0];\n\n rules.push({\n match: { provider, feature_tag_in: ['summarize', 'classify', 'translate'] },\n action: { recommend_model: cheapest.name, reason: 'cheap-feature routing' }\n });\n }\n\n // Unknown models: keep (no policy)\n rules.push({ match: { model_unknown: true }, action: { keep: true, reason: 'unknown model -> no policy applied' } });\n\n return {\n version: 1,\n default_provider: defaultProvider,\n rules,\n budgets: { currency: rt.currency, notes: 'MVP: budgets not enforced' },\n generated_from: { rate_table_version: rt.version, input: './aiopt-input/usage.jsonl' }\n };\n}\n\nfunction uniqUnknown(list: AnalysisJson['unknown_models']) {\n const seen = new Set<string>();\n const out: AnalysisJson['unknown_models'] = [];\n for (const x of list) {\n const k = `${x.provider}:${x.model}:${x.reason}`;\n if (seen.has(k)) continue;\n seen.add(k);\n out.push(x);\n }\n return out;\n}\n\nfunction round2(n: number) {\n return Math.round(n * 100) / 100;\n}\n\nexport function writeOutputs(outDir: string, analysis: AnalysisJson, savings: Savings, policy: PolicyJson, meta?: { mode?: 'attempt-log'|'legacy'; cwd?: string; cliVersion?: string }) {\n const mode = meta?.mode || 'legacy';\n\n fs.mkdirSync(outDir, { recursive: true });\n\n fs.writeFileSync(path.join(outDir, 'analysis.json'), JSON.stringify(analysis, null, 2));\n\n // report.json is the “one file to parse” summary for downstream tooling.\n const unknownCount = analysis.unknown_models?.length || 0;\n // confidence: downgrade if many unknowns; keep deterministic\n const confidence = unknownCount === 0 ? 'HIGH' : (unknownCount <= 3 ? 'MED' : 'LOW');\n const ratio = analysis.total_cost > 0 ? (savings.estimated_savings_total / analysis.total_cost) : 0;\n const warnings: string[] = [];\n if (ratio >= 0.9) warnings.push('estimated savings >= 90%');\n if (unknownCount > 0) warnings.push('unknown models/providers detected (estimated pricing used)');\n\n const reportJson = {\n version: 3,\n generated_at: new Date().toISOString(),\n confidence,\n warnings,\n assumptions: {\n no_double_counting: 'routing -> context -> retry allocation per-event with remaining-cost caps',\n retry_cost_model: mode === 'attempt-log'\n ? 'attempt-log mode: total_cost is sum of attempt lines; retry_waste is sum of attempts>=2'\n : 'legacy mode: total_cost includes retries as extra attempts (base_cost*(1+retries))',\n context_model: 'top 20% by input_tokens assume 25% input reduction',\n estimated_pricing_note: unknownCount > 0 ? 'some items use estimated rates; treat savings as a band' : 'all items used known rates'\n },\n summary: {\n total_cost_usd: analysis.total_cost,\n estimated_savings_usd: savings.estimated_savings_total,\n routing_savings_usd: savings.routing_savings,\n context_savings_usd: savings.context_savings,\n retry_waste_usd: savings.retry_waste\n },\n top: {\n by_model: analysis.by_model_top,\n by_feature: analysis.by_feature_top\n },\n unknown_models: analysis.unknown_models,\n notes: savings.notes\n };\n fs.writeFileSync(path.join(outDir, 'report.json'), JSON.stringify(reportJson, null, 2));\n\n // report.md: \"what to change\" guidance + confidence/assumptions (T4 DoD)\n const ratioMd = analysis.total_cost > 0 ? (savings.estimated_savings_total / analysis.total_cost) : 0;\n const warningsMd: string[] = [];\n if (ratioMd >= 0.9) warningsMd.push('WARNING: estimated savings >= 90% — check overlap/missing rate table');\n\n const reportMd = [\n '# AIOpt Report',\n '',\n `- Total cost: $${analysis.total_cost}`,\n `- Estimated savings: $${savings.estimated_savings_total} (guarded <= total_cost)`,\n `- Confidence: ${confidence}`,\n unknownCount > 0 ? `- Unknown models: ${unknownCount} (estimated pricing used)` : '- Unknown models: 0',\n ...warningsMd.map(w => `- ${w}`),\n '',\n '## ASSUMPTIONS',\n '- No double-counting: routing → context → retry savings allocated per-event with remaining-cost caps.',\n mode === 'attempt-log'\n ? '- Retry cost model: attempt-log mode (total_cost=sum attempts, retry_waste=sum attempt>=2).'\n : '- Retry cost model: legacy mode (total_cost=base_cost*(1+retries)).',\n '- Context savings: top 20% input_tokens events assume 25% input reduction.',\n '',\n '## WHAT TO CHANGE',\n '1) Retry tuning → edit `aiopt/policies/retry.json`',\n '2) Output cap → edit `aiopt/policies/output.json`',\n '3) Routing rule → edit `aiopt/policies/routing.json`',\n '',\n '## OUTPUTS',\n '- `aiopt-output/analysis.json`',\n '- `aiopt-output/report.json`',\n '- `aiopt-output/patches/*`',\n ''\n ].join('\\n');\n fs.writeFileSync(path.join(outDir, 'report.md'), reportMd);\n\n const reportTxt = [\n `총비용: $${analysis.total_cost}`,\n `절감 가능 금액(Estimated): $${savings.estimated_savings_total}`,\n `절감 근거 3줄:`,\n savings.notes[0],\n savings.notes[1],\n savings.notes[2],\n ''\n ].join('\\n');\n fs.writeFileSync(path.join(outDir, 'report.txt'), reportTxt);\n\n fs.writeFileSync(path.join(outDir, 'cost-policy.json'), JSON.stringify(policy, null, 2));\n\n // patches/*\n const fixes = buildTopFixes(analysis, savings);\n writePatches(outDir, fixes);\n\n // Optional: SARIF output for PR annotations (best-effort, compatibility-safe).\n // This uses lightweight code scanning heuristics to produce file:line findings.\n try {\n const cwd = meta?.cwd;\n const cliVersion = meta?.cliVersion || 'unknown';\n if (cwd && fs.existsSync(cwd)) {\n const findings = runCodeScan(cwd);\n const sarif = buildSarif('aiopt', cliVersion, findings);\n fs.writeFileSync(path.join(outDir, 'aiopt.sarif'), JSON.stringify(sarif, null, 2));\n }\n } catch {\n // ignore\n }\n}\n","{\n \"name\": \"aiopt\",\n \"version\": \"0.3.5\",\n \"description\": \"Pre-deploy LLM cost accident guardrail (serverless local CLI)\",\n \"bin\": {\n \"aiopt\": \"dist/cli.js\"\n },\n \"type\": \"commonjs\",\n \"main\": \"dist/cli.js\",\n \"files\": [\n \"dist\",\n \"rates\",\n \"samples\",\n \"README.md\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"node --enable-source-maps dist/cli.js\",\n \"prepack\": \"npm run build\",\n \"test:npx\": \"npm pack --silent && node -e \\\"const fs=require('fs');const p=fs.readdirSync('.').find(f=>/^aiopt-.*\\\\.tgz$/.test(f)); if(!p) throw new Error('tgz not found'); console.log('tgz',p);\\\" && npx --yes ./$(ls -1 aiopt-*.tgz | tail -n 1) install --force && npx --yes ./$(ls -1 aiopt-*.tgz | tail -n 1) doctor && npx --yes ./$(ls -1 aiopt-*.tgz | tail -n 1) scan && test -f ./aiopt-output/report.md && echo OK\",\n \"test:guard\": \"npm run build --silent && node scripts/test-guard.js\",\n \"test:license\": \"npm run build --silent && node scripts/test-license.js\",\n \"test:landing\": \"node scripts/test-landing.js\"\n },\n \"dependencies\": {\n \"commander\": \"^14.0.0\",\n \"csv-parse\": \"^6.1.0\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^24.0.0\",\n \"tsup\": \"^8.5.0\",\n \"typescript\": \"^5.9.2\"\n }\n}\n","import fs from 'fs';\nimport path from 'path';\n\nexport type InstallOptions = {\n force?: boolean;\n seedSample?: boolean;\n};\n\nfunction ensureDir(p: string) {\n fs.mkdirSync(p, { recursive: true });\n}\n\nfunction writeFile(filePath: string, content: string, force?: boolean) {\n if (!force && fs.existsSync(filePath)) return { wrote: false, reason: 'exists' as const };\n ensureDir(path.dirname(filePath));\n fs.writeFileSync(filePath, content);\n return { wrote: true as const };\n}\n\nexport function runInstall(cwd: string, opts: InstallOptions) {\n const force = Boolean(opts.force);\n\n const aioptDir = path.join(cwd, 'aiopt');\n const policiesDir = path.join(aioptDir, 'policies');\n const outDir = path.join(cwd, 'aiopt-output');\n\n ensureDir(aioptDir);\n ensureDir(policiesDir);\n ensureDir(outDir);\n\n const created: Array<{ path: string; status: 'created' | 'skipped' }> = [];\n\n // 1) aiopt/README.md\n const readme = `# AIOpt\n\nAIOpt는 **scan툴이 아니라 설치형 비용 가드레일이다.**\n\n## Quick start\n\\`\\`\\`bash\nnpx aiopt install --force\nnpx aiopt doctor\n# (your app runs, wrapper logs usage)\nnpx aiopt scan\n\\`\\`\\`\n\n- 서버/대시보드/계정/업로드/결제/프록시 없음\n- 로컬 파일 기반(정책 + usage.jsonl)\n- LLM 호출 금지(수학/룰 기반)\n\n## Wrapper usage (Node.js)\n\nAIOpt 설치 후, 앱 코드에서 wrapper를 불러서 사용량 JSONL을 자동 기록할 수 있습니다.\n\n\na) 최소 형태(토큰을 직접 넘김)\n\n\\`\\`\\`js\nconst { guardedCall } = require('./aiopt/aiopt-wrapper.js');\n\nawait guardedCall(process.cwd(), {\n provider: 'openai',\n model: 'gpt-5-mini',\n endpoint: 'responses.create',\n feature_tag: 'summarize',\n prompt_tokens: 1200,\n trace_id: 'my-trace'\n}, async (req) => {\n // req: { provider, model, endpoint, max_output_tokens, prompt_tokens, idempotency_key }\n // 여기서 실제 SDK 호출 후 결과를 반환\n return { status: 'ok', completion_tokens: 200 };\n});\n\\`\\`\\`\n\nb) OpenAI-style 응답(usage 자동 추출)\n\n\\`\\`\\`js\nreturn {\n status: 'ok',\n response: {\n usage: { prompt_tokens: 1200, completion_tokens: 200, total_tokens: 1400 }\n }\n};\n\\`\\`\\`\n`;\n\n const r1 = writeFile(path.join(aioptDir, 'README.md'), readme, force);\n created.push({ path: 'aiopt/README.md', status: r1.wrote ? 'created' : 'skipped' });\n\n // 2) aiopt/aiopt.config.json\n const config = {\n version: 1,\n installed_at: new Date().toISOString(),\n output_dir: './aiopt-output',\n usage_path: './aiopt-output/usage.jsonl',\n policies_dir: './aiopt/policies',\n rate_table: { path: './rates/rate_table.json' }\n };\n const r2 = writeFile(path.join(aioptDir, 'aiopt.config.json'), JSON.stringify(config, null, 2) + '\\n', force);\n created.push({ path: 'aiopt/aiopt.config.json', status: r2.wrote ? 'created' : 'skipped' });\n\n // 3) policies\n const routing = {\n version: 1,\n rules: [\n { match: { feature_tag_in: ['summarize', 'classify', 'translate'] }, action: { tier: 'cheap', reason: 'cheap feature routing' } },\n { match: { feature_tag_in: ['coding', 'reasoning'] }, action: { tier: 'default', reason: 'keep for quality' } }\n ]\n };\n const retry = {\n version: 1,\n max_attempts: 2,\n backoff_ms: [200, 500],\n retry_on_status: ['error', 'timeout'],\n notes: 'MVP deterministic retry tuning'\n };\n const output = {\n version: 1,\n max_output_tokens_default: 1024,\n per_feature: {\n summarize: 512,\n classify: 256,\n translate: 512\n }\n };\n const context = {\n version: 1,\n input_token_soft_cap: 12000,\n reduce_top_percentile: 0.2,\n assumed_reduction_ratio: 0.25\n };\n\n const p1 = writeFile(path.join(policiesDir, 'routing.json'), JSON.stringify(routing, null, 2) + '\\n', force);\n const p2 = writeFile(path.join(policiesDir, 'retry.json'), JSON.stringify(retry, null, 2) + '\\n', force);\n const p3 = writeFile(path.join(policiesDir, 'output.json'), JSON.stringify(output, null, 2) + '\\n', force);\n const p4 = writeFile(path.join(policiesDir, 'context.json'), JSON.stringify(context, null, 2) + '\\n', force);\n\n created.push({ path: 'aiopt/policies/routing.json', status: p1.wrote ? 'created' : 'skipped' });\n created.push({ path: 'aiopt/policies/retry.json', status: p2.wrote ? 'created' : 'skipped' });\n created.push({ path: 'aiopt/policies/output.json', status: p3.wrote ? 'created' : 'skipped' });\n created.push({ path: 'aiopt/policies/context.json', status: p4.wrote ? 'created' : 'skipped' });\n\n // 4) wrapper template (T2: real guardrails wrapper)\n const wrapperPath = path.join(aioptDir, 'aiopt-wrapper.js');\n const wrapper = \n`// AIOpt Wrapper (guardrails) — local-only (CommonJS)\n\nconst fs = require('fs');\n\nconst path = require('path');\n\nconst crypto = require('crypto');\n\nfunction readJson(p){ return JSON.parse(fs.readFileSync(p,'utf8')); }\nfunction ensureDir(p){ fs.mkdirSync(p,{recursive:true}); }\nfunction appendJsonl(filePath,obj){ ensureDir(path.dirname(filePath)); fs.appendFileSync(filePath, JSON.stringify(obj)+'\\\\n'); }\nfunction sleep(ms){ return new Promise(r=>setTimeout(r,ms)); }\n\nfunction loadConfig(cwd){ return readJson(path.join(cwd,'aiopt','aiopt.config.json')); }\nfunction loadPolicies(cwd,cfg){ const dir=path.isAbsolute(cfg.policies_dir)?cfg.policies_dir:path.join(cwd,cfg.policies_dir);\n return {\n retry: readJson(path.join(dir,'retry.json')) ,\n output: readJson(path.join(dir,'output.json'))\n };\n}\nfunction loadRates(cwd,cfg){\n const rp=path.isAbsolute(cfg.rate_table.path)?cfg.rate_table.path:path.join(cwd,cfg.rate_table.path);\n try{ return readJson(rp); }catch(e){\n // Fresh projects may not have a rates/ table yet. Fall back to a safe default.\n return { providers: {} };\n }\n}\n\nfunction costUsd(rt, provider, model, promptTokens, completionTokens){\n const p=rt.providers && rt.providers[provider];\n const r=(p && p.models && p.models[model]) || (p && p.default_estimated) || {input:1.0, output:4.0};\n return (promptTokens/1e6)*r.input + (completionTokens/1e6)*r.output;\n}\n\nfunction pickRoutedModel(rt, provider, featureTag, currentModel){\n const cheap=['summarize','classify','translate'];\n if(!cheap.includes(String(featureTag||'').toLowerCase())) return { model: currentModel, routed_from: null, hit: null };\n const p=rt.providers && rt.providers[provider];\n const entries=p && p.models ? Object.entries(p.models) : [];\n if(!entries.length) return { model: currentModel, routed_from: null, hit: null };\n const cheapest=entries.map(([name,r])=>({name,score:(r.input+r.output)/2})).sort((a,b)=>a.score-b.score)[0];\n if(!cheapest || cheapest.name===currentModel) return { model: currentModel, routed_from: null, hit: null };\n return { model: cheapest.name, routed_from: currentModel, hit: 'routing:cheap-feature' };\n}\n\nfunction outputCap(outputPolicy, featureTag, requested){\n const per=(outputPolicy && outputPolicy.per_feature) || {};\n const cap=per[String(featureTag||'').toLowerCase()] ?? (outputPolicy.max_output_tokens_default || 1024);\n const req=requested ?? cap;\n return Math.min(req, cap);\n}\n\nconst IDEMPOTENCY=new Map();\n\nfunction normalizeResult(out, input){\n // Accept either normalized return or provider raw.\n const o = (out && out.response) ? out.response : out;\n const status = (out && out.status) || o.status || (o.error ? 'error' : 'ok');\n const usage = o.usage || (o.data && o.data.usage) || null;\n\n const prompt_tokens = Number(\n (out && out.prompt_tokens) ??\n (o && o.prompt_tokens) ??\n (usage && usage.prompt_tokens) ??\n input.prompt_tokens ??\n 0\n );\n const completion_tokens = Number(\n (out && out.completion_tokens) ??\n (o && o.completion_tokens) ??\n (usage && usage.completion_tokens) ??\n 0\n );\n const total_tokens = Number(\n (out && out.total_tokens) ??\n (o && o.total_tokens) ??\n (usage && usage.total_tokens) ??\n (prompt_tokens + completion_tokens)\n );\n\n const error_code = status === 'ok' ? null : String((out && out.error_code) || (o && o.error_code) || (o && o.error && (o.error.code || o.error.type)) || status);\n const cost_usd = (out && typeof out.cost_usd === 'number') ? out.cost_usd : null;\n\n return { status, prompt_tokens, completion_tokens, total_tokens, error_code, cost_usd };\n}\n\n/**\n * guardedCall(cwd, input, fn)\n *\n * fn(req) can return either:\n * 1) Normalized shape:\n * { status: 'ok'|'error'|'timeout', prompt_tokens?, completion_tokens?, total_tokens?, cost_usd?, error_code? }\n * 2) Provider raw response (OpenAI-style), e.g.:\n * { status:'ok', response:{ usage:{prompt_tokens, completion_tokens, total_tokens} } }\n * { usage:{prompt_tokens, completion_tokens, total_tokens} }\n *\n * If token fields are missing, AIOpt will fall back to input.prompt_tokens and/or 0.\n */\nasync function guardedCall(cwd, input, fn){\n const cfg=loadConfig(cwd);\n const pol=loadPolicies(cwd,cfg);\n const rt=loadRates(cwd,cfg);\n\n const request_id=crypto.randomUUID();\n const trace_id=input.trace_id || request_id;\n const idem=input.idempotency_key || trace_id;\n if(IDEMPOTENCY.has(idem)) return IDEMPOTENCY.get(idem);\n\n const routed=pickRoutedModel(rt, input.provider, input.feature_tag, input.model);\n const maxOut=outputCap(pol.output, input.feature_tag, input.max_output_tokens);\n const usagePath=path.isAbsolute(cfg.usage_path)?cfg.usage_path:path.join(cwd,cfg.usage_path);\n\n const maxAttempts=Math.max(1, Number(pol.retry.max_attempts||1));\n const backoffs=pol.retry.backoff_ms || [200];\n const retryOn=new Set(pol.retry.retry_on_status || ['error','timeout']);\n\n let last={status:'error', completion_tokens:0, error_code:'unknown'};\n\n for(let attempt=1; attempt<=maxAttempts; attempt++){\n const t0=Date.now();\n const policy_hits=[];\n if(routed.hit) policy_hits.push(routed.hit);\n policy_hits.push('outputcap:'+maxOut);\n try{\n const out=await fn({ provider: input.provider, model: routed.model, endpoint: input.endpoint, max_output_tokens: maxOut, prompt_tokens: input.prompt_tokens, idempotency_key: idem });\n const latency_ms=Date.now()-t0;\n const norm=normalizeResult(out, input);\n const cost_usd=(typeof norm.cost_usd==='number') ? norm.cost_usd : costUsd(rt, input.provider, routed.model, norm.prompt_tokens, norm.completion_tokens);\n const feature_tag = input.feature_tag || input.endpoint || 'unknown';\n appendJsonl(usagePath, { ts:new Date().toISOString(), request_id, trace_id, attempt, status: norm.status, error_code: norm.error_code, provider: input.provider, model: routed.model, endpoint: input.endpoint, prompt_tokens: norm.prompt_tokens, completion_tokens: norm.completion_tokens, total_tokens: norm.total_tokens, cost_usd, latency_ms, meta:{ feature_tag, routed_from: routed.routed_from, policy_hits } });\n last={ status: norm.status, completion_tokens: norm.completion_tokens, error_code: norm.error_code };\n if(norm.status==='ok'){ IDEMPOTENCY.set(idem,out); return out; }\n if(retryOn.has(norm.status) && attempt<maxAttempts){ await sleep(Number(backoffs[Math.min(attempt-1, backoffs.length-1)]||200)); continue; }\n IDEMPOTENCY.set(idem,out); return out;\n }catch(e){\n const latency_ms=Date.now()-t0;\n const out={ status:'error', completion_tokens:0, error_code:String(e && (e.code||e.name) || 'exception') };\n const feature_tag = input.feature_tag || input.endpoint || 'unknown';\n appendJsonl(usagePath, { ts:new Date().toISOString(), request_id, trace_id, attempt, status: out.status, error_code: out.error_code, provider: input.provider, model: routed.model, endpoint: input.endpoint, prompt_tokens:Number(input.prompt_tokens||0), completion_tokens:0, total_tokens:Number(input.prompt_tokens||0), cost_usd:costUsd(rt, input.provider, routed.model, Number(input.prompt_tokens||0), 0), latency_ms, meta:{ feature_tag, routed_from: routed.routed_from, policy_hits:[routed.hit||'routing:none','outputcap:'+maxOut,'error:exception'] } });\n last=out;\n if(attempt<maxAttempts){ await sleep(Number(backoffs[Math.min(attempt-1, backoffs.length-1)]||200)); continue; }\n IDEMPOTENCY.set(idem,out); return out;\n }\n }\n IDEMPOTENCY.set(idem,last);\n return last;\n}\n\nmodule.exports = { guardedCall };\n`;\n;\n const w = writeFile(wrapperPath, wrapper, force);\n created.push({ path: 'aiopt/aiopt-wrapper.js', status: w.wrote ? 'created' : 'skipped' });\n\n // 5) usage.jsonl\n const usagePath = path.join(outDir, 'usage.jsonl');\n if (force || !fs.existsSync(usagePath)) {\n // default: empty file (avoid mixing demo data into real user logs)\n fs.writeFileSync(usagePath, '');\n created.push({ path: 'aiopt-output/usage.jsonl', status: 'created' });\n\n if (opts.seedSample) {\n const sample = {\n ts: new Date().toISOString(),\n request_id: 'sample',\n trace_id: 'sample',\n attempt: 1,\n status: 'ok',\n error_code: null,\n provider: 'openai',\n model: 'gpt-5-mini',\n endpoint: 'demo',\n prompt_tokens: 12,\n completion_tokens: 3,\n total_tokens: 15,\n cost_usd: 0.0,\n latency_ms: 1,\n meta: { feature_tag: 'demo', routed_from: null, policy_hits: ['install-sample'] }\n };\n fs.appendFileSync(usagePath, JSON.stringify(sample) + '\\n');\n }\n } else {\n created.push({ path: 'aiopt-output/usage.jsonl', status: 'skipped' });\n }\n\n return { created };\n}\n","import fs from 'fs';\nimport path from 'path';\n\nfunction canWrite(dir: string) {\n try {\n fs.mkdirSync(dir, { recursive: true });\n const p = path.join(dir, `.aiopt-write-test-${Date.now()}`);\n fs.writeFileSync(p, 'ok');\n fs.unlinkSync(p);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction tailLines(filePath: string, n: number): string[] {\n try {\n const raw = fs.readFileSync(filePath, 'utf8');\n const lines = raw.split(/\\r?\\n/).filter(l => l.trim().length > 0);\n return lines.slice(Math.max(0, lines.length - n));\n } catch {\n return [];\n }\n}\n\nexport type DoctorResult = {\n ok: boolean;\n checks: Array<{ name: string; ok: boolean; detail?: string }>;\n last5: Array<{ status?: string; provider?: string; model?: string; endpoint?: string; attempt?: number }>;\n};\n\nexport function runDoctor(cwd: string): DoctorResult {\n const aioptDir = path.join(cwd, 'aiopt');\n const policiesDir = path.join(aioptDir, 'policies');\n const outDir = path.join(cwd, 'aiopt-output');\n const usagePath = path.join(outDir, 'usage.jsonl');\n\n const checks: DoctorResult['checks'] = [];\n\n checks.push({ name: 'aiopt/ exists', ok: fs.existsSync(aioptDir) });\n checks.push({ name: 'aiopt/policies exists', ok: fs.existsSync(policiesDir) });\n checks.push({ name: 'aiopt-output/ writable', ok: canWrite(outDir) });\n checks.push({ name: 'usage.jsonl exists', ok: fs.existsSync(usagePath), detail: usagePath });\n\n const last5raw = tailLines(usagePath, 5);\n const last5 = last5raw.length === 0 ? [{ status: '(empty usage.jsonl)' }] as any : last5raw.map(l => {\n try {\n const j = JSON.parse(l);\n return {\n status: j.status,\n provider: j.provider,\n model: j.model,\n endpoint: j.endpoint,\n attempt: j.attempt,\n feature_tag: j?.meta?.feature_tag\n };\n } catch {\n return {};\n }\n });\n\n // Feature-tag quality check (sample last 50 lines)\n const last50 = tailLines(usagePath, 50);\n let missing = 0;\n let total50 = 0;\n for (const l of last50) {\n total50++;\n try {\n const j = JSON.parse(l);\n const ft = j?.meta?.feature_tag;\n if (!ft || String(ft).trim() === '') missing++;\n } catch {\n missing++;\n }\n }\n if (total50 > 0 && missing > 0) {\n checks.push({ name: 'feature_tag quality (last50)', ok: false, detail: `${missing}/${total50} missing meta.feature_tag` });\n } else {\n checks.push({ name: 'feature_tag quality (last50)', ok: true, detail: 'meta.feature_tag present' });\n }\n\n const ok = checks.every(c => c.ok);\n return { ok, checks, last5 };\n}\n\n","import crypto from 'crypto';\nimport fs from 'fs';\nimport path from 'path';\n\nexport type LicensePayload = {\n sub: string; // customer id/email/etc\n plan: 'pro' | 'team' | 'trial' | string;\n iat: number; // issued at (unix seconds)\n exp: number; // expires at (unix seconds)\n features?: Record<string, boolean>;\n};\n\nexport type LicenseFile = {\n key: string;\n payload: LicensePayload;\n verified: boolean;\n verified_at: string;\n};\n\n// NOTE: Public key only. No servers.\n// Replace this with your own RSA public key in PEM (SPKI) format.\nexport const DEFAULT_PUBLIC_KEY_PEM = `-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz1LLE/pXIx5TloDa0LAf\njg9NSIW6STWhsAFP2ZzXgpWoQ3cCmW6xcB/4QNEmPpGlfMWhyRfkxsdKuhnjUMTg\n8MpMAcbjjF8JrGS9iLnW4yrLm7jzsOcndjkGO7pH+32GopZk98dVzmIRPok2Je76\n3MQRaxLi0jWytaCmacEB4R7HyuquOQlHPg0vD9NOEwrC/+br2GdQbD1lKPyLeLv3\nRidwAs8Iw2xx5g8G+BsVSM/HRC3jQT5GynfnuDsvMHCvGLRct/76ajiR71/NFZEP\nZ7liILNnZzCTlKGGZfZmG70t+zkg8HKdpRuWy8rZ0DPWyQg5MKm6TZOMV6dC0Rpg\nDwIDAQAB\n-----END PUBLIC KEY-----`;\n\nfunction b64urlDecodeToBuffer(s: string): Buffer {\n const padLen = (4 - (s.length % 4)) % 4;\n const padded = s.replace(/-/g, '+').replace(/_/g, '/') + '='.repeat(padLen);\n return Buffer.from(padded, 'base64');\n}\n\nfunction safeJsonParse(buf: Buffer): any {\n const txt = buf.toString('utf8');\n return JSON.parse(txt);\n}\n\nexport function parseLicenseKey(key: string): { payload: LicensePayload; signature: Buffer; payloadB64Url: string } {\n const parts = String(key).trim().split('.');\n if (parts.length !== 2) throw new Error('invalid license key format: expected <payloadB64Url>.<sigB64Url>');\n const [payloadB64Url, sigB64Url] = parts;\n const payloadBuf = b64urlDecodeToBuffer(payloadB64Url);\n const sigBuf = b64urlDecodeToBuffer(sigB64Url);\n const payload = safeJsonParse(payloadBuf) as LicensePayload;\n return { payload, signature: sigBuf, payloadB64Url };\n}\n\nexport function verifyLicenseKey(key: string, publicKeyPem: string): { ok: boolean; reason?: string; payload?: LicensePayload } {\n let parsed: { payload: LicensePayload; signature: Buffer; payloadB64Url: string };\n try {\n parsed = parseLicenseKey(key);\n } catch (e: any) {\n return { ok: false, reason: e?.message || 'parse error' };\n }\n\n const now = Math.floor(Date.now() / 1000);\n if (typeof parsed.payload?.exp !== 'number' || parsed.payload.exp < now) {\n return { ok: false, reason: 'expired', payload: parsed.payload };\n }\n\n try {\n const verifier = crypto.createVerify('RSA-SHA256');\n verifier.update(parsed.payloadB64Url);\n verifier.end();\n const ok = verifier.verify(publicKeyPem, parsed.signature);\n if (!ok) return { ok: false, reason: 'bad signature', payload: parsed.payload };\n return { ok: true, payload: parsed.payload };\n } catch (e: any) {\n return { ok: false, reason: e?.message || 'verify error', payload: parsed.payload };\n }\n}\n\nexport function defaultLicensePath(cwd: string): string {\n return path.join(cwd, 'aiopt', 'license.json');\n}\n\nexport function writeLicenseFile(p: string, key: string, payload: LicensePayload, verified: boolean) {\n const out: LicenseFile = {\n key,\n payload,\n verified,\n verified_at: new Date().toISOString()\n };\n fs.mkdirSync(path.dirname(p), { recursive: true });\n fs.writeFileSync(p, JSON.stringify(out, null, 2));\n}\n\nexport function readLicenseFile(p: string): LicenseFile {\n return JSON.parse(fs.readFileSync(p, 'utf8')) as LicenseFile;\n}\n","import fs from 'fs';\nimport path from 'path';\n\ntype Sarif = {\n runs?: Array<{\n results?: Array<{\n level?: string;\n locations?: Array<{\n physicalLocation?: {\n artifactLocation?: { uri?: string };\n region?: { startLine?: number };\n };\n }>;\n }>;\n }>;\n};\n\nfunction parseFileUri(uri: string): string {\n // SARIF uses file:// URIs. Convert to local path when possible.\n // Keep stable output: prefer relative paths when under cwd.\n try {\n if (!uri) return '';\n const u = uri.replace(/^file:\\/\\//, '');\n // Windows: /C:/path\n const norm = u.replace(/^\\/+/, '').replace(/%20/g, ' ');\n return norm;\n } catch {\n return uri;\n }\n}\n\nexport type GateResult = {\n violations: number;\n top3: Array<{ file: string; line: number }>;\n};\n\nexport function runGate(outDir: string, cwd: string): GateResult {\n const sarifPath = path.join(outDir, 'aiopt.sarif');\n if (!fs.existsSync(sarifPath)) {\n return { violations: 0, top3: [] };\n }\n\n let sarif: Sarif;\n try {\n sarif = JSON.parse(fs.readFileSync(sarifPath, 'utf8'));\n } catch {\n return { violations: 0, top3: [] };\n }\n\n const results = sarif.runs?.[0]?.results || [];\n\n const viol = results.filter(r => {\n const lvl = String(r.level || '').toLowerCase();\n return lvl === 'warning' || lvl === 'error';\n });\n\n const locs: Array<{ file: string; line: number }> = [];\n for (const r of viol) {\n const loc = r.locations?.[0]?.physicalLocation;\n const uri = loc?.artifactLocation?.uri || '';\n const line = Number(loc?.region?.startLine || 1);\n let file = parseFileUri(uri);\n // Best-effort: make relative to cwd for readable PR comments.\n try {\n const abs = path.isAbsolute(file) ? file : path.resolve(file);\n file = path.relative(cwd, abs) || file;\n } catch {\n // ignore\n }\n locs.push({ file, line: Number.isFinite(line) && line > 0 ? line : 1 });\n }\n\n const top3 = locs.slice(0, 3);\n return { violations: viol.length, top3 };\n}\n\nexport function formatGateStdout(r: GateResult, outDir: string): { text: string; exitCode: 0 | 1 } {\n const lines: string[] = [];\n if (r.violations <= 0) {\n lines.push('OK: no policy violations');\n lines.push(`Artifacts: ${path.join(outDir, 'report.md')} | ${path.join(outDir, 'aiopt.sarif')}`);\n return { text: lines.join('\\n'), exitCode: 0 };\n }\n\n lines.push(`FAIL: policy violations=${r.violations}`);\n lines.push('Top3:');\n for (const x of r.top3) lines.push(`- ${x.file}:${x.line}`);\n lines.push('See artifacts: aiopt-output/report.md | aiopt-output/aiopt.sarif | aiopt-output/patches/');\n\n // Keep <= 10 lines guarantee.\n const text = lines.slice(0, 10).join('\\n');\n return { text, exitCode: 1 };\n}\n","import fs from 'fs';\nimport path from 'path';\nimport os from 'os';\nimport { execSync } from 'child_process';\n\nconst DEFAULT_EXCLUDES = new Set([\n '.git',\n 'node_modules',\n 'dist',\n 'aiopt-output',\n '.next',\n 'build',\n 'coverage'\n]);\n\nfunction isTextLike(p: string) {\n const ext = path.extname(p).toLowerCase();\n return ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'].includes(ext);\n}\n\nfunction walk(root: string, out: string[]) {\n const items = fs.readdirSync(root, { withFileTypes: true });\n for (const it of items) {\n // skip hidden dirs/files and common build folders\n if (it.name.startsWith('.')) continue;\n if (DEFAULT_EXCLUDES.has(it.name)) continue;\n const full = path.join(root, it.name);\n if (it.isDirectory()) walk(full, out);\n else out.push(full);\n }\n}\n\nfunction insertModelConst(content: string): { changed: boolean; next: string } {\n if (/\\bAIOPT_MODEL\\b/.test(content)) return { changed: false, next: content };\n if (!/\\bprocess\\.env\\.AIOPT_MODEL\\b/.test(content)) {\n // We'll still allow override by injecting a const that reads env.\n }\n const line = \"const AIOPT_MODEL = process.env.AIOPT_MODEL || 'gpt-5.2-mini';\";\n\n const lines = content.split(/\\r?\\n/);\n let i = 0;\n // Skip shebang\n if (lines[0] && lines[0].startsWith('#!')) i++;\n // Skip import/require headers\n while (i < lines.length) {\n const t = lines[i].trim();\n if (t.startsWith('import ')) { i++; continue; }\n if (t.startsWith('const ') && t.includes(\"require(\")) { i++; continue; }\n if (t === '' || t.startsWith('//') || t.startsWith('/*')) { i++; continue; }\n break;\n }\n lines.splice(i, 0, line, '');\n return { changed: true, next: lines.join('\\n') };\n}\n\nfunction applyRetryCap(content: string): { changed: boolean; next: string } {\n let changed = false;\n let next = content;\n\n // Replace maxRetries: N (N>=4) -> 3\n next = next.replace(/\\b(maxRetries|maximumRetries|max_attempts|attempts)\\s*:\\s*(\\d+)\\b/gi, (m, key, num) => {\n const n = Number(num);\n if (!Number.isFinite(n) || n < 4) return m;\n changed = true;\n return `${key}: 3`;\n });\n\n // Replace retry: { retries: N } etc\n next = next.replace(/\\b(retries)\\s*:\\s*(\\d+)\\b/gi, (m, key, num) => {\n const n = Number(num);\n if (!Number.isFinite(n) || n < 4) return m;\n changed = true;\n return `${key}: 3`;\n });\n\n return { changed, next };\n}\n\nfunction applyModelRouting(content: string): { changed: boolean; next: string } {\n // Only target obvious \"model: AIOPT_MODEL\" patterns.\n let changed = false;\n let next = content;\n\n const re = /(\\bmodel\\s*[:=]\\s*)(['\"])gpt-5\\.2\\2/g;\n if (re.test(next)) {\n // ensure AIOPT_MODEL const exists\n const ins = insertModelConst(next);\n next = ins.next;\n\n next = next.replace(re, (_m, prefix) => {\n changed = true;\n return `${prefix}AIOPT_MODEL`;\n });\n\n // Also handle gpt-5.2-codex style names if present\n const re2 = /(\\bmodel\\s*[:=]\\s*)(['\"])openai-codex\\/gpt-5\\.2\\2/g;\n next = next.replace(re2, (_m, prefix) => {\n changed = true;\n // Keep provider prefix if caller expects it; allow override still.\n return `${prefix}(process.env.AIOPT_MODEL_FULL || 'openai-codex/gpt-5.2-mini')`;\n });\n }\n\n return { changed, next };\n}\n\nfunction tmpFilePath(original: string) {\n const base = path.basename(original);\n const rand = Math.random().toString(16).slice(2);\n return path.join(os.tmpdir(), `aiopt-fix-${base}-${rand}`);\n}\n\nfunction diffNoIndex(oldPath: string, newPath: string): string {\n try {\n // --no-index works even outside git repos.\n return execSync(`git diff --no-index -- ${JSON.stringify(oldPath)} ${JSON.stringify(newPath)}`, {\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'pipe']\n });\n } catch (e: any) {\n // git diff returns exit code 1 when diff exists; stdout is still present.\n const out = String(e?.stdout || '');\n return out;\n }\n}\n\nfunction normalizePatchPaths(diffText: string, rel: string): string {\n // Make patch apply-able inside the repo by rewriting file paths to the repo-relative path.\n // Convert:\n // diff --git a/<anything> b/<anything>\n // --- a/<anything>\n // +++ b/<anything>\n // into:\n // diff --git a/<rel> b/<rel>\n // --- a/<rel>\n // +++ b/<rel>\n // This keeps hunks intact.\n const raw = diffText.split(/\\r?\\n/);\n const lines: string[] = [];\n for (let i = 0; i < raw.length; i++) {\n const line = raw[i];\n // Avoid noisy mode diffs; they cause warnings and are not essential.\n if (line.startsWith('old mode ') || line.startsWith('new mode ')) continue;\n\n if (line.startsWith('diff --git ')) {\n lines.push(`diff --git a/${rel} b/${rel}`);\n continue;\n }\n if (line.startsWith('--- ')) {\n lines.push(`--- a/${rel}`);\n continue;\n }\n if (line.startsWith('+++ ')) {\n lines.push(`+++ b/${rel}`);\n continue;\n }\n lines.push(line);\n }\n return lines.join('\\n');\n}\n\nexport type FixOptions = {\n outDir: string;\n apply: boolean;\n};\n\nexport function runFix(cwd: string, opts: FixOptions) {\n const files: string[] = [];\n walk(cwd, files);\n\n const patches: string[] = [];\n const changedFiles: string[] = [];\n\n for (const file of files) {\n if (!isTextLike(file)) continue;\n\n let st: fs.Stats;\n try { st = fs.statSync(file); } catch { continue; }\n if (!st.isFile()) continue;\n if (st.size > 1024 * 1024) continue;\n\n let content = '';\n try { content = fs.readFileSync(file, 'utf8'); } catch { continue; }\n\n // Apply transforms (two required types):\n // 1) retry cap\n // 2) model routing (cheap default + env override)\n const r1 = applyRetryCap(content);\n const r2 = applyModelRouting(r1.next);\n\n const next = r2.next;\n if (next === content) continue;\n\n const tmp = tmpFilePath(file);\n fs.writeFileSync(tmp, next);\n\n const rel = path.relative(cwd, file).replace(/\\\\/g, '/');\n const d0 = diffNoIndex(file, tmp);\n const d = normalizePatchPaths(d0, rel);\n if (d && d.trim().length > 0) {\n patches.push(d);\n changedFiles.push(rel);\n }\n\n try { fs.unlinkSync(tmp); } catch {}\n\n // Keep patch sizes bounded\n if (patches.join('\\n').length > 500_000) break;\n }\n\n fs.mkdirSync(opts.outDir, { recursive: true });\n const patchPath = path.join(opts.outDir, 'aiopt.patch');\n\n const header = [\n '# AIOpt patch (generated)',\n '# - retry cap: reduce high retry/attempt counts to 3',\n '# - model routing: cheap default via AIOPT_MODEL env override',\n ''\n ].join('\\n');\n\n fs.writeFileSync(patchPath, header + patches.join('\\n'));\n\n if (opts.apply) {\n // Only attempt apply inside a git working tree.\n try {\n const inside = execSync('git rev-parse --is-inside-work-tree', { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim();\n if (inside !== 'true') {\n return { ok: false, applied: false, patchPath, changedFiles, hint: 'not inside a git work tree (run from your repo root, or omit --apply and apply manually)' };\n }\n } catch {\n return { ok: false, applied: false, patchPath, changedFiles, hint: 'git not available or not a git repo (omit --apply and apply manually)' };\n }\n\n try {\n execSync(`git apply ${JSON.stringify(patchPath)}`, { stdio: 'inherit' });\n return { ok: true, applied: true, patchPath, changedFiles };\n } catch {\n return { ok: false, applied: false, patchPath, changedFiles, hint: 'git apply failed. Ensure a clean working tree, then re-run; or open aiopt.patch and apply manually.' };\n }\n }\n\n return { ok: true, applied: false, patchPath, changedFiles };\n}\n","import { RateTable, UsageEvent } from './types';\nimport { analyze } from './scan';\nimport { costOfEvent } from './cost';\n\nexport type GuardInput = {\n // Required. Historical usage for comparison.\n baselineEvents: UsageEvent[];\n\n // Optional. If provided, guard compares two *actual* log sets.\n // When set, candidate transform knobs (model/context/retries multipliers) are ignored.\n candidateEvents?: UsageEvent[];\n\n candidate: {\n provider?: string;\n model?: string;\n contextMultiplier?: number; // multiplies input_tokens\n outputMultiplier?: number; // multiplies output_tokens\n retriesDelta?: number; // adds to retries\n callMultiplier?: number; // multiplies call volume\n budgetMonthlyUsd?: number; // absolute budget gate\n };\n};\n\nexport type GuardResult = {\n exitCode: 0 | 2 | 3;\n message: string;\n};\n\nfunction accidentRiskFromMonthly(monthly: number): 'Low' | 'Medium' | 'High' {\n if (!Number.isFinite(monthly)) return 'Medium';\n if (monthly >= 100) return 'High';\n if (monthly >= 10) return 'Medium';\n return 'Low';\n}\n\nfunction round2(n: number) {\n return Math.round(n * 100) / 100;\n}\n\nfunction windowDays(events: UsageEvent[]): number {\n let days = 1;\n try {\n const times = events\n .map(e => Date.parse(e.ts))\n .filter(t => Number.isFinite(t))\n .sort((a, b) => a - b);\n if (times.length >= 2) {\n const spanMs = Math.max(0, times[times.length - 1] - times[0]);\n const spanDays = spanMs / (1000 * 60 * 60 * 24);\n days = Math.max(1, spanDays);\n }\n } catch {\n days = 1;\n }\n return days;\n}\n\nfunction monthEstimate(delta: number, events: UsageEvent[]) {\n // Convert observed delta (over the sample window) into a monthly estimate.\n const days = windowDays(events);\n return (delta * 30) / days;\n}\n\nfunction applyCandidate(events: UsageEvent[], cand: GuardInput['candidate']): UsageEvent[] {\n const ctxM = cand.contextMultiplier ?? 1;\n const outM = cand.outputMultiplier ?? 1;\n const rDelta = cand.retriesDelta ?? 0;\n\n return events.map(ev => ({\n ...ev,\n provider: cand.provider ? String(cand.provider).toLowerCase() : ev.provider,\n model: cand.model ? String(cand.model) : ev.model,\n input_tokens: Math.max(0, Math.round((ev.input_tokens || 0) * ctxM)),\n output_tokens: Math.max(0, Math.round((ev.output_tokens || 0) * outM)),\n retries: Math.max(0, Math.round((ev.retries || 0) + rDelta)),\n // clear billed_cost so pricing recalculates for new model/provider\n billed_cost: undefined\n }));\n}\n\nfunction confidenceFromChange(cand: GuardInput['candidate']): { level: 'High'|'Medium'|'Low'; reasons: string[] } {\n const reasons: string[] = [];\n\n if (cand.retriesDelta && cand.retriesDelta !== 0) reasons.push('retries change');\n if (cand.model) reasons.push('model change');\n if (cand.provider) reasons.push('provider change');\n if (cand.contextMultiplier && cand.contextMultiplier !== 1) reasons.push('context length change');\n if (cand.outputMultiplier && cand.outputMultiplier !== 1) reasons.push('output length change');\n\n // Spec rule:\n // High: retries/failed/dup calls (we only model retries here)\n // Medium: model/provider change\n // Low: context trimming / prompt structure\n if (cand.retriesDelta && cand.retriesDelta !== 0) return { level: 'High', reasons };\n if (cand.model || cand.provider) return { level: 'Medium', reasons };\n if ((cand.contextMultiplier && cand.contextMultiplier !== 1) || (cand.outputMultiplier && cand.outputMultiplier !== 1)) {\n return { level: 'Low', reasons };\n }\n return { level: 'Medium', reasons: reasons.length ? reasons : ['unknown change'] };\n}\n\nfunction assessDataQuality(baselineEvents: UsageEvent[], base: ReturnType<typeof analyze>) {\n const reasons: string[] = [];\n\n // ts span\n const times = baselineEvents\n .map(e => Date.parse(e.ts))\n .filter(t => Number.isFinite(t))\n .sort((a, b) => a - b);\n if (times.length < 2) reasons.push('ts span unknown');\n else {\n const spanDays = Math.max(0, (times[times.length - 1] - times[0]) / (1000 * 60 * 60 * 24));\n if (spanDays < 0.25) reasons.push('ts span too short');\n }\n\n // feature tag coverage\n const missingFt = baselineEvents.filter(e => !e.feature_tag && !(e.meta && (e.meta as any).feature_tag)).length;\n if (missingFt / Math.max(1, baselineEvents.length) > 0.2) reasons.push('feature_tag missing >20%');\n\n // unknown model/provider\n const unknown = (base.analysis.unknown_models || []).length;\n if (unknown / Math.max(1, baselineEvents.length) > 0.2) reasons.push('unknown model/provider >20%');\n\n // Map to a confidence penalty.\n let penalty: 'none'|'low'|'medium' = 'none';\n if (reasons.length >= 2) penalty = 'medium';\n else if (reasons.length === 1) penalty = 'low';\n\n return { reasons, penalty };\n}\n\nfunction degrade(level: 'High'|'Medium'|'Low', penalty: 'none'|'low'|'medium'): 'High'|'Medium'|'Low' {\n if (penalty === 'none') return level;\n if (penalty === 'low') return level === 'High' ? 'Medium' : 'Low';\n // medium\n return 'Low';\n}\n\nexport function runGuard(rt: RateTable, input: GuardInput): GuardResult {\n if (!input.baselineEvents || input.baselineEvents.length === 0) {\n const conf = { level: 'Low' as const, reasons: ['baseline empty'] };\n const msg = [\n 'FAIL: baseline usage is empty (need aiopt-output/usage.jsonl)',\n 'Impact (monthly est): +$0 (insufficient baseline)',\n `Accident risk: ${accidentRiskFromMonthly(100)}`,\n `Confidence: ${conf.level} (${(conf.reasons.length ? conf.reasons.join(', ') : 'baseline empty')})`,\n 'Recommendation: run the wrapper to collect baseline usage before using guard.'\n ].join('\\n');\n return { exitCode: 3, message: msg };\n }\n\n // For fair comparison, ignore billed_cost/cost_usd and recompute both sides from rate table.\n const baselineEvents = input.baselineEvents.map(e => ({ ...e, billed_cost: undefined }));\n const base = analyze(rt, baselineEvents);\n\n const candidateEvents = (input.candidateEvents && input.candidateEvents.length > 0)\n ? input.candidateEvents.map(e => ({ ...e, billed_cost: undefined }))\n : applyCandidate(baselineEvents, input.candidate);\n\n const cand = analyze(rt, candidateEvents);\n\n const baseCost = base.analysis.total_cost;\n let candCost = cand.analysis.total_cost;\n\n // call volume multiplier (traffic spike)\n const callMult = input.candidate.callMultiplier && input.candidate.callMultiplier > 0 ? input.candidate.callMultiplier : 1;\n if (callMult !== 1) {\n candCost = candCost * callMult;\n }\n\n // attempt-log baseline: retriesDelta should be interpreted as \"extra attempts\".\n const attemptLog = baselineEvents.some(e => (e.trace_id && String(e.trace_id).length > 0) || (e.attempt !== undefined && Number(e.attempt) > 0));\n if (attemptLog && input.candidate.retriesDelta && input.candidate.retriesDelta > 0) {\n // More accurate deterministic approximation:\n // - If baseline already has retry attempts (attempt>=2), use their average cost as retry unit.\n // - Else fall back to avg baseline attempt cost.\n let retryUnit = 0;\n let retryCount = 0;\n for (const ev of baselineEvents) {\n const attempt = Number(ev.attempt || 1);\n if (attempt >= 2) {\n retryUnit += costOfEvent(rt, ev).cost;\n retryCount += 1;\n }\n }\n if (retryCount > 0) {\n retryUnit = retryUnit / retryCount;\n } else {\n retryUnit = baseCost / Math.max(1, baselineEvents.length);\n }\n candCost += retryUnit * input.candidate.retriesDelta;\n }\n\n const delta = candCost - baseCost;\n\n const days = windowDays(baselineEvents);\n const baselineMonthly = (baseCost * 30) / days;\n const candidateMonthly = (candCost * 30) / days;\n\n const changeConf = input.candidateEvents\n ? ({ level: 'High' as const, reasons: ['actual logs diff (--baseline/--candidate)'] })\n : confidenceFromChange(input.candidate);\n\n const dq = assessDataQuality(baselineEvents, base);\n const conf = { level: degrade(changeConf.level, dq.penalty), reasons: [...changeConf.reasons, ...dq.reasons.map(r => `data: ${r}`)] };\n\n // Guard logic:\n // - Warning if delta > 0 and monthEstimate(delta) >= $10\n // - Fail if delta > 0 and monthEstimate(delta) >= $100 (merge-blocking)\n const monthly = monthEstimate(Math.max(0, delta), baselineEvents);\n const monthlyRounded = round2(monthly);\n\n let exitCode: 0 | 2 | 3 = 0;\n let headline = 'OK: no cost accident risk detected';\n\n if (monthly >= 100) { exitCode = 3; headline = 'FAIL: high risk of LLM cost accident'; }\n else if (monthly >= 10) { exitCode = 2; headline = 'WARN: possible LLM cost accident'; }\n\n // Budget gate: absolute monthly cost ceiling for candidate.\n const budget = input.candidate.budgetMonthlyUsd;\n if (budget && Number.isFinite(budget) && budget > 0 && candidateMonthly > budget) {\n exitCode = 3;\n headline = 'FAIL: candidate exceeds monthly budget';\n }\n\n const reasons = conf.reasons.length ? conf.reasons.join(', ') : 'n/a';\n\n function topCauses(): string[] {\n const out: string[] = [];\n\n // transform mode causes\n if (!input.candidateEvents) {\n if (callMult !== 1) out.push('traffic spike (call-mult)');\n if (input.candidate.retriesDelta && input.candidate.retriesDelta !== 0) out.push('retry spike (retries-delta)');\n if (input.candidate.model || input.candidate.provider) out.push('model/provider change');\n if (input.candidate.contextMultiplier && input.candidate.contextMultiplier !== 1) out.push('context length change');\n if (input.candidate.outputMultiplier && input.candidate.outputMultiplier !== 1) out.push('output length change');\n } else {\n // diff mode heuristic causes\n if (candidateEvents.length !== baselineEvents.length) out.push('traffic/call volume changed');\n const bTop = base.analysis.by_model_top?.[0]?.key;\n const cTop = cand.analysis.by_model_top?.[0]?.key;\n if (bTop && cTop && bTop !== cTop) out.push('model mix changed');\n if ((cand.savings?.retry_waste_usd || 0) > (base.savings?.retry_waste_usd || 0)) out.push('retry waste increased');\n }\n\n // budget\n if (budget && Number.isFinite(budget) && budget > 0) out.push(`budget gate: $${round2(budget)}/mo`);\n\n return out.slice(0, 3);\n }\n\n const causes = topCauses();\n\n function sumTokens(events: UsageEvent[]) {\n let input = 0;\n let output = 0;\n for (const e of events) {\n input += Number(e.input_tokens || 0);\n output += Number(e.output_tokens || 0);\n }\n return { input, output, total: input + output };\n }\n\n function topDeltas(kind: 'model' | 'feature') {\n const b = kind === 'model' ? (base.analysis.by_model_top || []) : (base.analysis.by_feature_top || []);\n const c = kind === 'model' ? (cand.analysis.by_model_top || []) : (cand.analysis.by_feature_top || []);\n const bm = new Map<string, { cost: number; events: number }>();\n const cm = new Map<string, { cost: number; events: number }>();\n for (const x of b) bm.set(String(x.key), { cost: Number(x.cost || 0), events: Number(x.events || 0) });\n for (const x of c) cm.set(String(x.key), { cost: Number(x.cost || 0), events: Number(x.events || 0) });\n const keys = new Set<string>([...bm.keys(), ...cm.keys()]);\n const deltas = [...keys].map(k => {\n const bb = bm.get(k) || { cost: 0, events: 0 };\n const cc = cm.get(k) || { cost: 0, events: 0 };\n return { key: k, deltaCost: cc.cost - bb.cost, deltaEvents: cc.events - bb.events };\n });\n return deltas\n .sort((a, b2) => Math.abs(b2.deltaCost) - Math.abs(a.deltaCost))\n .slice(0, 3)\n .filter(x => Math.abs(x.deltaCost) > 1e-9);\n }\n\n const tokB = sumTokens(baselineEvents);\n const tokC = sumTokens(candidateEvents);\n\n const msg = [\n headline,\n `Summary: baseline=$${round2(baseCost)} → candidate=$${round2(candCost)} (Δ=$${round2(delta)})`,\n `Monthly est: baseline=$${round2(baselineMonthly)} → candidate=$${round2(candidateMonthly)}${budget ? ` (budget=$${round2(budget)})` : ''}`,\n input.candidateEvents ? `Tokens: input ${tokB.input}→${tokC.input} (Δ ${tokC.input - tokB.input}), output ${tokB.output}→${tokC.output} (Δ ${tokC.output - tokB.output})` : null,\n callMult !== 1 ? `Call volume multiplier: x${callMult}` : null,\n causes.length ? `Top causes: ${causes.join(' | ')}` : null,\n input.candidateEvents ? (topDeltas('model').length ? `Top model deltas: ${topDeltas('model').map(x => `${x.key} (${round2(x.deltaCost)})`).join(' | ')}` : null) : null,\n input.candidateEvents ? (topDeltas('feature').length ? `Top feature deltas: ${topDeltas('feature').map(x => `${x.key} (${round2(x.deltaCost)})`).join(' | ')}` : null) : null,\n `Impact (monthly est): +$${monthlyRounded}`,\n `Accident risk: ${accidentRiskFromMonthly(monthly)}`,\n `Confidence: ${conf.level} (${reasons})`,\n 'Recommendation: review model/provider/retry/context changes before deploy.'\n ].filter(Boolean).join('\\n');\n\n return { exitCode, message: msg };\n}\n","import fs from 'fs';\nimport path from 'path';\nimport os from 'os';\n\nexport type UsageEventV2 = {\n ts: string;\n provider: string;\n model: string;\n input_tokens: number;\n output_tokens: number;\n retries: number;\n status: string;\n feature_tag?: string;\n // optional\n trace_id?: string;\n request_id?: string;\n attempt?: number;\n endpoint?: string;\n cost_usd?: number;\n meta?: Record<string, any>;\n};\n\nfunction exists(p: string) {\n try { return fs.existsSync(p); } catch { return false; }\n}\n\nfunction safeReadJsonl(p: string): any[] {\n const out: any[] = [];\n try {\n const txt = fs.readFileSync(p, 'utf8');\n for (const line of txt.split(/\\r?\\n/)) {\n if (!line.trim()) continue;\n try { out.push(JSON.parse(line)); } catch {}\n }\n } catch {}\n return out;\n}\n\nfunction listJsonlFiles(dir: string): string[] {\n const out: string[] = [];\n try {\n for (const name of fs.readdirSync(dir)) {\n const full = path.join(dir, name);\n let st: fs.Stats;\n try { st = fs.statSync(full); } catch { continue; }\n if (st.isFile() && name.endsWith('.jsonl')) out.push(full);\n }\n } catch {}\n return out;\n}\n\nfunction findOpenClawSessionLogs(): string[] {\n // OpenClaw stores per-session JSONL logs under ~/.openclaw/agents/*/sessions/*.jsonl\n const home = os.homedir();\n const root = path.join(home, '.openclaw', 'agents');\n if (!exists(root)) return [];\n\n const found: string[] = [];\n let agents: string[] = [];\n try { agents = fs.readdirSync(root); } catch { agents = []; }\n\n for (const a of agents) {\n const sessDir = path.join(root, a, 'sessions');\n if (!exists(sessDir)) continue;\n for (const f of listJsonlFiles(sessDir)) found.push(f);\n }\n return found;\n}\n\nfunction parseOpenClawSessionFile(p: string): UsageEventV2[] {\n const rows = safeReadJsonl(p);\n const events: UsageEventV2[] = [];\n\n for (const r of rows) {\n if (r && r.type === 'message' && r.message && typeof r.message === 'object') {\n const m = r.message;\n const u = m.usage;\n if (!u) continue;\n\n // Expected shape observed:\n // usage: { input, output, cacheRead, cacheWrite, totalTokens, cost: { total, input, output, cacheRead, cacheWrite } }\n const input = Number(u.input ?? u.prompt ?? u.prompt_tokens ?? 0);\n const output = Number(u.output ?? u.completion ?? u.completion_tokens ?? 0);\n const costTotal = u.cost && typeof u.cost === 'object' ? Number(u.cost.total ?? u.costTotal ?? u.cost_usd) : undefined;\n\n // OpenClaw stores timestamps as ms (number-like string). Normalize to ISO for downstream tools.\n let tsRaw: any = m.timestamp || r.timestamp || new Date().toISOString();\n let ts = String(tsRaw);\n if (String(tsRaw).match(/^\\d{10,}$/)) {\n try { ts = new Date(Number(tsRaw)).toISOString(); } catch {}\n }\n const provider = String(m.provider || r.provider || 'openclaw');\n const model = String(m.model || r.modelId || 'unknown');\n\n if (!Number.isFinite(input) && !Number.isFinite(output) && !Number.isFinite(costTotal as any)) continue;\n\n events.push({\n ts,\n provider,\n model,\n input_tokens: Number.isFinite(input) ? input : 0,\n output_tokens: Number.isFinite(output) ? output : 0,\n retries: 0,\n status: 'ok',\n cost_usd: Number.isFinite(costTotal as any) ? Number(costTotal) : undefined,\n meta: {\n source: 'openclaw-session',\n session_file: p,\n cache_read_tokens: u.cacheRead,\n cache_write_tokens: u.cacheWrite,\n total_tokens: u.totalTokens\n }\n });\n }\n }\n\n return events;\n}\n\nfunction stableKey(e: UsageEventV2) {\n // best-effort de-dup key\n return `${e.ts}|${e.provider}|${e.model}|${e.input_tokens}|${e.output_tokens}|${e.cost_usd ?? ''}`;\n}\n\nexport type CollectResult = {\n outPath: string;\n sources: Array<{ name: string; files: number; events: number }>;\n eventsWritten: number;\n};\n\nexport function collectToUsageJsonl(outPath: string): CollectResult {\n const all: UsageEventV2[] = [];\n const sources: CollectResult['sources'] = [];\n\n // OpenClaw\n const ocFiles = findOpenClawSessionLogs();\n let ocEvents = 0;\n for (const f of ocFiles) {\n const evs = parseOpenClawSessionFile(f);\n ocEvents += evs.length;\n all.push(...evs);\n }\n sources.push({ name: 'openclaw', files: ocFiles.length, events: ocEvents });\n\n // Future: cursor, claude-code, etc. (best-effort adapters)\n\n // De-dup + sort by ts\n const seen = new Set<string>();\n const uniq: UsageEventV2[] = [];\n for (const e of all) {\n const k = stableKey(e);\n if (seen.has(k)) continue;\n seen.add(k);\n uniq.push(e);\n }\n uniq.sort((a, b) => Date.parse(a.ts) - Date.parse(b.ts));\n\n fs.mkdirSync(path.dirname(outPath), { recursive: true });\n const lines = uniq.map(e => JSON.stringify(e)).join('\\n') + (uniq.length ? '\\n' : '');\n fs.writeFileSync(outPath, lines);\n\n return { outPath, sources, eventsWritten: uniq.length };\n}\n","import http from 'http';\nimport fs from 'fs';\nimport path from 'path';\nimport { collectToUsageJsonl } from './collect';\nimport { analyze, writeOutputs } from './scan';\nimport { readJsonl, isCsvPath, readCsv } from './io';\nimport { runGuard } from './guard';\n\nexport async function startDashboard(cwd: string, opts: { port: number }) {\n const host = '127.0.0.1';\n const port = opts.port || 3010;\n\n const outDir = path.join(cwd, 'aiopt-output');\n const file = (name: string) => path.join(outDir, name);\n\n // Auto-collect (best-effort): if usage.jsonl is missing, try to derive it from known local sources.\n let lastCollect: null | { ts: string; outPath: string; sources: any; eventsWritten: number } = null;\n let lastCollectError: null | string = null;\n\n // Auto-generate (best-effort): if scan/guard outputs are missing, generate them so the dashboard is never empty.\n let lastAutoGen: null | { ts: string; did: string[] } = null;\n let lastAutoGenError: null | string = null;\n\n function ensureUsageFile() {\n try {\n const usagePath = file('usage.jsonl');\n if (fs.existsSync(usagePath)) return;\n const r = collectToUsageJsonl(usagePath);\n lastCollect = { ts: new Date().toISOString(), outPath: r.outPath, sources: r.sources, eventsWritten: r.eventsWritten };\n lastCollectError = null;\n } catch (e: any) {\n lastCollectError = String(e?.message || e || 'collect failed');\n }\n }\n\n function loadRateTable(): any {\n // dist/cli.js lives under dist; rates/ is at repo root.\n const p = path.join(__dirname, '..', 'rates', 'rate_table.json');\n return JSON.parse(fs.readFileSync(p, 'utf8'));\n }\n\n function readEvents(usagePath: string): any[] {\n if (!fs.existsSync(usagePath)) return [];\n return isCsvPath(usagePath) ? readCsv(usagePath) : readJsonl(usagePath);\n }\n\n function ensureScanAndGuard() {\n // Resource-friendly: only run if outputs are missing.\n // Never auto-runs network calls; only reads local files and writes local artifacts.\n const did: string[] = [];\n try {\n const usagePath = file('usage.jsonl');\n const rt = loadRateTable();\n\n const needScan = !fs.existsSync(file('report.json')) || !fs.existsSync(file('report.md'));\n if (needScan) {\n const events = readEvents(usagePath);\n const { analysis, savings, policy, meta } = analyze(rt, events);\n policy.generated_from.input = usagePath;\n writeOutputs(outDir, analysis, savings, policy, { ...meta, cwd, cliVersion: 'dashboard' });\n did.push('scan');\n }\n\n const needGuard = !fs.existsSync(file('guard-last.txt')) || !fs.existsSync(file('guard-last.json'));\n if (needGuard) {\n const events = readEvents(usagePath);\n const r = runGuard(rt, { baselineEvents: events, candidate: {} });\n\n const ts = new Date().toISOString();\n fs.writeFileSync(file('guard-last.txt'), r.message);\n fs.writeFileSync(file('guard-last.json'), JSON.stringify({ ts, exitCode: r.exitCode }, null, 2));\n fs.appendFileSync(file('guard-history.jsonl'), JSON.stringify({ ts, exitCode: r.exitCode, mode: 'dashboard', baseline: usagePath, candidate: null }) + '\\n');\n did.push('guard');\n }\n\n if (did.length) lastAutoGen = { ts: new Date().toISOString(), did };\n lastAutoGenError = null;\n } catch (e: any) {\n lastAutoGenError = String(e?.message || e || 'auto-gen failed');\n }\n }\n\n ensureUsageFile();\n ensureScanAndGuard();\n\n function readOrNull(p: string) {\n try {\n if (!fs.existsSync(p)) return null;\n return fs.readFileSync(p, 'utf8');\n } catch {\n return null;\n }\n }\n\n function statOrNull(p: string): null | { size: number; mtimeMs: number } {\n try {\n const st = fs.statSync(p);\n return { size: st.size, mtimeMs: st.mtimeMs };\n } catch {\n return null;\n }\n }\n\n const indexHtml = `<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\"/>\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"/>\n <title>AIOpt Local Dashboard</title>\n <style>\n :root{\n --bg:#070b16; --card:#0b1222; --card2:#0e1730; --txt:#e7eaf2; --muted:#a3acc2;\n --border:rgba(255,255,255,.10);\n --ok:#34d399; --warn:#fbbf24; --fail:#fb7185;\n --shadow:0 18px 70px rgba(0,0,0,.35);\n }\n *{box-sizing:border-box}\n body{margin:0; font-family: ui-sans-serif,system-ui,-apple-system,Segoe UI,Roboto; background:var(--bg); color:var(--txt)}\n a{color:#bfffe3; text-decoration:none} a:hover{text-decoration:underline}\n .wrap{max-width:1100px; margin:0 auto; padding:18px}\n .top{display:flex; align-items:center; justify-content:space-between; gap:10px; flex-wrap:wrap}\n .h1{font-size:22px; font-weight:950; letter-spacing:-.02em}\n .pill{display:inline-flex; align-items:center; gap:8px; padding:7px 10px; border-radius:999px; border:1px solid var(--border);\n background:rgba(255,255,255,.03); color:var(--muted); font-size:12px; line-height:1}\n .dot{width:8px;height:8px;border-radius:99px;background:linear-gradient(90deg,#60a5fa,#34d399)}\n\n .grid{display:grid; grid-template-columns:repeat(12,1fr); gap:12px; margin-top:12px}\n .card{grid-column: span 12; background:linear-gradient(180deg, rgba(255,255,255,.03), rgba(255,255,255,0)), var(--card);\n border:1px solid var(--border); border-radius:18px; padding:14px; box-shadow: var(--shadow)}\n @media(min-width: 920px){\n .c6{grid-column: span 6}\n .c4{grid-column: span 4}\n .c8{grid-column: span 8}\n }\n\n .k{padding:2px 6px; border-radius:8px; border:1px solid var(--border); font-family: ui-monospace; font-size:12px; color:#d7def2; background:rgba(255,255,255,.03)}\n .muted{color:var(--muted)}\n .row{display:flex; gap:10px; flex-wrap:wrap; align-items:center}\n\n .badge{display:inline-flex; align-items:center; gap:8px; padding:8px 10px; border-radius:14px; border:1px solid var(--border);\n background:rgba(255,255,255,.03); font-weight:900}\n .badge.ok{border-color:rgba(52,211,153,.35)}\n .badge.warn{border-color:rgba(251,191,36,.35)}\n .badge.fail{border-color:rgba(251,113,133,.35)}\n .badge .b{width:10px;height:10px;border-radius:99px}\n .badge.ok .b{background:var(--ok)}\n .badge.warn .b{background:var(--warn)}\n .badge.fail .b{background:var(--fail)}\n\n pre{margin:0; white-space:pre-wrap; word-break:break-word; background: rgba(3,6,14,.65);\n border:1px solid rgba(255,255,255,.12);\n padding:12px; border-radius:14px;\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\"; font-size:13px; line-height:1.55}\n\n .bars{display:flex; flex-direction:column; gap:8px; margin-top:8px}\n .bar{display:grid; grid-template-columns: 1fr 64px; gap:10px; align-items:center}\n .track{height:10px; border-radius:999px; background:rgba(255,255,255,.08); overflow:hidden; border:1px solid rgba(255,255,255,.10)}\n .fill{height:100%; border-radius:999px; background:linear-gradient(90deg,#60a5fa,#34d399)}\n .label{font-size:13px}\n .val{font-family: ui-monospace; font-size:12px; color:#d7def2; text-align:right}\n\n .mini{font-size:12px; color:var(--muted)}\n </style>\n</head>\n<body>\n <div class=\"wrap\">\n <div class=\"top\">\n <div>\n <div class=\"h1\">AIOpt Local Dashboard</div>\n <div class=\"mini\" id=\"baseDir\">base: —</div>\n <div class=\"mini\" id=\"missingHint\" style=\"margin-top:4px\">checking files…</div>\n </div>\n <div class=\"pill\"><span class=\"dot\"></span> local-only · reads <span class=\"k\">./aiopt-output</span> · <span id=\"live\" class=\"muted\">live: off</span>\n <span class=\"muted\">·</span>\n <button id=\"btnRefresh\" style=\"all:unset; cursor:pointer; padding:2px 8px; border:1px solid rgba(255,255,255,.16); border-radius:999px; background:rgba(255,255,255,.04); font-size:12px\">Refresh</button>\n <button id=\"btnLive\" style=\"all:unset; cursor:pointer; padding:2px 8px; border:1px solid rgba(255,255,255,.16); border-radius:999px; background:rgba(255,255,255,.04); font-size:12px\">Live: Off</button>\n </div>\n </div>\n\n <div class=\"grid\">\n <div class=\"card c6\">\n <div class=\"row\" style=\"justify-content:space-between\">\n <div style=\"font-weight:950\">Guard verdict</div>\n <div class=\"mini\" id=\"guardMeta\">—</div>\n </div>\n <div style=\"height:8px\"></div>\n <div id=\"guardBadge\" class=\"badge\"><span class=\"b\"></span><span id=\"guardBadgeText\">loading…</span></div>\n <div style=\"height:10px\"></div>\n <pre id=\"guard\">loading… (if this stays, it usually means required files are missing — see the top “missing” line)</pre>\n <div style=\"height:10px\"></div>\n <div class=\"row\">\n <a href=\"/api/guard-last.txt\" target=\"_blank\">raw txt</a>\n <span class=\"muted\">·</span>\n <a href=\"/api/guard-last.json\" target=\"_blank\">raw json</a>\n <span class=\"muted\">·</span>\n <a href=\"/api/guard-history.jsonl\" target=\"_blank\">history</a>\n </div>\n\n <div style=\"height:12px\"></div>\n <div style=\"font-weight:900\">Recent guard runs</div>\n <pre id=\"guardHist\" style=\"max-height:220px; overflow:auto\">loading…</pre>\n <div class=\"mini\" style=\"margin-top:8px\">\n Quick actions (copy/paste):\n <div style=\"margin-top:6px; display:flex; flex-wrap:wrap; gap:8px\">\n <span class=\"k\">aiopt quickstart --demo</span>\n <span class=\"k\">aiopt guard --help</span>\n <span class=\"k\">aiopt scan</span>\n </div>\n </div>\n </div>\n\n <div class=\"card c6\">\n <div class=\"row\" style=\"justify-content:space-between\">\n <div style=\"font-weight:950\">Scan summary</div>\n <div class=\"mini\"><a href=\"/api/report.json\" target=\"_blank\">report.json</a> · <a href=\"/api/report.md\" target=\"_blank\">report.md</a></div>\n </div>\n <div style=\"height:8px\"></div>\n <div class=\"row\">\n <div class=\"badge\" id=\"totalCostBadge\"><span class=\"b\" style=\"background:#60a5fa\"></span><span id=\"totalCost\">total: —</span></div>\n <div class=\"badge\" id=\"savingsBadge\"><span class=\"b\" style=\"background:#a78bfa\"></span><span id=\"savings\">savings: —</span></div>\n </div>\n\n <div style=\"height:12px\"></div>\n <div class=\"row\" style=\"justify-content:space-between\">\n <div style=\"font-weight:900\">Live usage (last 60m)</div>\n <div class=\"mini\"><a href=\"/api/usage.jsonl\" target=\"_blank\">usage.jsonl</a></div>\n </div>\n <div id=\"liveSvg\" style=\"margin-top:8px\"></div>\n <pre id=\"liveText\" style=\"margin-top:8px\">loading…</pre>\n\n <div style=\"height:12px\"></div>\n <div class=\"row\" style=\"justify-content:space-between\">\n <div style=\"font-weight:900\">Cost trend (last 7d)</div>\n <div class=\"mini\">(from usage.jsonl)</div>\n </div>\n <div id=\"trendSvg\" style=\"margin-top:8px\"></div>\n <pre id=\"trend\" style=\"margin-top:8px\">loading…</pre>\n\n <div style=\"height:12px\"></div>\n <div style=\"font-weight:900\">Cost by model</div>\n <div id=\"byModel\" class=\"bars\"></div>\n\n <div style=\"height:12px\"></div>\n <div style=\"font-weight:900\">Cost by feature</div>\n <div id=\"byFeature\" class=\"bars\"></div>\n\n <div style=\"height:10px\"></div>\n <div class=\"mini\" id=\"scanMeta\">—</div>\n </div>\n\n <div class=\"card\">\n <div class=\"row\" style=\"justify-content:space-between\">\n <div style=\"font-weight:950\">Latest report.md</div>\n <div class=\"mini\">Tip: run <span class=\"k\">aiopt scan</span> after collecting baseline</div>\n </div>\n <div style=\"height:8px\"></div>\n <pre id=\"scan\">loading…</pre>\n </div>\n </div>\n </div>\n\n<script>\nfunction money(x){\n if (x === null || x === undefined || Number.isNaN(Number(x))) return '—';\n return '$' + (Math.round(Number(x)*100)/100);\n}\nfunction renderBars(el, items){\n el.innerHTML='';\n if(!items || items.length===0){ el.innerHTML='<div class=\"mini\">(no data)</div>'; return; }\n const max = Math.max(...items.map(i=>Number(i.cost)||0), 0.000001);\n for(const it of items.slice(0,8)){\n const w = Math.max(2, Math.round(((Number(it.cost)||0)/max)*100));\n const row = document.createElement('div');\n row.className='bar';\n row.innerHTML =\n '<div>'+\n '<div class=\"label\">'+ String(it.key) +'</div>'+\n '<div class=\"track\"><div class=\"fill\" style=\"width:'+ w +'%\"></div></div>'+\n '</div>'+\n '<div class=\"val\">'+ money(it.cost) +'</div>';\n el.appendChild(row);\n }\n}\n\nlet __live = false;\nlet __tick = 0;\n\nasync function load(){\n __tick++;\n // If fetch hangs / fails, do not leave “loading…” forever.\n const timer = setTimeout(()=>{\n const el = document.getElementById('missingHint');\n if(el && el.textContent && el.textContent.includes('checking')){\n el.textContent = 'still loading… (if this doesn\\'t change, refresh. If it persists: run aiopt quickstart --demo or aiopt scan)';\n }\n }, 1500);\n\n let meta = null;\n try{\n meta = await fetch('/api/_meta', { cache: 'no-store' }).then(r=>r.ok?r.json():null);\n }catch{}\n clearTimeout(timer);\n\n if(meta && meta.baseDir){\n document.getElementById('baseDir').textContent = 'base: ' + meta.baseDir;\n }\n\n const miss = (meta && meta.missing) ? meta.missing : null;\n const hint = document.getElementById('missingHint');\n if(miss && miss.length){\n hint.textContent = 'missing: ' + miss.join(', ') + ' → not broken. Run: aiopt quickstart --demo (or aiopt scan)';\n } else if(miss && miss.length===0){\n hint.textContent = 'missing: (none)';\n } else {\n hint.textContent = 'missing: (unknown — failed to load /api/_meta)';\n }\n\n const guardTxt = await fetch('/api/guard-last.txt', { cache: 'no-store' }).then(r=>r.ok?r.text():null).catch(()=>null);\n const guardMeta = await fetch('/api/guard-last.json', { cache: 'no-store' }).then(r=>r.ok?r.json():null).catch(()=>null);\n\n document.getElementById('guard').textContent = guardTxt || '(no guard-last.txt yet — run: aiopt guard)';\n if(guardMeta){\n document.getElementById('guardMeta').textContent = 'exit=' + guardMeta.exitCode + ' · ' + guardMeta.ts;\n const badge = document.getElementById('guardBadge');\n const t = document.getElementById('guardBadgeText');\n const code = Number(guardMeta.exitCode);\n badge.classList.remove('ok','warn','fail');\n if(code===0){badge.classList.add('ok'); t.textContent='OK (0)';}\n else if(code===2){badge.classList.add('warn'); t.textContent='WARN (2)';}\n else {badge.classList.add('fail'); t.textContent='FAIL (3)';}\n }\n\n const histTxt = await fetch('/api/guard-history.jsonl', { cache: 'no-store' }).then(r=>r.ok?r.text():null).catch(()=>null);\n if(histTxt){\n const lines = histTxt.trim().split('\\n').filter(Boolean).slice(-15).reverse();\n const pretty = [];\n for(const l of lines){\n try{\n const j = JSON.parse(l);\n const code = Number(j.exitCode);\n const badge = (code===0?'OK':(code===2?'WARN':'FAIL'));\n const mode = j.mode || '—';\n const ts = (j.ts || '').replace('T',' ').replace('Z','');\n pretty.push(badge.padEnd(5) + ' ' + mode.padEnd(9) + ' ' + ts);\n }catch{pretty.push(l)}\n }\n document.getElementById('guardHist').textContent = pretty.join('\\n');\n } else {\n document.getElementById('guardHist').textContent = '(no guard-history.jsonl yet — run: aiopt guard)';\n }\n\n const reportJson = await fetch('/api/report.json', { cache: 'no-store' }).then(r=>r.ok?r.json():null).catch(()=>null);\n if(reportJson){\n const total = reportJson.summary && reportJson.summary.total_cost_usd;\n const sav = reportJson.summary && reportJson.summary.estimated_savings_usd;\n document.getElementById('totalCost').textContent = 'total: ' + money(total);\n\n // UX: if savings is ~0, explicitly say it's normal (not broken).\n const sNum = Number(sav || 0);\n const savingsText = (Number.isFinite(sNum) && sNum <= 0.01)\n ? 'savings: $0 (no obvious waste found)'\n : ('savings: ' + money(sav));\n document.getElementById('savings').textContent = savingsText;\n renderBars(document.getElementById('byModel'), reportJson.top && reportJson.top.by_model);\n renderBars(document.getElementById('byFeature'), reportJson.top && reportJson.top.by_feature);\n document.getElementById('scanMeta').textContent = 'confidence=' + (reportJson.confidence || '—') + ' · generated_at=' + (reportJson.generated_at || '—');\n } else {\n document.getElementById('scanMeta').textContent = '(no report.json yet — run: aiopt scan)';\n }\n\n // Use computed JSON endpoints to avoid downloading/parsing huge usage.jsonl in the browser.\n const live60 = await fetch('/api/live-60m.json', { cache: 'no-store' }).then(r=>r.ok?r.json():null).catch(()=>null);\n const sum7d = await fetch('/api/usage-summary.json', { cache: 'no-store' }).then(r=>r.ok?r.json():null).catch(()=>null);\n\n if(live60 && live60.bins){\n const pts = (live60.bins || []).slice().reverse();\n const W=520, H=120, P=12;\n const max = Math.max(...pts.map(b=>Number(b.cost)||0), 0.000001);\n const xs = pts.map((_,i)=> P + (i*(W-2*P))/59);\n const ys = pts.map(b=> H-P - (((Number(b.cost)||0)/max)*(H-2*P)) );\n let d = '';\n for(let i=0;i<xs.length;i++) d += (i===0?'M':'L') + xs[i].toFixed(1)+','+ys[i].toFixed(1)+' ';\n const area = 'M'+xs[0].toFixed(1)+','+(H-P).toFixed(1)+' ' + d + 'L'+xs[xs.length-1].toFixed(1)+','+(H-P).toFixed(1)+' Z';\n const svg =\n '<svg viewBox=\"0 0 '+W+' '+H+'\" width=\"100%\" height=\"'+H+'\" xmlns=\"http://www.w3.org/2000/svg\" style=\"background:rgba(255,255,255,.02); border:1px solid rgba(255,255,255,.10); border-radius:14px\">'+\n '<path d=\"'+area+'\" fill=\"rgba(167,139,250,.10)\" />'+\n '<path d=\"'+d+'\" fill=\"none\" stroke=\"rgba(167,139,250,.95)\" stroke-width=\"2\" />'+\n '<text x=\"'+P+'\" y=\"'+(P+10)+'\" fill=\"rgba(229,231,235,.75)\" font-size=\"11\">max/min '+money(max)+'</text>'+\n '</svg>';\n document.getElementById('liveSvg').innerHTML = svg;\n\n const rows = pts.slice(-10).map((b,idx)=>{\n const mAgo = 9-idx;\n const label = (mAgo===0 ? 'now' : (mAgo+'m'));\n const dollars = ('$' + (Math.round((Number(b.cost)||0)*100)/100).toFixed(2));\n return String(label).padEnd(5) + ' ' + String(dollars).padStart(9) + ' (' + (b.calls||0) + ' calls)';\n });\n document.getElementById('liveText').textContent = rows.join('\\n');\n\n const liveEl = document.getElementById('live');\n if(liveEl){\n liveEl.textContent = 'live: on · last60m ' + money(live60.totalCostUsd || 0);\n }\n } else {\n document.getElementById('liveText').textContent = '(no live data yet)';\n document.getElementById('liveSvg').innerHTML = '';\n }\n\n if(sum7d && sum7d.dayBins){\n const bins = sum7d.dayBins || [];\n const W=520, H=120, P=12;\n const pts = bins.slice().reverse();\n const max = Math.max(...pts.map(b=>Number(b.cost)||0), 0.000001);\n const xs = pts.map((_,i)=> P + (i*(W-2*P))/6);\n const ys = pts.map(b=> H-P - (((Number(b.cost)||0)/max)*(H-2*P)) );\n let d = '';\n for(let i=0;i<xs.length;i++) d += (i===0?'M':'L') + xs[i].toFixed(1)+','+ys[i].toFixed(1)+' ';\n const area = 'M'+xs[0].toFixed(1)+','+(H-P).toFixed(1)+' ' + d + 'L'+xs[xs.length-1].toFixed(1)+','+(H-P).toFixed(1)+' Z';\n const circles = xs.map((x,i)=>'<circle cx=\"'+x.toFixed(1)+'\" cy=\"'+ys[i].toFixed(1)+'\" r=\"2.6\" fill=\"rgba(52,211,153,.9)\"/>').join('');\n const svg =\n '<svg viewBox=\"0 0 '+W+' '+H+'\" width=\"100%\" height=\"'+H+'\" xmlns=\"http://www.w3.org/2000/svg\" style=\"background:rgba(255,255,255,.02); border:1px solid rgba(255,255,255,.10); border-radius:14px\">'+\n '<path d=\"'+area+'\" fill=\"rgba(96,165,250,.12)\" />'+\n '<path d=\"'+d+'\" fill=\"none\" stroke=\"rgba(96,165,250,.95)\" stroke-width=\"2\" />'+\n circles+\n '<text x=\"'+P+'\" y=\"'+(P+10)+'\" fill=\"rgba(229,231,235,.75)\" font-size=\"11\">max '+money(max)+'</text>'+\n '</svg>';\n document.getElementById('trendSvg').innerHTML = svg;\n\n const rows = pts.map((b,idx)=>{\n const label = (idx===pts.length-1 ? 'd-6' : (idx===0 ? 'today' : ('d-'+idx)));\n const dollars = ('$' + (Math.round((Number(b.cost)||0)*100)/100).toFixed(2));\n return String(label).padEnd(7) + ' ' + String(dollars).padStart(9) + ' (' + (b.calls||0) + ' calls)';\n });\n document.getElementById('trend').textContent = rows.join('\\n');\n } else {\n document.getElementById('trend').textContent = '(no 7d data yet)';\n document.getElementById('trendSvg').innerHTML = '';\n }\n\n const reportMd = await fetch('/api/report.md').then(r=>r.ok?r.text():null).catch(()=>null);\n document.getElementById('scan').textContent = reportMd || '(no report.md yet — run: aiopt scan)';\n}\n\n// Default: no auto-refresh (resource-friendly). User can refresh on demand.\nlet liveTimer = null;\n\nfunction setLive(on){\n const btn = document.getElementById('btnLive');\n const liveEl = document.getElementById('live');\n if(!btn || !liveEl) return;\n\n if(on){\n btn.textContent = 'Live: On';\n liveEl.textContent = 'live: on';\n if(liveTimer) clearInterval(liveTimer);\n liveTimer = setInterval(()=>{ load(); }, 5000);\n } else {\n btn.textContent = 'Live: Off';\n liveEl.textContent = 'live: off';\n if(liveTimer) clearInterval(liveTimer);\n liveTimer = null;\n }\n}\n\ndocument.getElementById('btnRefresh')?.addEventListener('click', ()=>{ load(); });\ndocument.getElementById('btnLive')?.addEventListener('click', ()=>{\n const on = !liveTimer;\n setLive(on);\n load();\n});\n\nsetLive(false);\nload();\n</script>\n</body>\n</html>`;\n\n const server = http.createServer((req, res) => {\n const url = req.url || '/';\n if (url === '/' || url === '/index.html') {\n res.writeHead(200, { 'content-type': 'text/html; charset=utf-8' });\n res.end(indexHtml);\n return;\n }\n\n if (url.startsWith('/api/')) {\n const name = url.replace('/api/', '');\n\n if (name === '_meta') {\n ensureUsageFile();\n ensureScanAndGuard();\n const expected = ['guard-last.txt', 'guard-last.json', 'report.json', 'report.md', 'usage.jsonl', 'guard-history.jsonl'];\n const missing = expected.filter(f => !fs.existsSync(file(f)));\n res.writeHead(200, { 'content-type': 'application/json; charset=utf-8' });\n res.end(JSON.stringify({ baseDir: cwd, outDir, missing, collect: lastCollect, collectError: lastCollectError, autoGen: lastAutoGen, autoGenError: lastAutoGenError }, null, 2));\n return;\n }\n\n const allow = new Set([\n 'guard-last.txt', 'guard-last.json', 'guard-history.jsonl',\n 'report.md', 'report.json',\n 'usage.jsonl',\n 'usage-summary.json',\n 'live-60m.json'\n ]);\n // auto-collect hook for anything that depends on usage\n if (name === 'usage.jsonl' || name === 'usage-summary.json' || name === 'live-60m.json') ensureUsageFile();\n // auto-generate scan/guard so the dashboard is never empty\n if (name === 'report.json' || name === 'report.md' || name === 'guard-last.txt' || name === 'guard-last.json' || name === 'guard-history.jsonl') ensureScanAndGuard();\n if (!allow.has(name)) {\n res.writeHead(404, { 'content-type': 'text/plain; charset=utf-8' });\n res.end('not found');\n return;\n }\n\n // Computed endpoints to keep dashboard fast (avoid downloading/parsing huge usage.jsonl in the browser).\n if (name === 'live-60m.json' || name === 'usage-summary.json') {\n const usagePath = file('usage.jsonl');\n const st = statOrNull(usagePath);\n if (!st) {\n res.writeHead(404, { 'content-type': 'text/plain; charset=utf-8' });\n res.end('missing');\n return;\n }\n\n // cache by mtime\n (globalThis as any).__aioptDashCache = (globalThis as any).__aioptDashCache || {};\n const cache = (globalThis as any).__aioptDashCache;\n\n if (!cache.usage || cache.usage.mtimeMs !== st.mtimeMs) {\n const txt = fs.readFileSync(usagePath, 'utf8');\n const now = Date.now();\n\n const liveBins = Array.from({ length: 60 }, () => ({ cost: 0, calls: 0 }));\n const dayBins = Array.from({ length: 7 }, () => ({ cost: 0, calls: 0 }));\n\n for (const line of txt.split(/\\r?\\n/)) {\n if (!line.trim()) continue;\n try {\n const ev = JSON.parse(line);\n const t = Date.parse(ev.ts);\n if (!Number.isFinite(t)) continue;\n const cost = Number(ev.cost_usd);\n const c = Number.isFinite(cost) ? cost : 0;\n\n const dm = Math.floor((now - t) / 60000);\n if (dm >= 0 && dm < 60) {\n liveBins[dm].calls += 1;\n liveBins[dm].cost += c;\n }\n\n const dd = Math.floor((now - t) / 86400000);\n if (dd >= 0 && dd < 7) {\n dayBins[dd].calls += 1;\n dayBins[dd].cost += c;\n }\n } catch {\n // ignore\n }\n }\n\n cache.usage = {\n mtimeMs: st.mtimeMs,\n live60m: {\n bins: liveBins,\n totalCostUsd: Math.round(liveBins.reduce((a, b) => a + b.cost, 0) * 100) / 100\n },\n summary7d: {\n dayBins\n }\n };\n }\n\n const body = name === 'live-60m.json' ? cache.usage.live60m : cache.usage.summary7d;\n res.writeHead(200, { 'content-type': 'application/json; charset=utf-8', 'cache-control': 'no-store' });\n res.end(JSON.stringify(body, null, 2));\n return;\n }\n\n const p = file(name);\n const txt = readOrNull(p);\n if (txt === null) {\n res.writeHead(404, { 'content-type': 'text/plain; charset=utf-8' });\n res.end('missing');\n return;\n }\n\n const ct = name.endsWith('.json') ? 'application/json; charset=utf-8' : 'text/plain; charset=utf-8';\n res.writeHead(200, { 'content-type': ct, 'cache-control': 'no-store' });\n res.end(txt);\n return;\n }\n\n res.writeHead(404, { 'content-type': 'text/plain; charset=utf-8' });\n res.end('not found');\n });\n\n await new Promise<void>((resolve, reject) => {\n server.once('error', reject);\n server.listen(port, host, () => resolve());\n });\n\n console.log(`OK: dashboard http://${host}:${port}/`);\n console.log('Tip: run `aiopt guard ...` and `aiopt scan` to populate aiopt-output files.');\n\n // keep alive\n await new Promise(() => {});\n}\n","import fs from 'fs';\nimport path from 'path';\n\nexport function findAioptOutputDir(startCwd: string): { cwd: string; outDir: string } {\n let cur = path.resolve(startCwd);\n while (true) {\n const outDir = path.join(cur, 'aiopt-output');\n if (fs.existsSync(outDir)) {\n try {\n if (fs.statSync(outDir).isDirectory()) return { cwd: cur, outDir };\n } catch {}\n }\n const parent = path.dirname(cur);\n if (parent === cur) break;\n cur = parent;\n }\n\n // If not found in parents, try one-level-down scan (common when user runs from a workspace root)\n try {\n const base = path.resolve(startCwd);\n const children = fs.readdirSync(base, { withFileTypes: true })\n .filter(d => d.isDirectory())\n .map(d => path.join(base, d.name));\n for (const child of children) {\n const outDir = path.join(child, 'aiopt-output');\n if (fs.existsSync(outDir)) {\n try {\n if (fs.statSync(outDir).isDirectory()) return { cwd: child, outDir };\n } catch {}\n }\n }\n } catch {\n // ignore\n }\n\n return { cwd: path.resolve(startCwd), outDir: path.join(path.resolve(startCwd), 'aiopt-output') };\n}\n","import fs from 'fs';\nimport path from 'path';\nimport { RateTable } from './types';\n\nexport function loadRateTableFromDistPath(): RateTable {\n // Works both in src/tsup and dist runtime.\n const p = path.join(__dirname, '..', 'rates', 'rate_table.json');\n return JSON.parse(fs.readFileSync(p, 'utf8')) as RateTable;\n}\n","import fs from 'fs';\nimport path from 'path';\nimport { analyze } from './scan';\nimport { loadRateTableFromDistPath } from './rates-util';\nimport { runGuard } from './guard';\n\nexport function seedDemoUsage(outDir: string) {\n fs.mkdirSync(outDir, { recursive: true });\n const p = path.join(outDir, 'usage.jsonl');\n const now = Date.now();\n const lines: any[] = [];\n for (let i = 0; i < 60; i++) {\n lines.push({\n ts: new Date(now - i * 60_000).toISOString(),\n provider: 'openai',\n model: i % 4 === 0 ? 'gpt-5.2' : 'gpt-5-mini',\n endpoint: 'responses',\n attempt: 1,\n trace_id: 'demo-' + i,\n status: 'ok',\n prompt_tokens: 10_000 + (i % 10) * 1000,\n completion_tokens: 1200 + (i % 5) * 200,\n meta: { feature_tag: i % 2 ? 'summarize' : 'coding' }\n });\n }\n fs.writeFileSync(p, lines.map(x => JSON.stringify(x)).join('\\n') + '\\n');\n return p;\n}\n\nexport function runQuickstart(cwd: string, opts: { port: number; budgetMonthlyUsd?: number }) {\n const outDir = path.join(cwd, 'aiopt-output');\n const usagePath = seedDemoUsage(outDir);\n\n const rt = loadRateTableFromDistPath();\n // Use the same normalizer as CLI scan/guard.\n const { readJsonl } = require('./io');\n const events = readJsonl(usagePath);\n const { analysis, savings, policy, meta } = analyze(rt, events);\n\n // write outputs (re-use scan writer by requiring dist is heavy; keep minimal here)\n fs.writeFileSync(path.join(outDir, 'analysis.json'), JSON.stringify(analysis, null, 2));\n fs.writeFileSync(path.join(outDir, 'report.json'), JSON.stringify({\n version: 3,\n generated_at: new Date().toISOString(),\n confidence: analysis.unknown_models?.length ? 'MEDIUM' : 'HIGH',\n warnings: [],\n assumptions: { quickstart: true },\n summary: {\n total_cost_usd: analysis.total_cost,\n estimated_savings_usd: savings.estimated_savings_total,\n routing_savings_usd: savings.routing_savings,\n context_savings_usd: savings.context_savings,\n retry_waste_usd: savings.retry_waste\n },\n top: {\n by_model: analysis.by_model_top,\n by_feature: analysis.by_feature_top\n },\n unknown_models: analysis.unknown_models || [],\n notes: []\n }, null, 2));\n fs.writeFileSync(path.join(outDir, 'cost-policy.json'), JSON.stringify(policy, null, 2));\n fs.writeFileSync(path.join(outDir, 'report.md'), '# AIOpt quickstart demo\\n\\nThis is a demo report generated by `aiopt quickstart --demo`.\\n');\n\n // Run guard on the same log with traffic spike to show WARN\n const r = runGuard(rt, {\n baselineEvents: events,\n candidate: {\n contextMultiplier: 1.2,\n callMultiplier: 5,\n budgetMonthlyUsd: opts.budgetMonthlyUsd\n }\n });\n\n return { usagePath, outDir, guard: r, port: opts.port };\n}\n","#!/usr/bin/env node\n\nimport fs from 'fs';\nimport path from 'path';\nimport { Command } from 'commander';\nimport { ensureDir, isCsvPath, readCsv, readJsonl } from './io';\nimport { RateTable } from './types';\nimport { analyze, writeOutputs } from './scan';\n\nconst program = new Command();\n\nconst DEFAULT_INPUT = './aiopt-output/usage.jsonl';\nconst DEFAULT_OUTPUT_DIR = './aiopt-output';\n\nfunction loadRateTable(): RateTable {\n const p = path.join(__dirname, '..', 'rates', 'rate_table.json');\n return JSON.parse(fs.readFileSync(p, 'utf8'));\n}\n\nprogram\n .name('aiopt')\n .description('AI 비용 자동 절감 인프라 — 서버 없는 로컬 CLI MVP')\n // keep CLI version in sync with package.json\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n .version(require('../package.json').version);\n\nprogram\n .command('init')\n .description('aiopt-input/ 및 샘플 usage.jsonl, aiopt-output/ 생성')\n .action(() => {\n ensureDir('./aiopt-input');\n ensureDir('./aiopt-output');\n\n const sampleSrc = path.join(__dirname, '..', 'samples', 'sample_usage.jsonl');\n const dst = path.join('./aiopt-input', 'usage.jsonl');\n\n if (!fs.existsSync(dst)) {\n fs.copyFileSync(sampleSrc, dst);\n console.log('Created ./aiopt-input/usage.jsonl (sample)');\n } else {\n console.log('Exists ./aiopt-input/usage.jsonl (skip)');\n }\n\n console.log('Ready: ./aiopt-output/');\n });\n\nprogram\n .command('scan')\n .description('입력 로그(JSONL/CSV)를 분석하고 report.md/report.json + patches까지 생성')\n .option('--input <path>', 'input file path (default: ./aiopt-output/usage.jsonl)', DEFAULT_INPUT)\n .option('--out <dir>', 'output dir (default: ./aiopt-output)', DEFAULT_OUTPUT_DIR)\n .action(async (opts) => {\n const inputPath = String(opts.input);\n const outDir = String(opts.out);\n\n if (!fs.existsSync(inputPath)) {\n console.error(`Input not found: ${inputPath}`);\n process.exit(1);\n }\n\n const rt = loadRateTable();\n const events = isCsvPath(inputPath) ? readCsv(inputPath) : readJsonl(inputPath);\n\n const { analysis, savings, policy, meta } = analyze(rt, events);\n // For reproducibility: embed input path & rate table meta\n policy.generated_from.input = inputPath;\n\n // Pass cwd + cli version for optional SARIF generation (code scan)\n writeOutputs(outDir, analysis, savings, policy, { ...meta, cwd: process.cwd(), cliVersion: program.version() });\n\n // Console: Top Fix 3 (data-driven)\n const { buildTopFixes } = await import('./solutions');\n const fixes = buildTopFixes(analysis, savings).slice(0, 3);\n\n console.log('Top Fix 3:');\n fixes.forEach((f, i) => {\n const tag = f.status === 'no-issue' ? '(no issue detected)' : `($${Math.round(f.impact_usd * 100) / 100})`;\n console.log(`${i + 1}) ${f.title} ${tag}`);\n });\n console.log(`Report: ${path.join(outDir, 'report.md')}`);\n });\n\nprogram\n .command('policy')\n .description('마지막 scan 결과 기반으로 cost-policy.json만 재생성 (MVP: scan과 동일 로직)')\n .option('--input <path>', 'input file path (default: ./aiopt-input/usage.jsonl)', DEFAULT_INPUT)\n .option('--out <dir>', 'output dir (default: ./aiopt-output)', DEFAULT_OUTPUT_DIR)\n .action((opts) => {\n const inputPath = String(opts.input);\n const outDir = String(opts.out);\n const rt = loadRateTable();\n const events = isCsvPath(inputPath) ? readCsv(inputPath) : readJsonl(inputPath);\n const { policy } = analyze(rt, events);\n policy.generated_from.input = inputPath;\n\n ensureDir(outDir);\n fs.writeFileSync(path.join(outDir, 'cost-policy.json'), JSON.stringify(policy, null, 2));\n console.log(`OK: ${outDir}/cost-policy.json`);\n });\n\n// v0.2: install/doctor (no servers)\nprogram\n .command('install')\n .description('Install AIOpt guardrails: create aiopt/ + policies + usage.jsonl')\n .option('--force', 'overwrite existing files')\n .option('--seed-sample', 'seed 1 sample line into aiopt-output/usage.jsonl')\n .action(async (opts) => {\n const { runInstall } = await import('./install');\n const result = runInstall(process.cwd(), { force: Boolean(opts.force), seedSample: Boolean(opts.seedSample) });\n for (const c of result.created) {\n console.log(`${c.status === 'created' ? 'CREATED' : 'SKIP'}: ${c.path}`);\n }\n });\n\nprogram\n .command('doctor')\n .description('Check installation + print last 5 usage events')\n .action(async () => {\n const { runDoctor } = await import('./doctor');\n const r = runDoctor(process.cwd());\n console.log(r.ok ? 'OK: doctor' : 'WARN: doctor');\n for (const c of r.checks) {\n console.log(`${c.ok ? 'OK' : 'FAIL'}: ${c.name}${c.detail ? ` (${c.detail})` : ''}`);\n }\n console.log('--- last5 usage');\n for (const x of r.last5) {\n console.log(JSON.stringify(x));\n }\n });\n\n// Offline license (no servers)\nconst licenseCmd = program\n .command('license')\n .description('Offline license activate/verify (public key only; no server calls)');\n\nlicenseCmd\n .command('activate')\n .argument('<KEY>', 'license key (<payloadB64Url>.<sigB64Url>)')\n .option('--out <path>', 'output license.json path (default: ./aiopt/license.json)')\n .action(async (key, opts) => {\n const { DEFAULT_PUBLIC_KEY_PEM, defaultLicensePath, verifyLicenseKey, writeLicenseFile } = await import('./license');\n const outPath = opts.out ? String(opts.out) : defaultLicensePath(process.cwd());\n const pub = process.env.AIOPT_LICENSE_PUBKEY || DEFAULT_PUBLIC_KEY_PEM;\n const v = verifyLicenseKey(String(key), pub);\n if (!v.payload) {\n console.error(`FAIL: ${v.reason || 'invalid license'}`);\n process.exit(3);\n }\n writeLicenseFile(outPath, String(key), v.payload, v.ok);\n console.log(v.ok ? `OK: activated (${outPath})` : `WARN: saved but not verified (${v.reason}) (${outPath})`);\n process.exit(v.ok ? 0 : 2);\n });\n\nlicenseCmd\n .command('verify')\n .option('--path <path>', 'license.json path (default: ./aiopt/license.json)')\n .action(async (opts) => {\n const { DEFAULT_PUBLIC_KEY_PEM, defaultLicensePath, readLicenseFile, verifyLicenseKey } = await import('./license');\n const p = opts.path ? String(opts.path) : defaultLicensePath(process.cwd());\n const pub = process.env.AIOPT_LICENSE_PUBKEY || DEFAULT_PUBLIC_KEY_PEM;\n if (!fs.existsSync(p)) {\n console.error(`FAIL: license file not found: ${p}`);\n process.exit(3);\n }\n const f = readLicenseFile(p);\n const v = verifyLicenseKey(f.key, pub);\n if (v.ok) {\n console.log('OK: license verified');\n process.exit(0);\n }\n console.error(`FAIL: license invalid (${v.reason || 'unknown'})`);\n process.exit(3);\n });\n\nlicenseCmd\n .command('status')\n .option('--path <path>', 'license.json path (default: ./aiopt/license.json)')\n .action(async (opts) => {\n const { DEFAULT_PUBLIC_KEY_PEM, defaultLicensePath, readLicenseFile, verifyLicenseKey } = await import('./license');\n const p = opts.path ? String(opts.path) : defaultLicensePath(process.cwd());\n const pub = process.env.AIOPT_LICENSE_PUBKEY || DEFAULT_PUBLIC_KEY_PEM;\n if (!fs.existsSync(p)) {\n console.log('NO_LICENSE');\n process.exit(2);\n }\n const f = readLicenseFile(p);\n const v = verifyLicenseKey(f.key, pub);\n if (v.ok) {\n console.log(`OK: ${f.payload.plan} exp=${f.payload.exp}`);\n process.exit(0);\n }\n console.log(`INVALID: ${v.reason || 'unknown'}`);\n process.exit(3);\n });\n\n// vNext: guardrail mode (pre-deploy warning)\nprogram\n .command('gate')\n .description('Merge gate (CI-friendly): fail (exit 1) when policy violations are detected; prints <=10 lines')\n .option('--input <path>', 'input usage jsonl/csv (default: ./aiopt-output/usage.jsonl)', DEFAULT_INPUT)\n .option('--out <dir>', 'output dir (default: ./aiopt-output)', DEFAULT_OUTPUT_DIR)\n .action(async (opts) => {\n const inputPath = String(opts.input);\n const outDir = String(opts.out);\n\n // Ensure scan artifacts exist (report + sarif). Keep deterministic, no network.\n if (!fs.existsSync(inputPath)) {\n console.error(`FAIL: input not found: ${inputPath}`);\n process.exit(1);\n }\n\n const rt = loadRateTable();\n const events = isCsvPath(inputPath) ? readCsv(inputPath) : readJsonl(inputPath);\n const { analysis, savings, policy, meta } = analyze(rt, events);\n policy.generated_from.input = inputPath;\n writeOutputs(outDir, analysis, savings, policy, { ...meta, cwd: process.cwd(), cliVersion: program.version() });\n\n const { runGate, formatGateStdout } = await import('./gate');\n const r = runGate(outDir, process.cwd());\n const out = formatGateStdout(r, outDir);\n console.log(out.text);\n process.exit(out.exitCode);\n });\n\nprogram\n .command('fix')\n .description('Auto-fix suggestions: generate aiopt.patch (and optionally apply it via git apply)')\n .option('--out <dir>', 'output dir (default: ./aiopt-output)', DEFAULT_OUTPUT_DIR)\n .option('--apply', 'apply the generated patch via git apply')\n .action(async (opts) => {\n const outDir = String(opts.out);\n const { runFix } = await import('./fix');\n const r = runFix(process.cwd(), { outDir, apply: Boolean(opts.apply) });\n console.log(`Patch: ${r.patchPath}`);\n if (r.changedFiles.length) {\n console.log(`Files: ${r.changedFiles.slice(0, 10).join(', ')}${r.changedFiles.length > 10 ? ' ...' : ''}`);\n } else {\n console.log('No changes suggested.');\n }\n if (r.applied) {\n console.log('OK: patch applied');\n process.exit(0);\n }\n if (!r.ok) {\n console.error(`FAIL: could not apply patch${r.hint ? ` (${r.hint})` : ''}`);\n process.exit(1);\n }\n process.exit(0);\n });\n\nprogram\n .command('guard')\n .description('Pre-deploy guardrail: compare baseline usage vs candidate change (or diff two log sets) and print warnings (exit codes 0/2/3)')\n .option('--input <path>', 'baseline usage jsonl/csv (legacy alias for --baseline; default: ./aiopt-output/usage.jsonl)', DEFAULT_INPUT)\n .option('--baseline <path>', 'baseline usage jsonl/csv (diff mode when used with --candidate)')\n .option('--candidate <path>', 'candidate usage jsonl/csv (diff mode: compare two real log sets)')\n .option('--provider <provider>', 'candidate provider override (transform mode only)')\n .option('--model <model>', 'candidate model override (transform mode only)')\n .option('--context-mult <n>', 'multiply input_tokens by n (transform mode only)', (v) => Number(v))\n .option('--output-mult <n>', 'multiply output_tokens by n (transform mode only)', (v) => Number(v))\n .option('--retries-delta <n>', 'add n to retries (transform mode only)', (v) => Number(v))\n .option('--call-mult <n>', 'multiply call volume by n (traffic spike)', (v) => Number(v))\n .option('--budget-monthly <usd>', 'fail if estimated candidate monthly cost exceeds this budget', (v) => Number(v))\n .action(async (opts) => {\n const rt = loadRateTable();\n\n const baselinePath = String(opts.baseline || opts.input);\n const candidatePath = opts.candidate ? String(opts.candidate) : null;\n\n const diffMode = Boolean(opts.baseline || opts.candidate);\n if (diffMode && (!opts.baseline || !opts.candidate)) {\n console.error('FAIL: diff mode requires both --baseline and --candidate');\n process.exit(3);\n }\n\n if (!fs.existsSync(baselinePath)) {\n console.error(`FAIL: baseline not found: ${baselinePath}`);\n process.exit(3);\n }\n if (candidatePath && !fs.existsSync(candidatePath)) {\n console.error(`FAIL: candidate not found: ${candidatePath}`);\n process.exit(3);\n }\n\n const baselineEvents = isCsvPath(baselinePath) ? readCsv(baselinePath) : readJsonl(baselinePath);\n const candidateEvents = candidatePath\n ? (isCsvPath(candidatePath) ? readCsv(candidatePath) : readJsonl(candidatePath))\n : undefined;\n\n const { runGuard } = await import('./guard');\n const r = runGuard(rt, {\n baselineEvents,\n candidateEvents,\n candidate: {\n provider: opts.provider,\n model: opts.model,\n contextMultiplier: opts.contextMult,\n outputMultiplier: opts.outputMult,\n retriesDelta: opts.retriesDelta,\n callMultiplier: opts.callMult,\n budgetMonthlyUsd: opts.budgetMonthly\n }\n });\n\n console.log(r.message);\n\n // Persist last guard output + history for local dashboard / CI attachments\n try {\n const outDir = path.resolve(DEFAULT_OUTPUT_DIR);\n fs.mkdirSync(outDir, { recursive: true });\n const ts = new Date().toISOString();\n fs.writeFileSync(path.join(outDir, 'guard-last.txt'), r.message);\n fs.writeFileSync(path.join(outDir, 'guard-last.json'), JSON.stringify({ ts, exitCode: r.exitCode }, null, 2));\n const histLine = JSON.stringify({ ts, exitCode: r.exitCode, mode: candidateEvents ? 'diff' : 'transform', baseline: baselinePath, candidate: candidatePath }) + '\\n';\n fs.appendFileSync(path.join(outDir, 'guard-history.jsonl'), histLine);\n } catch {\n // ignore\n }\n\n process.exit(r.exitCode);\n });\n\n// Local-only dashboard (no auth; binds to 127.0.0.1)\nprogram\n .command('dashboard')\n .description('Local dashboard (localhost only): view last guard + last scan outputs')\n .option('--port <n>', 'port (default: 3010)', (v) => Number(v), 3010)\n .option('--dir <path>', 'base directory containing ./aiopt-output (default: cwd)')\n .option('--auto', 'auto-detect by searching parents (and one-level children) for aiopt-output')\n .action(async (opts) => {\n const { startDashboard } = await import('./dashboard');\n const base = opts.dir ? String(opts.dir) : process.cwd();\n if (opts.auto) {\n const { findAioptOutputDir } = await import('./find-output');\n const found = findAioptOutputDir(base);\n await startDashboard(found.cwd, { port: Number(opts.port || 3010) });\n return;\n }\n await startDashboard(base, { port: Number(opts.port || 3010) });\n });\n\nprogram\n .command('quickstart')\n .description('1-minute demo: generate sample usage, run scan+guard, and print dashboard URL')\n .option('--demo', 'run demo workflow (writes to ./aiopt-output)')\n .option('--port <n>', 'dashboard port (default: 3010)', (v) => Number(v), 3010)\n .option('--budget-monthly <usd>', 'optional budget gate for the demo guard', (v) => Number(v))\n .option('--serve', 'start the local dashboard after generating demo outputs')\n .option('--open', 'best-effort open browser to the dashboard URL')\n .action(async (opts) => {\n if (!opts.demo) {\n console.error('FAIL: quickstart requires --demo');\n process.exit(3);\n }\n const port = Number(opts.port || 3010);\n const { runQuickstart } = await import('./quickstart');\n const r = runQuickstart(process.cwd(), { port, budgetMonthlyUsd: opts.budgetMonthly });\n console.log('OK: demo usage written:', r.usagePath);\n console.log('--- guard ---');\n console.log(r.guard.message);\n\n // persist guard-last + append guard history for dashboard\n try {\n const fs = await import('fs');\n const path = await import('path');\n fs.mkdirSync(r.outDir, { recursive: true });\n const ts = new Date().toISOString();\n fs.writeFileSync(path.join(r.outDir, 'guard-last.txt'), r.guard.message);\n fs.writeFileSync(path.join(r.outDir, 'guard-last.json'), JSON.stringify({ ts, exitCode: r.guard.exitCode }, null, 2));\n const histLine = JSON.stringify({ ts, exitCode: r.guard.exitCode, mode: 'quickstart', baseline: r.usagePath, candidate: null }) + '\\n';\n fs.appendFileSync(path.join(r.outDir, 'guard-history.jsonl'), histLine);\n } catch {}\n\n console.log('--- next ---');\n console.log(`Open: http://127.0.0.1:${port}/`);\n\n if (opts.serve) {\n const { startDashboard } = await import('./dashboard');\n if (opts.open) {\n try {\n const { execSync } = await import('child_process');\n const url = `http://127.0.0.1:${port}/`;\n if (process.platform === 'darwin') execSync(`open \"${url}\"`);\n else if (process.platform === 'win32') execSync(`cmd.exe /c start \"\" \"${url}\"`);\n else execSync(`xdg-open \"${url}\"`);\n } catch {}\n }\n console.log('Serving dashboard. Press CTRL+C to stop.');\n await startDashboard(process.cwd(), { port });\n return;\n }\n\n console.log(`Run: npx aiopt dashboard --port ${port}`);\n process.exit(r.guard.exitCode);\n });\n\nprogram.parse(process.argv);\n"],"mappings":"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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA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","names":["fs","parseCsv","path","cost","path","fs","import_fs","import_path","path","fs","import_fs","import_path","path","import_path","round2","fs","path","import_fs","import_path","exports","module","ensureDir","fs","path","import_fs","import_path","fs","path","import_fs","import_path","crypto","path","fs","import_fs","import_path","path","fs","import_fs","import_path","isTextLike","path","walk","fs","DEFAULT_EXCLUDES","os","import_fs","import_path","round2","conf","msg","input","fs","path","os","import_fs","import_path","import_os","path","fs","loadRateTable","http","txt","import_fs","import_path","path","fs","import_fs","import_path","path","fs","import_fs","import_path","fs","path","readJsonl","import_fs","import_path","import_fs","import_path","path","fs","buildTopFixes","runInstall","runDoctor","DEFAULT_PUBLIC_KEY_PEM","defaultLicensePath","verifyLicenseKey","writeLicenseFile","readLicenseFile","runGate","formatGateStdout","runFix","runGuard","startDashboard","findAioptOutputDir","runQuickstart","execSync"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aiopt",
3
- "version": "0.3.4",
3
+ "version": "0.3.5",
4
4
  "description": "Pre-deploy LLM cost accident guardrail (serverless local CLI)",
5
5
  "bin": {
6
6
  "aiopt": "dist/cli.js"