@jphutchins/code-review 0.1.0-alpha.10 → 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 +141 -29
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/templates/comment.eta +8 -7
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { defineCommand, runMain } from 'citty';
|
|
3
3
|
import { readFileSync, writeFileSync, readdirSync } from 'fs';
|
|
4
|
-
import { resolve as resolve$1, join, dirname } from 'path';
|
|
4
|
+
import { resolve as resolve$1, join, dirname, basename } from 'path';
|
|
5
5
|
import { Eta } from 'eta';
|
|
6
6
|
import parseDiff from 'parse-diff';
|
|
7
7
|
import { Ajv2020 } from 'ajv/dist/2020.js';
|
|
@@ -463,8 +463,9 @@ var sumTranscriptUsage = (entries) => {
|
|
|
463
463
|
};
|
|
464
464
|
};
|
|
465
465
|
var subagentFiles = (mainPath) => {
|
|
466
|
+
const dir = join(dirname(mainPath), basename(mainPath, ".jsonl"), "subagents");
|
|
466
467
|
try {
|
|
467
|
-
return readdirSync(
|
|
468
|
+
return readdirSync(dir).filter((name) => name.endsWith(".jsonl")).map((name) => join(dir, name));
|
|
468
469
|
} catch {
|
|
469
470
|
return [];
|
|
470
471
|
}
|
|
@@ -659,7 +660,7 @@ var decideGate = (state, nudges, maxNudges, draftPath, kind) => {
|
|
|
659
660
|
reason: [
|
|
660
661
|
`This review is not complete \u2014 ${whatsWrong(state, draftPath, kind)}`,
|
|
661
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.`,
|
|
662
|
-
`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).`
|
|
663
664
|
].join("\n")
|
|
664
665
|
};
|
|
665
666
|
};
|
|
@@ -722,19 +723,27 @@ var stopHookSettings = (command) => ({
|
|
|
722
723
|
});
|
|
723
724
|
|
|
724
725
|
// src/budget.ts
|
|
725
|
-
var
|
|
726
|
+
var DEADLINE_ENV = "CODE_REVIEW_DEADLINE_EPOCH";
|
|
727
|
+
var DEFAULT_RESERVE = {
|
|
728
|
+
frac: 0.15,
|
|
729
|
+
growth: 0.25,
|
|
730
|
+
flatUsd: 0.02,
|
|
731
|
+
flatMs: 12e4
|
|
732
|
+
};
|
|
726
733
|
var SOFT_MULTIPLE = 2;
|
|
727
734
|
var costAxis = (i) => i.spentUsd !== null && i.budgetUsd !== null && i.budgetUsd > 0 ? { used: i.spentUsd, limit: i.budgetUsd, flat: i.reserve.flatUsd } : null;
|
|
728
735
|
var timeAxis = (i) => i.elapsedMs !== null && i.wallMs !== null && i.wallMs > 0 ? { used: i.elapsedMs, limit: i.wallMs, flat: i.reserve.flatMs } : null;
|
|
729
|
-
var axisSeverity = (a,
|
|
730
|
-
const
|
|
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);
|
|
731
740
|
const remaining = a.limit - a.used;
|
|
732
741
|
if (remaining <= hardReserve) return 2;
|
|
733
742
|
if (remaining <= SOFT_MULTIPLE * hardReserve) return 1;
|
|
734
743
|
return 0;
|
|
735
744
|
};
|
|
736
745
|
var decideBudget = (i) => {
|
|
737
|
-
const worst = [costAxis(i), timeAxis(i)].filter((a) => a !== null).reduce((max, a) => Math.max(max, axisSeverity(a, i.reserve
|
|
746
|
+
const worst = [costAxis(i), timeAxis(i)].filter((a) => a !== null).reduce((max, a) => Math.max(max, axisSeverity(a, i.reserve)), 0);
|
|
738
747
|
return worst === 2 ? { kind: "hard" } : worst === 1 ? { kind: "soft" } : { kind: "ok" };
|
|
739
748
|
};
|
|
740
749
|
var pct = (n) => `${String(Math.round(n * 100))}%`;
|
|
@@ -742,7 +751,7 @@ var money = (n) => `$${n.toFixed(2)}`;
|
|
|
742
751
|
var mins = (ms) => `${(ms / 6e4).toFixed(1)}m`;
|
|
743
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)}`;
|
|
744
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`;
|
|
745
|
-
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.`;
|
|
746
755
|
var budgetMessage = (i, phase, draftPath) => {
|
|
747
756
|
const status = [spendClause(i), timeClause(i)].filter((c) => c !== null).join(" \xB7 ");
|
|
748
757
|
return `Budget check \u2014 ${status}. ${directive(phase, draftPath)}`;
|
|
@@ -810,6 +819,20 @@ var parseWallMs = (raw) => {
|
|
|
810
819
|
return n * 36e5;
|
|
811
820
|
}
|
|
812
821
|
};
|
|
822
|
+
var parseEpochSecMs = (raw) => {
|
|
823
|
+
if (raw === void 0) return null;
|
|
824
|
+
const t4 = raw.trim();
|
|
825
|
+
if (!/^\d+$/.test(t4)) return null;
|
|
826
|
+
const n = Number.parseInt(t4, 10);
|
|
827
|
+
return Number.isFinite(n) && n > 0 ? n * 1e3 : null;
|
|
828
|
+
};
|
|
829
|
+
var anchoredElapsedMs = (src) => {
|
|
830
|
+
if (src.deadlineMs !== null && src.wallMs !== null)
|
|
831
|
+
return Math.max(0, src.wallMs - (src.deadlineMs - src.nowMs));
|
|
832
|
+
if (src.firstTsMs !== null) return Math.max(0, src.nowMs - src.firstTsMs);
|
|
833
|
+
return null;
|
|
834
|
+
};
|
|
835
|
+
var deadlineEpochSec = (wallMs, nowMs) => Math.floor(nowMs / 1e3) + Math.ceil(wallMs / 1e3);
|
|
813
836
|
var parseFraction = (raw, fallback) => {
|
|
814
837
|
if (raw === void 0) return fallback;
|
|
815
838
|
const n = Number.parseFloat(raw);
|
|
@@ -822,6 +845,7 @@ var budgetHookCommand = (draftPath, opts) => [
|
|
|
822
845
|
...opts.wall ? ["--wall", shellQuote(opts.wall)] : [],
|
|
823
846
|
...opts.prices ? ["--prices", shellQuote(opts.prices)] : [],
|
|
824
847
|
...opts.reserveFrac ? ["--reserve-frac", shellQuote(opts.reserveFrac)] : [],
|
|
848
|
+
...opts.reserveGrowth ? ["--reserve-growth", shellQuote(opts.reserveGrowth)] : [],
|
|
825
849
|
...opts.reserveUsd ? ["--reserve-usd", shellQuote(opts.reserveUsd)] : [],
|
|
826
850
|
...opts.reserveWall ? ["--reserve-wall", shellQuote(opts.reserveWall)] : []
|
|
827
851
|
].join(" ");
|
|
@@ -1362,7 +1386,7 @@ var post = async (input, ghApi = runGhApi) => {
|
|
|
1362
1386
|
`
|
|
1363
1387
|
);
|
|
1364
1388
|
}
|
|
1365
|
-
const botReviews =
|
|
1389
|
+
const botReviews = await fetchBotReviews(input.repo, prNumber, input.botLogin, ghApi);
|
|
1366
1390
|
const alreadyReviewedThisSha = botReviews.some((r) => r.commitId === input.headSha);
|
|
1367
1391
|
const initialDisposition = comments.length > 0 ? alreadyReviewedThisSha ? { kind: "suppressed-existing-review", sha: input.headSha } : void 0 : strays.length > 0 ? { kind: "none-in-diff" } : void 0;
|
|
1368
1392
|
const commonRenderInput = {
|
|
@@ -1396,10 +1420,9 @@ var post = async (input, ghApi = runGhApi) => {
|
|
|
1396
1420
|
renderBody(initialDisposition),
|
|
1397
1421
|
ghApi
|
|
1398
1422
|
);
|
|
1399
|
-
if (comments.length === 0) return;
|
|
1400
1423
|
if (alreadyReviewedThisSha) {
|
|
1401
1424
|
process.stderr.write(
|
|
1402
|
-
`A completed bot review already exists for ${input.headSha} \u2014 updated sticky only, no new
|
|
1425
|
+
`A completed bot review already exists for ${input.headSha} \u2014 updated sticky only, no new review
|
|
1403
1426
|
`
|
|
1404
1427
|
);
|
|
1405
1428
|
return;
|
|
@@ -1418,11 +1441,11 @@ var post = async (input, ghApi = runGhApi) => {
|
|
|
1418
1441
|
ghApi
|
|
1419
1442
|
);
|
|
1420
1443
|
process.stderr.write(
|
|
1421
|
-
`Posted ${String(comments.length)} inline
|
|
1444
|
+
`Posted a review with ${String(comments.length)} inline comment(s) on PR #${String(prNumber)}
|
|
1422
1445
|
`
|
|
1423
1446
|
);
|
|
1424
1447
|
await minimizeSupersededComments(input.repo, prNumber, input.headSha, input.botLogin, ghApi);
|
|
1425
|
-
if (stickyRef !== null) {
|
|
1448
|
+
if (comments.length > 0 && stickyRef !== null) {
|
|
1426
1449
|
const confirmedDisposition = {
|
|
1427
1450
|
kind: "posted",
|
|
1428
1451
|
count: comments.length,
|
|
@@ -1776,16 +1799,34 @@ var withMeta = (base, meta) => ({
|
|
|
1776
1799
|
...meta.route ? { route: meta.route } : {},
|
|
1777
1800
|
...meta.effort ? { effort: meta.effort } : {}
|
|
1778
1801
|
});
|
|
1779
|
-
var
|
|
1802
|
+
var resolveTelemetry = (native, meta) => {
|
|
1803
|
+
const fb = native.models.length === 0 ? meta.transcriptFallback?.() : void 0;
|
|
1804
|
+
const useFallback = fb !== void 0 && fb.models.length > 0;
|
|
1805
|
+
return withMeta(
|
|
1806
|
+
useFallback ? {
|
|
1807
|
+
models: [...fb.models],
|
|
1808
|
+
turns: fb.turns,
|
|
1809
|
+
duration_ms: fb.durationMs,
|
|
1810
|
+
vendor_cost_usd: native.vendorCostUsd
|
|
1811
|
+
} : {
|
|
1812
|
+
models: native.models,
|
|
1813
|
+
turns: native.turns,
|
|
1814
|
+
duration_ms: native.durationMs,
|
|
1815
|
+
vendor_cost_usd: native.vendorCostUsd
|
|
1816
|
+
},
|
|
1817
|
+
meta
|
|
1818
|
+
);
|
|
1819
|
+
};
|
|
1820
|
+
var nativeTelemetry = (native, meta) => resolveTelemetry(
|
|
1780
1821
|
{
|
|
1781
1822
|
models: mapModelUsage(native.modelUsage),
|
|
1782
1823
|
turns: native.num_turns,
|
|
1783
|
-
|
|
1784
|
-
|
|
1824
|
+
durationMs: native.duration_ms,
|
|
1825
|
+
vendorCostUsd: native.total_cost_usd ?? null
|
|
1785
1826
|
},
|
|
1786
1827
|
meta
|
|
1787
1828
|
);
|
|
1788
|
-
var absentTelemetry = (meta) =>
|
|
1829
|
+
var absentTelemetry = (meta) => resolveTelemetry({ models: [], turns: 0, durationMs: 0, vendorCostUsd: null }, meta);
|
|
1789
1830
|
var buildEnvelope = (telemetry, native, agentFilePath) => {
|
|
1790
1831
|
const outcome = findingsOutcome(native, agentFilePath);
|
|
1791
1832
|
switch (outcome.kind) {
|
|
@@ -1908,6 +1949,16 @@ var unwrapAdapt = (either) => {
|
|
|
1908
1949
|
}
|
|
1909
1950
|
throw new Error("unreachable");
|
|
1910
1951
|
};
|
|
1952
|
+
var transcriptFallbackFrom = (path) => {
|
|
1953
|
+
const tree = readTranscriptTree(resolve$1(path));
|
|
1954
|
+
if (tree.missing)
|
|
1955
|
+
process.stderr.write(
|
|
1956
|
+
`code-review adapt: transcript ${path} is unreadable \u2014 no telemetry fallback (issue #36)
|
|
1957
|
+
`
|
|
1958
|
+
);
|
|
1959
|
+
const usage = sumTranscriptUsage(tree.entries);
|
|
1960
|
+
return { models: usage.models, turns: usage.turns, durationMs: usage.durationMs };
|
|
1961
|
+
};
|
|
1911
1962
|
var bundledPath = (...segments) => resolve$1(import.meta.dirname, "..", ...segments);
|
|
1912
1963
|
var packageVersion = JSON.parse(readFileSync(bundledPath("package.json"), "utf-8")).version;
|
|
1913
1964
|
var resolveTemplatePath = (templateArg) => templateArg ? resolve$1(templateArg) : bundledPath("templates", "comment.eta");
|
|
@@ -2128,7 +2179,11 @@ var budgetHookCmd = defineCommand({
|
|
|
2128
2179
|
},
|
|
2129
2180
|
"reserve-frac": {
|
|
2130
2181
|
type: "string",
|
|
2131
|
-
description: "
|
|
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)"
|
|
2132
2187
|
},
|
|
2133
2188
|
"reserve-usd": {
|
|
2134
2189
|
type: "string",
|
|
@@ -2148,13 +2203,20 @@ var budgetHookCmd = defineCommand({
|
|
|
2148
2203
|
const usage = tree ? sumTranscriptUsage(tree.entries) : void 0;
|
|
2149
2204
|
const prices = args.prices ? tryReadPrices(args.prices) : null;
|
|
2150
2205
|
const spentUsd = prices !== null && usage ? computeCost(usage.models, prices).totalCostUSD : null;
|
|
2206
|
+
const wallMs = args.wall ? parseWallMs(args.wall) : null;
|
|
2151
2207
|
const output = evaluateBudgetHook(input, {
|
|
2152
2208
|
spentUsd,
|
|
2153
2209
|
budgetUsd: parseBudgetUsd(args["budget-usd"]),
|
|
2154
|
-
elapsedMs:
|
|
2155
|
-
|
|
2210
|
+
elapsedMs: anchoredElapsedMs({
|
|
2211
|
+
deadlineMs: parseEpochSecMs(process.env[DEADLINE_ENV]),
|
|
2212
|
+
wallMs,
|
|
2213
|
+
firstTsMs: usage?.firstTsMs ?? null,
|
|
2214
|
+
nowMs: Date.now()
|
|
2215
|
+
}),
|
|
2216
|
+
wallMs,
|
|
2156
2217
|
reserve: {
|
|
2157
2218
|
frac: parseFraction(args["reserve-frac"], DEFAULT_RESERVE.frac),
|
|
2219
|
+
growth: parseFraction(args["reserve-growth"], DEFAULT_RESERVE.growth),
|
|
2158
2220
|
flatUsd: parseBudgetUsd(args["reserve-usd"]) ?? DEFAULT_RESERVE.flatUsd,
|
|
2159
2221
|
flatMs: args["reserve-wall"] ? parseWallMs(args["reserve-wall"]) ?? DEFAULT_RESERVE.flatMs : DEFAULT_RESERVE.flatMs
|
|
2160
2222
|
},
|
|
@@ -2216,7 +2278,11 @@ var printSettingsCmd = defineCommand({
|
|
|
2216
2278
|
},
|
|
2217
2279
|
"reserve-frac": {
|
|
2218
2280
|
type: "string",
|
|
2219
|
-
description: "
|
|
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)"
|
|
2220
2286
|
},
|
|
2221
2287
|
"reserve-usd": {
|
|
2222
2288
|
type: "string",
|
|
@@ -2244,6 +2310,7 @@ var printSettingsCmd = defineCommand({
|
|
|
2244
2310
|
wall: args.wall,
|
|
2245
2311
|
prices: args.prices,
|
|
2246
2312
|
reserveFrac: args["reserve-frac"],
|
|
2313
|
+
reserveGrowth: args["reserve-growth"],
|
|
2247
2314
|
reserveUsd: args["reserve-usd"],
|
|
2248
2315
|
reserveWall: args["reserve-wall"]
|
|
2249
2316
|
}
|
|
@@ -2252,7 +2319,36 @@ var printSettingsCmd = defineCommand({
|
|
|
2252
2319
|
`);
|
|
2253
2320
|
}
|
|
2254
2321
|
});
|
|
2322
|
+
var deadlineCmd = defineCommand({
|
|
2323
|
+
meta: {
|
|
2324
|
+
name: "deadline",
|
|
2325
|
+
description: "Print the run's absolute deadline as Unix epoch seconds (now + --wall). The review job exports this as CODE_REVIEW_DEADLINE_EPOCH right before `claude -p` so every budget hook \u2014 the main agent's and each fan-out subagent's \u2014 measures the SAME true remaining wall instead of its own transcript's start, which reads \u22480 in a fresh subagent and leaves the fan-out unsteered (issue #45)."
|
|
2326
|
+
},
|
|
2327
|
+
args: {
|
|
2328
|
+
wall: {
|
|
2329
|
+
type: "string",
|
|
2330
|
+
description: "Wall-clock budget for the run (e.g. 24m, 1200s, 2h) \u2014 the deadline is now + this",
|
|
2331
|
+
required: true
|
|
2332
|
+
}
|
|
2333
|
+
},
|
|
2334
|
+
run: async ({ args }) => {
|
|
2335
|
+
const wallMs = parseWallMs(args.wall);
|
|
2336
|
+
if (wallMs === null) {
|
|
2337
|
+
fail(`--wall must be a duration like 24m, 1200s, or 2h (got '${args.wall}')`);
|
|
2338
|
+
} else {
|
|
2339
|
+
process.stdout.write(`${String(deadlineEpochSec(wallMs, Date.now()))}
|
|
2340
|
+
`);
|
|
2341
|
+
}
|
|
2342
|
+
}
|
|
2343
|
+
});
|
|
2255
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
|
+
};
|
|
2256
2352
|
var validateCmd = defineCommand({
|
|
2257
2353
|
meta: {
|
|
2258
2354
|
name: "validate",
|
|
@@ -2275,6 +2371,10 @@ var validateCmd = defineCommand({
|
|
|
2275
2371
|
"schema-version": {
|
|
2276
2372
|
type: "string",
|
|
2277
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"
|
|
2278
2378
|
}
|
|
2279
2379
|
},
|
|
2280
2380
|
run: async ({ args }) => {
|
|
@@ -2288,6 +2388,14 @@ var validateCmd = defineCommand({
|
|
|
2288
2388
|
process.stderr.write("\u274C invalid\n");
|
|
2289
2389
|
for (const e of errors) process.stderr.write(` - ${e}
|
|
2290
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
|
+
}
|
|
2291
2399
|
process.exit(1);
|
|
2292
2400
|
}
|
|
2293
2401
|
}
|
|
@@ -2319,13 +2427,20 @@ var adaptCmd = defineCommand({
|
|
|
2319
2427
|
effort: {
|
|
2320
2428
|
type: "string",
|
|
2321
2429
|
description: 'Effort label to stamp into the envelope (e.g. "max" or "low")'
|
|
2430
|
+
},
|
|
2431
|
+
transcript: {
|
|
2432
|
+
type: "string",
|
|
2433
|
+
description: "Path to the session transcript (the main .jsonl); when the native envelope carries no per-model usage \u2014 a wall-clock kill leaves it empty (issue #39) \u2014 telemetry is recovered from the transcript tree (main + subagents) so cost is real, not $0.00 (issue #36)"
|
|
2322
2434
|
}
|
|
2323
2435
|
},
|
|
2324
2436
|
run: async ({ args }) => {
|
|
2325
2437
|
const envelope = unwrapAdapt(
|
|
2326
2438
|
adapt(requireAdapterName(args.adapter), readJSONOrAbsent(args.native), args["agent-file"], {
|
|
2327
2439
|
route: args.route,
|
|
2328
|
-
effort: args.effort
|
|
2440
|
+
effort: args.effort,
|
|
2441
|
+
...args.transcript ? {
|
|
2442
|
+
transcriptFallback: () => transcriptFallbackFrom(args.transcript)
|
|
2443
|
+
} : {}
|
|
2329
2444
|
})
|
|
2330
2445
|
);
|
|
2331
2446
|
process.stdout.write(`${JSON.stringify(envelope, null, 2)}
|
|
@@ -2493,11 +2608,7 @@ var printSchemaCmd = defineCommand({
|
|
|
2493
2608
|
run: async ({ args }) => {
|
|
2494
2609
|
const schemaKind = requireSchemaKind(args.name);
|
|
2495
2610
|
const schemaPath = requireSchemaPath(schemaKind, args["schema-version"]);
|
|
2496
|
-
|
|
2497
|
-
const enforcementSchema = Object.fromEntries(
|
|
2498
|
-
Object.entries(schema).filter(([key2]) => key2 !== "$schema")
|
|
2499
|
-
);
|
|
2500
|
-
process.stdout.write(`${JSON.stringify(enforcementSchema, null, 2)}
|
|
2611
|
+
process.stdout.write(`${printableSchema(schemaPath)}
|
|
2501
2612
|
`);
|
|
2502
2613
|
}
|
|
2503
2614
|
});
|
|
@@ -2733,7 +2844,7 @@ var main = defineCommand({
|
|
|
2733
2844
|
meta: {
|
|
2734
2845
|
name: "code-review",
|
|
2735
2846
|
version: packageVersion,
|
|
2736
|
-
description: "Deterministic commenter for agentic PR review \u2014 gather, render, inline, post, adapt, extract, validate-patches, cost, check-cost, validate, stop-gate, budget-hook,
|
|
2847
|
+
description: "Deterministic commenter for agentic PR review \u2014 gather, render, inline, post, adapt, extract, validate-patches, cost, check-cost, validate, stop-gate, budget-hook, print-settings, and deadline"
|
|
2737
2848
|
},
|
|
2738
2849
|
subCommands: {
|
|
2739
2850
|
gather: gatherCmd,
|
|
@@ -2749,7 +2860,8 @@ var main = defineCommand({
|
|
|
2749
2860
|
"print-schema": printSchemaCmd,
|
|
2750
2861
|
"stop-gate": stopGateCmd,
|
|
2751
2862
|
"budget-hook": budgetHookCmd,
|
|
2752
|
-
"print-settings": printSettingsCmd
|
|
2863
|
+
"print-settings": printSettingsCmd,
|
|
2864
|
+
deadline: deadlineCmd
|
|
2753
2865
|
}
|
|
2754
2866
|
});
|
|
2755
2867
|
if (!process.env["VITEST"]) {
|