@jphutchins/code-review 0.1.0-alpha.11 → 0.1.0-alpha.12

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/index.js CHANGED
@@ -660,7 +660,7 @@ var decideGate = (state, nudges, maxNudges, draftPath, kind) => {
660
660
  reason: [
661
661
  `This review is not complete \u2014 ${whatsWrong(state, draftPath, kind)}`,
662
662
  `The only deliverable is a ${kind} document that validates against the ${kind} schema \u2014 run "code-review print-schema ${kind}" to see the exact shape.`,
663
- `Write it to ${draftPath}, then run "code-review validate ${draftPath} --kind ${kind}" until it exits 0 before ending your turn.`
663
+ `Write it to ${draftPath}, then run "code-review validate ${draftPath} --kind ${kind} --explain" until it exits 0 before ending your turn (--explain prints the schema when the shape is wrong).`
664
664
  ].join("\n")
665
665
  };
666
666
  };
@@ -724,19 +724,26 @@ var stopHookSettings = (command) => ({
724
724
 
725
725
  // src/budget.ts
726
726
  var DEADLINE_ENV = "CODE_REVIEW_DEADLINE_EPOCH";
727
- var DEFAULT_RESERVE = { frac: 0.15, flatUsd: 0.02, flatMs: 12e4 };
727
+ var DEFAULT_RESERVE = {
728
+ frac: 0.15,
729
+ growth: 0.25,
730
+ flatUsd: 0.02,
731
+ flatMs: 12e4
732
+ };
728
733
  var SOFT_MULTIPLE = 2;
729
734
  var costAxis = (i) => i.spentUsd !== null && i.budgetUsd !== null && i.budgetUsd > 0 ? { used: i.spentUsd, limit: i.budgetUsd, flat: i.reserve.flatUsd } : null;
730
735
  var timeAxis = (i) => i.elapsedMs !== null && i.wallMs !== null && i.wallMs > 0 ? { used: i.elapsedMs, limit: i.wallMs, flat: i.reserve.flatMs } : null;
731
- var axisSeverity = (a, frac) => {
732
- const hardReserve = Math.max(a.flat, frac * a.limit);
736
+ var axisSeverity = (a, reserve) => {
737
+ const usedFrac = Math.min(1, Math.max(0, a.used / a.limit));
738
+ const effFrac = reserve.frac + reserve.growth * usedFrac;
739
+ const hardReserve = Math.max(a.flat, effFrac * a.limit);
733
740
  const remaining = a.limit - a.used;
734
741
  if (remaining <= hardReserve) return 2;
735
742
  if (remaining <= SOFT_MULTIPLE * hardReserve) return 1;
736
743
  return 0;
737
744
  };
738
745
  var decideBudget = (i) => {
739
- const worst = [costAxis(i), timeAxis(i)].filter((a) => a !== null).reduce((max, a) => Math.max(max, axisSeverity(a, i.reserve.frac)), 0);
746
+ const worst = [costAxis(i), timeAxis(i)].filter((a) => a !== null).reduce((max, a) => Math.max(max, axisSeverity(a, i.reserve)), 0);
740
747
  return worst === 2 ? { kind: "hard" } : worst === 1 ? { kind: "soft" } : { kind: "ok" };
741
748
  };
742
749
  var pct = (n) => `${String(Math.round(n * 100))}%`;
@@ -744,7 +751,7 @@ var money = (n) => `$${n.toFixed(2)}`;
744
751
  var mins = (ms) => `${(ms / 6e4).toFixed(1)}m`;
745
752
  var spendClause = (i) => i.spentUsd === null ? null : i.budgetUsd !== null && i.budgetUsd > 0 ? `spent ${money(i.spentUsd)}/${money(i.budgetUsd)} (${pct(i.spentUsd / i.budgetUsd)})` : `spent ${money(i.spentUsd)}`;
746
753
  var timeClause = (i) => i.elapsedMs === null ? null : i.wallMs !== null && i.wallMs > 0 ? `${mins(i.elapsedMs)}/${mins(i.wallMs)} elapsed (${pct(i.elapsedMs / i.wallMs)})` : `${mins(i.elapsedMs)} elapsed`;
747
- var directive = (phase, draftPath) => phase.kind === "hard" ? `Budget nearly exhausted \u2014 STOP all new investigation now. Write your COMPLETE findings to ${draftPath} and run \`code-review validate ${draftPath}\` until it passes. Other tools are blocked until that draft is written.` : `Wind down investigation and write your COMPLETE findings to ${draftPath} now, then validate \u2014 you may run out of budget before you finish otherwise.`;
754
+ var directive = (phase, draftPath) => phase.kind === "hard" ? `Budget nearly exhausted \u2014 STOP all new investigation now. Write your COMPLETE findings to ${draftPath} and run \`code-review validate ${draftPath} --explain\` until it passes (--explain prints the exact schema when the shape is wrong). Other tools are blocked until that draft is written.` : `Wind down investigation and write your COMPLETE findings to ${draftPath} now, then run \`code-review validate ${draftPath} --explain\` (it prints the exact schema if the shape is wrong) \u2014 you may run out of budget before you finish otherwise.`;
748
755
  var budgetMessage = (i, phase, draftPath) => {
749
756
  const status = [spendClause(i), timeClause(i)].filter((c) => c !== null).join(" \xB7 ");
750
757
  return `Budget check \u2014 ${status}. ${directive(phase, draftPath)}`;
@@ -838,6 +845,7 @@ var budgetHookCommand = (draftPath, opts) => [
838
845
  ...opts.wall ? ["--wall", shellQuote(opts.wall)] : [],
839
846
  ...opts.prices ? ["--prices", shellQuote(opts.prices)] : [],
840
847
  ...opts.reserveFrac ? ["--reserve-frac", shellQuote(opts.reserveFrac)] : [],
848
+ ...opts.reserveGrowth ? ["--reserve-growth", shellQuote(opts.reserveGrowth)] : [],
841
849
  ...opts.reserveUsd ? ["--reserve-usd", shellQuote(opts.reserveUsd)] : [],
842
850
  ...opts.reserveWall ? ["--reserve-wall", shellQuote(opts.reserveWall)] : []
843
851
  ].join(" ");
@@ -2171,7 +2179,11 @@ var budgetHookCmd = defineCommand({
2171
2179
  },
2172
2180
  "reserve-frac": {
2173
2181
  type: "string",
2174
- description: "Wind-down headroom as a fraction of each budget: converge once less than this remains (default: 0.15; the soft steer tier reserves 2\xD7 this)"
2182
+ description: "Base wind-down headroom as a fraction of each budget: converge once less than this remains (default: 0.15; the soft steer tier reserves 2\xD7 this)"
2183
+ },
2184
+ "reserve-growth": {
2185
+ type: "string",
2186
+ description: "How much the reserve grows as a budget is spent \u2014 added at full usage, so convergence lands earlier the longer the run has gone (default: 0.25; 0 = flat reserve)"
2175
2187
  },
2176
2188
  "reserve-usd": {
2177
2189
  type: "string",
@@ -2204,6 +2216,7 @@ var budgetHookCmd = defineCommand({
2204
2216
  wallMs,
2205
2217
  reserve: {
2206
2218
  frac: parseFraction(args["reserve-frac"], DEFAULT_RESERVE.frac),
2219
+ growth: parseFraction(args["reserve-growth"], DEFAULT_RESERVE.growth),
2207
2220
  flatUsd: parseBudgetUsd(args["reserve-usd"]) ?? DEFAULT_RESERVE.flatUsd,
2208
2221
  flatMs: args["reserve-wall"] ? parseWallMs(args["reserve-wall"]) ?? DEFAULT_RESERVE.flatMs : DEFAULT_RESERVE.flatMs
2209
2222
  },
@@ -2265,7 +2278,11 @@ var printSettingsCmd = defineCommand({
2265
2278
  },
2266
2279
  "reserve-frac": {
2267
2280
  type: "string",
2268
- description: "Wind-down headroom as a fraction of each budget (default: 0.15; soft tier is 2\xD7)"
2281
+ description: "Base wind-down headroom as a fraction of each budget (default: 0.15; soft tier is 2\xD7)"
2282
+ },
2283
+ "reserve-growth": {
2284
+ type: "string",
2285
+ description: "How much the reserve grows as a budget is spent, converging earlier the longer the run has gone (default: 0.25; 0 = flat)"
2269
2286
  },
2270
2287
  "reserve-usd": {
2271
2288
  type: "string",
@@ -2293,6 +2310,7 @@ var printSettingsCmd = defineCommand({
2293
2310
  wall: args.wall,
2294
2311
  prices: args.prices,
2295
2312
  reserveFrac: args["reserve-frac"],
2313
+ reserveGrowth: args["reserve-growth"],
2296
2314
  reserveUsd: args["reserve-usd"],
2297
2315
  reserveWall: args["reserve-wall"]
2298
2316
  }
@@ -2324,6 +2342,13 @@ var deadlineCmd = defineCommand({
2324
2342
  }
2325
2343
  });
2326
2344
  var derivedSchemaVersion = (kind, raw) => kind === "findings" ? declaredVersion(raw) : void 0;
2345
+ var printableSchema = (schemaPath) => {
2346
+ const schema = JSON.parse(readFileSync(schemaPath, "utf-8"));
2347
+ const enforcementSchema = Object.fromEntries(
2348
+ Object.entries(schema).filter(([key2]) => key2 !== "$schema")
2349
+ );
2350
+ return JSON.stringify(enforcementSchema, null, 2);
2351
+ };
2327
2352
  var validateCmd = defineCommand({
2328
2353
  meta: {
2329
2354
  name: "validate",
@@ -2346,6 +2371,10 @@ var validateCmd = defineCommand({
2346
2371
  "schema-version": {
2347
2372
  type: "string",
2348
2373
  description: "Schema major.minor version to validate against (default: the document's declared schema_version for findings, or the kind's latest)"
2374
+ },
2375
+ explain: {
2376
+ type: "boolean",
2377
+ description: "On failure, also print the schema after the errors \u2014 its field descriptions are the authoritative spec, so the document can be fixed in one pass instead of by trial and error"
2349
2378
  }
2350
2379
  },
2351
2380
  run: async ({ args }) => {
@@ -2359,6 +2388,14 @@ var validateCmd = defineCommand({
2359
2388
  process.stderr.write("\u274C invalid\n");
2360
2389
  for (const e of errors) process.stderr.write(` - ${e}
2361
2390
  `);
2391
+ if (args.explain) {
2392
+ process.stderr.write(
2393
+ `
2394
+ The ${kind} document must conform to this schema (the field descriptions are the authoritative spec \u2014 match the property names exactly):
2395
+ ${printableSchema(schemaPath)}
2396
+ `
2397
+ );
2398
+ }
2362
2399
  process.exit(1);
2363
2400
  }
2364
2401
  }
@@ -2571,11 +2608,7 @@ var printSchemaCmd = defineCommand({
2571
2608
  run: async ({ args }) => {
2572
2609
  const schemaKind = requireSchemaKind(args.name);
2573
2610
  const schemaPath = requireSchemaPath(schemaKind, args["schema-version"]);
2574
- const schema = JSON.parse(readFileSync(schemaPath, "utf-8"));
2575
- const enforcementSchema = Object.fromEntries(
2576
- Object.entries(schema).filter(([key2]) => key2 !== "$schema")
2577
- );
2578
- process.stdout.write(`${JSON.stringify(enforcementSchema, null, 2)}
2611
+ process.stdout.write(`${printableSchema(schemaPath)}
2579
2612
  `);
2580
2613
  }
2581
2614
  });