fix(review): give the extension host the same report body the core renders

`terminal_mode_tests::actual_cli_review_report_host_matches_legacy_and_core_keeps_inline_authority`
failed deterministically on `main`, alone and in the safety filter: the
ReviewHost path and the pure-Rust path are supposed to render byte-identical
bodies, and they had drifted twice.

`5573bab7ca` gave every review body a machine-readable severity tally
(`<!-- codewhale-review: {...} -->`) in the core, but not in the TypeScript
adapter the extension host actually runs, so every hosted review lost the line
a merge gate is meant to parse. `1f40f4ba05` likewise moved a posted body's
non-committable fix from a `text` fence to a `diff` fence in the core only.

Both are now in `review-adapter.ts`, mirroring `render_review_summary`:
counts derive from the same severities, and `preexisting` is decided by
`authorship`, exactly as `review_severity_tally` does. The frozen parity
fixture and the one stale `text` assertion move with them.

The harness digest in `tier.rs` moves too, because it pins the built
`dist/builtin/harness.mjs` and the core refuses to activate a module whose
digest differs. The build is deterministic: two rebuilds produced the same
`ad24207f…`.

Verification: `node --test test/review-adapters.test.mjs` 13 passed, 0 failed.
`terminal_mode_tests` + `auto_review|authority|sandbox|review` filters:
933 passed, 0 failed. Before this change the same filter was 932 passed,
1 failed (the test above), and alone it failed too.
This commit is contained in:
CodeWhale Bot committed 2026-10-22 11:29:49 -07:00
1 parent 4f1d7ab56e
commit 877d013669
8 files changed
+43 -11

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
{
"modules": {
"harness": "782094d964894c91fc74da1704d3a793163e9605cc802dd7760578b5ba83135d",
"harness": "ad24207f93d963dcffe1967f6863f416117d9acd67cdfccbcef59c12ccb39f92",
"mcp": "3a64805433d63f34822ae71230a432ccdbd956174bc8575d5a0a001fda8c50cf"
}
}
+12 -1
View File
@@ -788,7 +788,7 @@ function report(input) {
if (replacement !== void 0 && trim(replacement).length) {
const codeFence = fence(replacement);
out += `
${codeFence}${posted ? "text" : "suggestion"}
${codeFence}${posted ? "diff" : "suggestion"}
`;
for (const line of replacement.split("\n")) out += ` ${line}
`;
@@ -799,6 +799,17 @@ function report(input) {
out += "\n";
}
if (assessment.length) out += "### Assessment\n\n" + trim(assessment) + "\n\n";
const tally = { blocker: 0, concern: 0, nit: 0, introduced: 0, preexisting: 0 };
for (const item of issues) {
const issue = row3(item), severity = text3(issue.severity);
if (severity === "blocker") tally.blocker += 1;
else if (severity === "concern") tally.concern += 1;
else if (severity === "nit") tally.nit += 1;
if (optional(issue.authorship) === "preexisting") tally.preexisting += 1;
else tally.introduced += 1;
}
out += `<!-- codewhale-review: {"blocker":${tally.blocker},"concern":${tally.concern},"nit":${tally.nit},"introduced":${tally.introduced},"preexisting":${tally.preexisting}} -->
`;
return out;
}
function transformReviewSnapshot(operation, value) {
@@ -19,7 +19,7 @@ var __export = (target, all) => {
var define_BUILTIN_MODULE_DIGESTS_default;
var init_define_BUILTIN_MODULE_DIGESTS = __esm({
"<define:__BUILTIN_MODULE_DIGESTS__>"() {
define_BUILTIN_MODULE_DIGESTS_default = { harness: "782094d964894c91fc74da1704d3a793163e9605cc802dd7760578b5ba83135d", mcp: "3a64805433d63f34822ae71230a432ccdbd956174bc8575d5a0a001fda8c50cf" };
define_BUILTIN_MODULE_DIGESTS_default = { harness: "ad24207f93d963dcffe1967f6863f416117d9acd67cdfccbcef59c12ccb39f92", mcp: "3a64805433d63f34822ae71230a432ccdbd956174bc8575d5a0a001fda8c50cf" };
}
});
+12 -1
View File
@@ -632,7 +632,7 @@ function report(input) {
if (replacement !== void 0 && trim(replacement).length) {
const codeFence = fence(replacement);
out += `
${codeFence}${posted ? "text" : "suggestion"}
${codeFence}${posted ? "diff" : "suggestion"}
`;
for (const line of replacement.split("\n")) out += ` ${line}
`;
@@ -643,6 +643,17 @@ function report(input) {
out += "\n";
}
if (assessment.length) out += "### Assessment\n\n" + trim(assessment) + "\n\n";
const tally = { blocker: 0, concern: 0, nit: 0, introduced: 0, preexisting: 0 };
for (const item of issues) {
const issue = row3(item), severity = text3(issue.severity);
if (severity === "blocker") tally.blocker += 1;
else if (severity === "concern") tally.concern += 1;
else if (severity === "nit") tally.nit += 1;
if (optional(issue.authorship) === "preexisting") tally.preexisting += 1;
else tally.introduced += 1;
}
out += `<!-- codewhale-review: {"blocker":${tally.blocker},"concern":${tally.concern},"nit":${tally.nit},"introduced":${tally.introduced},"preexisting":${tally.preexisting}} -->
`;
return out;
}
function transformReviewSnapshot(operation, value) {
@@ -87,7 +87,7 @@ function report(input: Row): string {
const replacement = optional(suggestion.replacement)
if (replacement !== undefined && trim(replacement).length) {
const codeFence = fence(replacement)
out += `\n ${codeFence}${posted ? 'text' : 'suggestion'}\n`
out += `\n ${codeFence}${posted ? 'diff' : 'suggestion'}\n`
for (const line of replacement.split('\n')) out += ` ${line}\n`
out += ` ${codeFence}\n`
}
@@ -95,6 +95,16 @@ function report(input: Row): string {
out += '\n'
}
if (assessment.length) out += '### Assessment\n\n' + trim(assessment) + '\n\n'
const tally = {blocker: 0, concern: 0, nit: 0, introduced: 0, preexisting: 0}
for (const item of issues) {
const issue = row(item), severity = text(issue.severity)
if (severity === 'blocker') tally.blocker += 1
else if (severity === 'concern') tally.concern += 1
else if (severity === 'nit') tally.nit += 1
if (optional(issue.authorship) === 'preexisting') tally.preexisting += 1
else tally.introduced += 1
}
out += `<!-- codewhale-review: {"blocker":${tally.blocker},"concern":${tally.concern},"nit":${tally.nit},"introduced":${tally.introduced},"preexisting":${tally.preexisting}} -->\n`
return out
}
export function transformReviewSnapshot(operation: string, value: unknown): Result {
+1 -1
View File
@@ -147,7 +147,7 @@ impl BuiltinModule {
pub(crate) const BUILTIN_MODULES: &[BuiltinModule] = &[
BuiltinModule {
id: "harness",
source_sha256: "782094d964894c91fc74da1704d3a793163e9605cc802dd7760578b5ba83135d",
source_sha256: "ad24207f93d963dcffe1967f6863f416117d9acd67cdfccbcef59c12ccb39f92",
tools: &[],
},
BuiltinModule {
@@ -946,7 +946,7 @@
"{posted}"
);
assert!(!posted.contains("```suggestion"), "{posted}");
assert!(posted.contains("```text"), "{posted}");
assert!(posted.contains("```diff"), "{posted}");
}
/// #6510: a plain-diff review now asks for the one structured review
+4 -4
View File
@@ -167,7 +167,7 @@
"output": "raw unused",
"posted": false
},
"content": "## Codewhale review\n\n漢字 summary\n\n### Findings\n\n- **[WARNING] Unchecked unwrap** (`src/漢字.rs:11`)\n detail\n> ```suggestion\nevil\n```\n\n### Suggestions\n\n- `src/漢字.rs:11` — Keep context\n\n `````suggestion\n let x = \"````\";\n 漢字\n \n `````\n\n### Assessment\n\nUse care\n\n"
"content": "## Codewhale review\n\n漢字 summary\n\n### Findings\n\n- **[WARNING] Unchecked unwrap** (`src/漢字.rs:11`)\n detail\n> ```suggestion\nevil\n```\n\n### Suggestions\n\n- `src/漢字.rs:11` — Keep context\n\n `````suggestion\n let x = \"````\";\n 漢字\n \n `````\n\n### Assessment\n\nUse care\n\n<!-- codewhale-review: {\"blocker\":0,\"concern\":0,\"nit\":0,\"introduced\":1,\"preexisting\":0} -->\n"
},
{
"operation": "review_report",
@@ -198,7 +198,7 @@
"output": "raw unused",
"posted": true
},
"content": "## Codewhale review\n\n漢字 summary\n\n### Findings\n\n- **[WARNING] Unchecked unwrap** (`src/漢字.rs:11`)\n detail\n> ```suggestion\nevil\n```\n\n### Suggestions\n\n- `src/漢字.rs:11` — Keep context\n\n `````text\n let x = \"````\";\n 漢字\n \n `````\n\n### Assessment\n\nUse care\n\n"
"content": "## Codewhale review\n\n漢字 summary\n\n### Findings\n\n- **[WARNING] Unchecked unwrap** (`src/漢字.rs:11`)\n detail\n> ```suggestion\nevil\n```\n\n### Suggestions\n\n- `src/漢字.rs:11` — Keep context\n\n `````diff\n let x = \"````\";\n 漢字\n \n `````\n\n### Assessment\n\nUse care\n\n<!-- codewhale-review: {\"blocker\":0,\"concern\":0,\"nit\":0,\"introduced\":1,\"preexisting\":0} -->\n"
},
{
"operation": "review_report",
@@ -212,7 +212,7 @@
"output": "raw unused",
"posted": false
},
"content": "## Codewhale review\n\n"
"content": "## Codewhale review\n\n<!-- codewhale-review: {\"blocker\":0,\"concern\":0,\"nit\":0,\"introduced\":0,\"preexisting\":0} -->\n"
},
{
"operation": "review_report",
@@ -226,7 +226,7 @@
"output": "raw unused",
"posted": true
},
"content": "## Codewhale review\n\n"
"content": "## Codewhale review\n\n<!-- codewhale-review: {\"blocker\":0,\"concern\":0,\"nit\":0,\"introduced\":0,\"preexisting\":0} -->\n"
}
]
}