@jphutchins/code-review 0.1.0-alpha.42 → 0.1.0-alpha.44
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/README.md +32 -44
- package/dist/index.js +68 -65
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/schema/VERSIONING.md +18 -15
- package/schema/findings.schema.json +16 -3
package/README.md
CHANGED
|
@@ -100,61 +100,49 @@ links to:
|
|
|
100
100
|
downstream tool) SHOULD base64-decode and parse that marker rather than parse the comment's prose.
|
|
101
101
|
Embedding in the comment (rather than only linking the artifact) keeps the pointer from expiring
|
|
102
102
|
with artifact retention; when the encoded findings are too large to embed, the sticky falls back to
|
|
103
|
-
a `<!-- code-review:findings-json <url> -->` link marker instead
|
|
104
|
-
agent's draft and lacks the surfaced fields below) — the shared serializer is
|
|
103
|
+
a `<!-- code-review:findings-json <url> -->` link marker instead. The shared serializer is
|
|
105
104
|
[`src/surface.ts`](src/surface.ts).
|
|
106
105
|
|
|
107
|
-
The embedded document is the **
|
|
108
|
-
|
|
109
|
-
[`schema/findings.schema.json`](schema/findings.schema.json) validates
|
|
110
|
-
|
|
111
|
-
|
|
106
|
+
The embedded document is the agent's **complete** findings document — the same `schema_version`
|
|
107
|
+
0.9.0 contract the review agent is held to and
|
|
108
|
+
[`schema/findings.schema.json`](schema/findings.schema.json) validates, and the same object the
|
|
109
|
+
comment is rendered from. It is embedded verbatim: no field is added or dropped, so the machine
|
|
110
|
+
channel can never carry less than, or drift from, the rendered prose.
|
|
112
111
|
|
|
113
112
|
```json
|
|
114
113
|
{
|
|
115
|
-
"schema_version": "0.
|
|
114
|
+
"schema_version": "0.9.0",
|
|
116
115
|
"verdict": "comment",
|
|
117
116
|
"summary": "...",
|
|
118
|
-
"convergence": { "score": 1, "threshold": 1, "converged": true },
|
|
119
|
-
"round": 4,
|
|
120
|
-
"scope_metastasis": {
|
|
121
|
-
"decision_prompt": "Findings keep recurring in the same mechanism across consecutive rounds — each fix keeps enabling the next finding in that machinery. This is a decision, not a directive: state in your summary whether you are committing to the expanding scope (plan the remaining facets of the recurring mechanism(s) above as one unit) or narrowing the scope so the recurrence stops.",
|
|
122
|
-
"recurring": [
|
|
123
|
-
{ "code": "mixin-field-guard-gap", "consecutive_rounds": 4, "start_round": 1 }
|
|
124
|
-
]
|
|
125
|
-
},
|
|
126
117
|
"findings": []
|
|
127
118
|
}
|
|
128
119
|
```
|
|
129
120
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
the next post reads it back. The same compact marker is emitted when the embedded payload is too
|
|
156
|
-
large and the whole-document marker falls back to the artifact link — an oversized review's stop
|
|
157
|
-
signal stays readable and can be carried forward.
|
|
121
|
+
The deterministic **stop signal** for an iterating author-agent rides its own compact marker beside
|
|
122
|
+
the findings blob, `<!-- code-review:signal;base64 <base64> -->`, whose decoded payload is
|
|
123
|
+
`{ "schema_version": "0.8.0", "round": <n>, "convergence": { "score": <s>, "threshold": <t>, "converged": <bool> } }`.
|
|
124
|
+
`round` is the count of completed full-review rounds; `convergence.score` sums each finding and
|
|
125
|
+
systemic problem's `floor(severity) + max(0, ceiling − floor) × confidence` (ceilings critical 4 ·
|
|
126
|
+
major 2 · minor 1 · nit 0; floors critical `threshold + 0.01` · major 0.5 · else 0), rounded to 2
|
|
127
|
+
decimals; `threshold` defaults to 1, and `converged` = score ≤ threshold as a literal
|
|
128
|
+
boolean — `converged: true` means the last completed round is at or below the tolerance, so another
|
|
129
|
+
iteration round is not warranted. The commenter computes the signal from the review's own severities
|
|
130
|
+
(the agent never writes it); it appears once at least one full-review round has completed and is
|
|
131
|
+
carried verbatim afterward — a mechanic (CI-fix) pass or an envelope-loss notice re-emits the last
|
|
132
|
+
completed round's signal rather than re-deriving it, so an operator changing `convergence_threshold`
|
|
133
|
+
mid-PR cannot flip a stored `converged`, and a notice never fabricates a stop signal for a run that
|
|
134
|
+
produced no review. Both markers survive the "review in progress" banner, which replaces only the
|
|
135
|
+
sticky's prose and carries them forward verbatim.
|
|
136
|
+
|
|
137
|
+
Cross-round recurrence (the sticky's "Scope metastasis" warning) is carried structurally in the
|
|
138
|
+
`<!-- code-review:rounds;base64 <base64> -->` marker — per-round severity counts and mechanism
|
|
139
|
+
frequencies — from which the re-review seed re-derives the advisory `scope_metastasis` entry it
|
|
140
|
+
hands the next-round agent. It is deliberately NOT embedded in the findings blob: the blob is the
|
|
141
|
+
agent's own document, and a recurrence claim is round state the commenter owns. Each inline review
|
|
142
|
+
comment embeds only its own finding (a `schema_version` + one-finding fragment), and the
|
|
143
|
+
review-object body only links the sticky — so the **sticky is the sole documented decode surface**
|
|
144
|
+
for the whole-document marker; a decoding agent reads it there. The review body is written only after
|
|
145
|
+
the sticky exists (a failed sticky write aborts the run first), so it never carries the blob itself.
|
|
158
146
|
- **`code-review-transcript`** — the full Claude Code session transcripts for the triage and review
|
|
159
147
|
phases. This is advisory/auditability only: it is never read by the comment job and never affects
|
|
160
148
|
what gets posted.
|
package/dist/index.js
CHANGED
|
@@ -31,6 +31,7 @@ var LineNumber = t.refinement(
|
|
|
31
31
|
"LineNumber"
|
|
32
32
|
);
|
|
33
33
|
var Confidence = t.refinement(t.number, (n) => n >= 0 && n <= 1, "Confidence");
|
|
34
|
+
var Likelihood = t.refinement(t.number, (n) => n >= 0 && n <= 1, "Likelihood");
|
|
34
35
|
var SCHEMA_VERSION_RE = /^(0|[1-9]\d*)\.(\d+)\.(\d+)(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
|
|
35
36
|
var SchemaVersion = t.refinement(
|
|
36
37
|
t.string,
|
|
@@ -55,7 +56,8 @@ var FindingShape = t.intersection([
|
|
|
55
56
|
title: t.string,
|
|
56
57
|
description: t.string,
|
|
57
58
|
reasoning: t.string,
|
|
58
|
-
confidence: Confidence
|
|
59
|
+
confidence: Confidence,
|
|
60
|
+
likelihood: Likelihood
|
|
59
61
|
}),
|
|
60
62
|
FindingRuleCodec,
|
|
61
63
|
t.partial({
|
|
@@ -75,7 +77,8 @@ var SystemicRequired = t.type({
|
|
|
75
77
|
description: t.string,
|
|
76
78
|
severity: SeverityCodec,
|
|
77
79
|
reasoning: t.string,
|
|
78
|
-
confidence: Confidence
|
|
80
|
+
confidence: Confidence,
|
|
81
|
+
likelihood: Likelihood
|
|
79
82
|
});
|
|
80
83
|
var SystemicOptional = t.partial({
|
|
81
84
|
finding_codes: t.array(t.string),
|
|
@@ -202,7 +205,7 @@ var TestSummaryCodec = t.intersection([
|
|
|
202
205
|
failures: t.array(TestFailureCodec)
|
|
203
206
|
})
|
|
204
207
|
]);
|
|
205
|
-
var DEFAULT_SCHEMA_VERSION = "0.
|
|
208
|
+
var DEFAULT_SCHEMA_VERSION = "0.9.0";
|
|
206
209
|
var incompleteFindings = (summary) => ({
|
|
207
210
|
schema_version: DEFAULT_SCHEMA_VERSION,
|
|
208
211
|
summary,
|
|
@@ -585,41 +588,39 @@ var computeSameRootNotes = (priorRounds, findings, currentSha) => {
|
|
|
585
588
|
}
|
|
586
589
|
return Object.fromEntries(entries);
|
|
587
590
|
};
|
|
588
|
-
var
|
|
591
|
+
var CONVERGENCE_CEILINGS = { critical: 4, major: 2, minor: 1, nit: 0 };
|
|
592
|
+
var CRITICAL_FLOOR_MARGIN = 0.01;
|
|
589
593
|
var DEFAULT_CONVERGENCE_THRESHOLD = 1;
|
|
590
|
-
var
|
|
591
|
-
var
|
|
592
|
-
|
|
594
|
+
var convergenceFloor = (severity, threshold) => severity === "critical" ? threshold + CRITICAL_FLOOR_MARGIN : severity === "major" ? 0.5 : 0;
|
|
595
|
+
var round2 = (n) => Math.round((n + Number.EPSILON) * 100) / 100;
|
|
596
|
+
var convergenceScore = (doc, threshold) => round2(
|
|
597
|
+
[...doc.findings, ...doc.systemic_problems ?? []].reduce(
|
|
598
|
+
(sum, { severity, confidence, likelihood }) => {
|
|
599
|
+
const floor = convergenceFloor(severity, threshold);
|
|
600
|
+
return sum + floor + Math.max(0, CONVERGENCE_CEILINGS[severity] - floor) * confidence * likelihood;
|
|
601
|
+
},
|
|
602
|
+
0
|
|
603
|
+
)
|
|
604
|
+
);
|
|
605
|
+
var convergenceSummary = (doc, threshold = DEFAULT_CONVERGENCE_THRESHOLD) => {
|
|
606
|
+
const { score, converged } = convergenceSignal(doc, threshold);
|
|
593
607
|
return converged ? `**Convergence** \u{1F3C1} ${String(score)} \u2264 ${String(threshold)} \u2014 converged` : `**Convergence** \u{1F504} ${String(score)} > ${String(threshold)} \u2014 iterating`;
|
|
594
608
|
};
|
|
595
609
|
var SURFACE_SCHEMA_VERSION = "0.8.0";
|
|
596
|
-
var convergenceSignal = (
|
|
597
|
-
const score = convergenceScore(
|
|
610
|
+
var convergenceSignal = (doc, threshold = DEFAULT_CONVERGENCE_THRESHOLD) => {
|
|
611
|
+
const score = convergenceScore(doc, threshold);
|
|
598
612
|
return { score, threshold, converged: score <= threshold };
|
|
599
613
|
};
|
|
600
|
-
var signalForRound = (round,
|
|
601
|
-
var surfaceFindings = (findings, signal, scopeMetastasis = null) => {
|
|
602
|
-
const agentDoc = Object.fromEntries(
|
|
603
|
-
Object.entries(findings).filter(
|
|
604
|
-
([key2]) => key2 !== "round" && key2 !== "convergence" && key2 !== "scope_metastasis"
|
|
605
|
-
)
|
|
606
|
-
);
|
|
607
|
-
return {
|
|
608
|
-
...agentDoc,
|
|
609
|
-
schema_version: SURFACE_SCHEMA_VERSION,
|
|
610
|
-
...signal === null ? {} : signal,
|
|
611
|
-
...scopeMetastasis === null ? {} : { scope_metastasis: scopeMetastasis }
|
|
612
|
-
};
|
|
613
|
-
};
|
|
614
|
+
var signalForRound = (round, doc, threshold = DEFAULT_CONVERGENCE_THRESHOLD) => ({ round, convergence: convergenceSignal(doc, threshold) });
|
|
614
615
|
var signalMarker = (signal) => `<!-- code-review:signal;base64 ${Buffer.from(
|
|
615
616
|
JSON.stringify({ schema_version: SURFACE_SCHEMA_VERSION, ...signal }),
|
|
616
617
|
"utf-8"
|
|
617
618
|
).toString("base64")} -->`;
|
|
618
|
-
var
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
619
|
+
var joinSignalMarker = (base, marker) => base === "" ? marker : `${base}
|
|
620
|
+
${marker}`;
|
|
621
|
+
var surfacedFindingsPointer = (findings, signal, jsonUrl) => {
|
|
622
|
+
const marker = findingsPointer(findings, jsonUrl);
|
|
623
|
+
return signal === null ? marker : joinSignalMarker(marker, signalMarker(signal));
|
|
623
624
|
};
|
|
624
625
|
var SIGNAL_RE = /<!-- code-review:signal;base64 ([A-Za-z0-9+/=]+) -->/;
|
|
625
626
|
var parseSignalMarker = (body) => {
|
|
@@ -630,8 +631,7 @@ var parseSignalMarker = (body) => {
|
|
|
630
631
|
var parseSurfaceSignal = (doc) => {
|
|
631
632
|
if (typeof doc !== "object" || doc === null || Array.isArray(doc)) return null;
|
|
632
633
|
const o = doc;
|
|
633
|
-
|
|
634
|
-
if (typeof declared !== "string" || !SURFACE_SCHEMA_VERSIONS.includes(declared)) return null;
|
|
634
|
+
if (!isSurfaceVersion(o["schema_version"])) return null;
|
|
635
635
|
const round = o["round"];
|
|
636
636
|
const convergence = o["convergence"];
|
|
637
637
|
if (typeof round !== "number" || !Number.isSafeInteger(round) || round < 1) return null;
|
|
@@ -646,11 +646,11 @@ var parseSurfaceSignal = (doc) => {
|
|
|
646
646
|
};
|
|
647
647
|
};
|
|
648
648
|
var SURFACE_SCHEMA_VERSIONS = ["0.7.0", SURFACE_SCHEMA_VERSION];
|
|
649
|
+
var isSurfaceVersion = (version) => typeof version === "string" && SURFACE_SCHEMA_VERSIONS.includes(version);
|
|
649
650
|
var stripSurfaceFields = (doc) => {
|
|
650
651
|
if (typeof doc !== "object" || doc === null || Array.isArray(doc)) return doc;
|
|
651
652
|
const o = doc;
|
|
652
|
-
|
|
653
|
-
if (typeof declared !== "string" || !SURFACE_SCHEMA_VERSIONS.includes(declared)) return doc;
|
|
653
|
+
if (!isSurfaceVersion(o["schema_version"])) return doc;
|
|
654
654
|
const rest = Object.fromEntries(
|
|
655
655
|
Object.entries(o).filter(([key2]) => key2 !== "convergence" && key2 !== "round")
|
|
656
656
|
);
|
|
@@ -674,12 +674,9 @@ var projectPatch = (patch) => {
|
|
|
674
674
|
return typeof lowered === "string" ? { kind: "suggestion", text: escapeFence(lowered) } : { kind: "patch", raw: escapeFence(patch) };
|
|
675
675
|
};
|
|
676
676
|
var formatConfidence = (n) => n.toFixed(2);
|
|
677
|
-
var reviewBodyPointer = (headSha, stickyUrl
|
|
677
|
+
var reviewBodyPointer = (headSha, stickyUrl) => {
|
|
678
678
|
const sha7 = headSha.slice(0, 7);
|
|
679
|
-
|
|
680
|
-
return marker ? `${marker}
|
|
681
|
-
|
|
682
|
-
${linkLine}` : linkLine;
|
|
679
|
+
return stickyUrl ? `\u{1F916} Automated code review for \`${sha7}\` \u2014 see the [summary comment](${stickyUrl}) for the verdict, walkthrough, and cost.` : `\u{1F916} Automated code review for \`${sha7}\` \u2014 see the summary comment for the verdict, walkthrough, and cost.`;
|
|
683
680
|
};
|
|
684
681
|
var asRecord = (u) => typeof u === "object" && u !== null && !Array.isArray(u) ? u : null;
|
|
685
682
|
var errMsg = (e) => e instanceof Error ? e.message : String(e);
|
|
@@ -1057,9 +1054,7 @@ var render = (input) => {
|
|
|
1057
1054
|
const rounds = input.rounds ?? [];
|
|
1058
1055
|
const sameRootNotes = input.sameRootNotes ?? computeSameRootNotes(rounds.slice(0, -1), input.findings.findings);
|
|
1059
1056
|
const isFullReviewRound = (input.convergenceRound ?? (isConvergenceRound(route, incomplete) && rounds.length > 0)) && isReviewVerdict(input.findings.verdict);
|
|
1060
|
-
const convergenceCounts = rounds[rounds.length - 1] ?? computeRoundCounts(input.findings);
|
|
1061
1057
|
const advisoryAllowed = isFullReviewRound;
|
|
1062
|
-
const scopeMetastasis = input.scopeMetastasis !== void 0 ? input.scopeMetastasis : advisoryAllowed ? computeScopeMetastasis(rounds) : null;
|
|
1063
1058
|
return eta.renderString(input.template, {
|
|
1064
1059
|
findings: input.findings,
|
|
1065
1060
|
envelope: input.envelope,
|
|
@@ -1075,7 +1070,7 @@ var render = (input) => {
|
|
|
1075
1070
|
reviewedSha: input.reviewedSha ?? "0000000000000000000000000000000000000000",
|
|
1076
1071
|
postedAt: input.postedAt ?? "",
|
|
1077
1072
|
severityCounts,
|
|
1078
|
-
convergenceSummary: isFullReviewRound ? convergenceSummary(
|
|
1073
|
+
convergenceSummary: isFullReviewRound ? convergenceSummary(input.findings, input.convergenceThreshold) : "",
|
|
1079
1074
|
strays: (input.strays ?? []).map((f) => sanitizeFinding(f, input.answeredNotes)),
|
|
1080
1075
|
systemic: (input.findings.systemic_problems ?? []).map(sanitizeSystemic),
|
|
1081
1076
|
unanchoredCount: input.unanchoredCount ?? 0,
|
|
@@ -1085,13 +1080,12 @@ var render = (input) => {
|
|
|
1085
1080
|
findingsPointer: input.findingsPointer ?? surfacedFindingsPointer(
|
|
1086
1081
|
input.findings,
|
|
1087
1082
|
// The fallback embeds a signal exactly when the badge renders — never beside a suppressed
|
|
1088
|
-
// badge, and
|
|
1083
|
+
// badge, and scores the same findings the badge does. It assumes a post-style history (the
|
|
1089
1084
|
// caller appends this run's counts last), numbering the round exactly as the trajectory
|
|
1090
1085
|
// label does; post always supplies the marker, so this path cannot disagree with it in
|
|
1091
1086
|
// production (issue #141 review r4).
|
|
1092
|
-
isFullReviewRound && rounds.length > 0 ? signalForRound(rounds.length,
|
|
1093
|
-
input.jsonUrl
|
|
1094
|
-
scopeMetastasis
|
|
1087
|
+
isFullReviewRound && rounds.length > 0 ? signalForRound(rounds.length, input.findings, input.convergenceThreshold) : null,
|
|
1088
|
+
input.jsonUrl
|
|
1095
1089
|
),
|
|
1096
1090
|
roundsMarker: roundsMarker(rounds),
|
|
1097
1091
|
roundsSummary: roundsSummary(rounds, input.roundCount),
|
|
@@ -1672,6 +1666,14 @@ var findingsTable = [
|
|
|
1672
1666
|
},
|
|
1673
1667
|
{
|
|
1674
1668
|
minor: "0.6",
|
|
1669
|
+
defaultVersion: "0.6.0",
|
|
1670
|
+
schemaFile: "findings.schema.json",
|
|
1671
|
+
codec: FindingsCodec,
|
|
1672
|
+
normalize: identity,
|
|
1673
|
+
latest: false
|
|
1674
|
+
},
|
|
1675
|
+
{
|
|
1676
|
+
minor: "0.9",
|
|
1675
1677
|
defaultVersion: DEFAULT_SCHEMA_VERSION,
|
|
1676
1678
|
schemaFile: "findings.schema.json",
|
|
1677
1679
|
codec: FindingsCodec,
|
|
@@ -2042,8 +2044,8 @@ var commentPayload = (c) => ({
|
|
|
2042
2044
|
...c.start_line !== void 0 && c.start_side !== void 0 ? { start_line: c.start_line, start_side: c.start_side } : {},
|
|
2043
2045
|
body: formatMarkdown(c.body)
|
|
2044
2046
|
});
|
|
2045
|
-
var postInlineReview = async (repo, prNumber, headSha, comments, inDiff, stickyUrl,
|
|
2046
|
-
const pointer = reviewBodyPointer(headSha, stickyUrl
|
|
2047
|
+
var postInlineReview = async (repo, prNumber, headSha, comments, inDiff, stickyUrl, ghApi) => {
|
|
2048
|
+
const pointer = reviewBodyPointer(headSha, stickyUrl);
|
|
2047
2049
|
const reviewBody = (withComments) => JSON.stringify({
|
|
2048
2050
|
body: pointer,
|
|
2049
2051
|
commit_id: headSha,
|
|
@@ -2273,10 +2275,9 @@ var post = async (input, ghApi = runGhApi) => {
|
|
|
2273
2275
|
const emptyMechanicWouldBury = (route, incomplete) => route === "mechanic" && !incomplete && findings.findings.length === 0 && existingSticky !== null && priorIsFullReview(existingSticky.body);
|
|
2274
2276
|
const priorRounds = existingSticky !== null ? parseRounds(existingSticky.body) : [];
|
|
2275
2277
|
const priorSignal = existingSticky === null ? null : parseSignalMarker(existingSticky.body) ?? parseSurfaceSignal(parseFindingsMarker(existingSticky.body));
|
|
2276
|
-
const findingsMarkerFor = (findings2, signal2
|
|
2277
|
-
const pointer = surfacedFindingsPointer(findings2, signal2, input.jsonUrl
|
|
2278
|
-
return signal2 !== null || priorSignal === null ? pointer :
|
|
2279
|
-
${signalMarker(priorSignal)}`;
|
|
2278
|
+
const findingsMarkerFor = (findings2, signal2) => {
|
|
2279
|
+
const pointer = surfacedFindingsPointer(findings2, signal2, input.jsonUrl);
|
|
2280
|
+
return signal2 !== null || priorSignal === null ? pointer : joinSignalMarker(pointer, signalMarker(priorSignal));
|
|
2280
2281
|
};
|
|
2281
2282
|
const leaveInPlace = (message) => {
|
|
2282
2283
|
process.stderr.write(
|
|
@@ -2430,8 +2431,8 @@ ${dropNote}` : ""}`,
|
|
|
2430
2431
|
inlineDisposition: { kind: "no-envelope" },
|
|
2431
2432
|
runUrl: input.runUrl,
|
|
2432
2433
|
jsonUrl: input.jsonUrl,
|
|
2433
|
-
// Same signal rule as the main path:
|
|
2434
|
-
//
|
|
2434
|
+
// Same signal rule as the main path: a completed-review doc and an error-verdict doc alike
|
|
2435
|
+
// ride the prior signal on the compact marker, never inside the blob.
|
|
2435
2436
|
findingsPointer: findingsMarkerFor(
|
|
2436
2437
|
findings,
|
|
2437
2438
|
isReviewVerdict(findings.verdict) ? priorSignal : null
|
|
@@ -2489,20 +2490,19 @@ ${dropNote}` : ""}`,
|
|
|
2489
2490
|
roundNumber
|
|
2490
2491
|
)
|
|
2491
2492
|
] : priorRounds;
|
|
2492
|
-
const signal = isRound ? signalForRound(roundNumber,
|
|
2493
|
-
const
|
|
2494
|
-
const
|
|
2495
|
-
const
|
|
2496
|
-
surfaceFindings(findings, signal, scopeMetastasis),
|
|
2497
|
-
input.jsonUrl
|
|
2498
|
-
);
|
|
2493
|
+
const signal = isRound ? signalForRound(roundNumber, findings, input.convergenceThreshold) : thisIncomplete || !isReviewVerdict(findings.verdict) ? null : priorSignal;
|
|
2494
|
+
const findingsMarker = findingsMarkerFor(findings, signal);
|
|
2495
|
+
const markerForm = findingsMarkerForm(findings, input.jsonUrl);
|
|
2496
|
+
const signalNote = signal !== null || priorSignal !== null ? " (the stop signal still rides the compact marker)" : "";
|
|
2499
2497
|
if (markerForm === "link") {
|
|
2500
2498
|
process.stderr.write(
|
|
2501
|
-
|
|
2499
|
+
`Warning: the findings-json blob exceeds the embed limit \u2014 degraded to the jsonUrl-link form; a decoding agent must fetch the artifact for the findings${signalNote}
|
|
2500
|
+
`
|
|
2502
2501
|
);
|
|
2503
2502
|
} else if (markerForm === "omitted") {
|
|
2504
2503
|
process.stderr.write(
|
|
2505
|
-
|
|
2504
|
+
`Warning: the findings-json blob exceeds the embed limit and no --json-url was given \u2014 the embedded findings seed is dropped from the posted surfaces${signalNote}
|
|
2505
|
+
`
|
|
2506
2506
|
);
|
|
2507
2507
|
}
|
|
2508
2508
|
const commonRenderInput = {
|
|
@@ -2521,7 +2521,6 @@ ${dropNote}` : ""}`,
|
|
|
2521
2521
|
sameRootNotes,
|
|
2522
2522
|
answeredNotes: reRaisedNotes,
|
|
2523
2523
|
answeredReRaiseNote: answeredDropNote,
|
|
2524
|
-
scopeMetastasis,
|
|
2525
2524
|
roundCount: signal?.round ?? priorSignal?.round ?? priorRounds.length,
|
|
2526
2525
|
convergenceThreshold: input.convergenceThreshold,
|
|
2527
2526
|
convergenceRound: isRound,
|
|
@@ -2570,7 +2569,6 @@ ${dropNote}` : ""}`,
|
|
|
2570
2569
|
comments,
|
|
2571
2570
|
inDiff,
|
|
2572
2571
|
stickyRef?.url,
|
|
2573
|
-
findingsMarker,
|
|
2574
2572
|
ghApi
|
|
2575
2573
|
);
|
|
2576
2574
|
process.stderr.write(
|
|
@@ -3683,7 +3681,7 @@ var resolvePrices = (pricesArg) => {
|
|
|
3683
3681
|
return { kind: "absent", path: bundledPath("schema", "prices.example.json") };
|
|
3684
3682
|
};
|
|
3685
3683
|
var TEST_REPORT_DESCRIPTION = 'Path to a JSON test summary: {"passed": number, "failed": number, "total": number, "failures"?: [{"name": string, "message"?: string}]}';
|
|
3686
|
-
var CONVERGENCE_THRESHOLD_DESCRIPTION = "Advisory convergence tolerance: the
|
|
3684
|
+
var CONVERGENCE_THRESHOLD_DESCRIPTION = "Advisory convergence tolerance: the per-finding convergence score (each finding's floor + confidence-weighted headroom; ceilings critical 4 \xB7 major 2 \xB7 minor 1 \xB7 nit 0) at or below which the sticky reads as converged (default: 1)";
|
|
3687
3685
|
var renderCmd = defineCommand({
|
|
3688
3686
|
meta: {
|
|
3689
3687
|
name: "render",
|
|
@@ -4166,6 +4164,8 @@ ${printableSchema(schemaPath)}
|
|
|
4166
4164
|
}
|
|
4167
4165
|
}
|
|
4168
4166
|
});
|
|
4167
|
+
var isSurfaceStampedDoc = (doc) => typeof doc === "object" && doc !== null && !Array.isArray(doc) && doc["schema_version"] === SURFACE_SCHEMA_VERSION;
|
|
4168
|
+
var withoutScopeMetastasis = (doc) => typeof doc === "object" && doc !== null && !Array.isArray(doc) ? Object.fromEntries(Object.entries(doc).filter(([key2]) => key2 !== "scope_metastasis")) : doc;
|
|
4169
4169
|
var seedDraftCmd = defineCommand({
|
|
4170
4170
|
meta: {
|
|
4171
4171
|
name: "seed-draft",
|
|
@@ -4239,7 +4239,10 @@ var seedDraftCmd = defineCommand({
|
|
|
4239
4239
|
})();
|
|
4240
4240
|
return typeof raw === "object" && raw !== null && "body" in raw && typeof raw.body === "string" ? raw.body : null;
|
|
4241
4241
|
})();
|
|
4242
|
-
const
|
|
4242
|
+
const parsedPrior = priorBody === null ? null : parseFindingsMarker(priorBody);
|
|
4243
|
+
const strippedPrior = parsedPrior === null ? null : stripSurfaceFields(
|
|
4244
|
+
isSurfaceStampedDoc(parsedPrior) ? parsedPrior : withoutScopeMetastasis(parsedPrior)
|
|
4245
|
+
);
|
|
4243
4246
|
const priorFindings = (() => {
|
|
4244
4247
|
if (strippedPrior === null || typeof strippedPrior !== "object" || Array.isArray(strippedPrior))
|
|
4245
4248
|
return strippedPrior;
|