review-council 2.1.3 → 3.0.0

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.
Files changed (106) hide show
  1. package/README.md +57 -0
  2. package/dist/config/data-dir.d.ts +6 -0
  3. package/dist/config/data-dir.js +12 -0
  4. package/dist/config/data-dir.js.map +1 -0
  5. package/dist/config/harness.d.ts +4 -0
  6. package/dist/config/harness.js +1 -1
  7. package/dist/config/harness.js.map +1 -1
  8. package/dist/config/loader.d.ts +1 -0
  9. package/dist/config/loader.js +1 -1
  10. package/dist/config/loader.js.map +1 -1
  11. package/dist/config/schema.d.ts +26 -0
  12. package/dist/config/schema.js +13 -0
  13. package/dist/config/schema.js.map +1 -1
  14. package/dist/consensus/finding-identity.d.ts +18 -0
  15. package/dist/consensus/finding-identity.js +0 -0
  16. package/dist/consensus/finding-identity.js.map +1 -0
  17. package/dist/consensus/gating.d.ts +4 -4
  18. package/dist/consensus/gating.js +216 -26
  19. package/dist/consensus/gating.js.map +1 -1
  20. package/dist/consensus/types.d.ts +35 -0
  21. package/dist/consensus/voter.js +4 -0
  22. package/dist/consensus/voter.js.map +1 -1
  23. package/dist/converge/finding-identity.d.ts +4 -16
  24. package/dist/converge/finding-identity.js +0 -0
  25. package/dist/converge/finding-identity.js.map +1 -1
  26. package/dist/converge/run-state.d.ts +6 -0
  27. package/dist/converge/run-state.js +10 -1
  28. package/dist/converge/run-state.js.map +1 -1
  29. package/dist/dispatch/anthropic.js +6 -1
  30. package/dist/dispatch/anthropic.js.map +1 -1
  31. package/dist/dispatch/google.js +6 -1
  32. package/dist/dispatch/google.js.map +1 -1
  33. package/dist/dispatch/merge.d.ts +8 -7
  34. package/dist/dispatch/merge.js +52 -17
  35. package/dist/dispatch/merge.js.map +1 -1
  36. package/dist/dispatch/openai-compat.js +6 -1
  37. package/dist/dispatch/openai-compat.js.map +1 -1
  38. package/dist/dispatch/openai.js +6 -1
  39. package/dist/dispatch/openai.js.map +1 -1
  40. package/dist/dispatch/utils.d.ts +39 -1
  41. package/dist/dispatch/utils.js +65 -0
  42. package/dist/dispatch/utils.js.map +1 -1
  43. package/dist/index.js +470 -26
  44. package/dist/index.js.map +1 -1
  45. package/dist/models/stats-store.d.ts +2 -1
  46. package/dist/models/stats-store.js +2 -5
  47. package/dist/models/stats-store.js.map +1 -1
  48. package/dist/output/markdown.js +19 -3
  49. package/dist/output/markdown.js.map +1 -1
  50. package/dist/output/progress.d.ts +1 -0
  51. package/dist/output/progress.js +19 -0
  52. package/dist/output/progress.js.map +1 -1
  53. package/dist/prepare/chunker.d.ts +10 -1
  54. package/dist/prepare/chunker.js +285 -29
  55. package/dist/prepare/chunker.js.map +1 -1
  56. package/dist/prepare/prompt-builder.d.ts +29 -0
  57. package/dist/prepare/prompt-builder.js +30 -10
  58. package/dist/prepare/prompt-builder.js.map +1 -1
  59. package/dist/prepare/unified-diff.d.ts +40 -0
  60. package/dist/prepare/unified-diff.js +135 -0
  61. package/dist/prepare/unified-diff.js.map +1 -0
  62. package/dist/prompts/hardening.d.ts +3 -0
  63. package/dist/prompts/hardening.js +15 -0
  64. package/dist/prompts/hardening.js.map +1 -1
  65. package/dist/report/run-header.d.ts +194 -0
  66. package/dist/report/run-header.js +286 -0
  67. package/dist/report/run-header.js.map +1 -0
  68. package/dist/report/uuid.d.ts +7 -0
  69. package/dist/report/uuid.js +23 -0
  70. package/dist/report/uuid.js.map +1 -0
  71. package/dist/resolver/git.d.ts +13 -0
  72. package/dist/resolver/git.js +36 -0
  73. package/dist/resolver/git.js.map +1 -1
  74. package/dist/resolver/github.d.ts +7 -0
  75. package/dist/resolver/github.js +89 -18
  76. package/dist/resolver/github.js.map +1 -1
  77. package/dist/resolver/plan.js +1 -1
  78. package/dist/resolver/target.d.ts +27 -0
  79. package/dist/resolver/target.js +67 -0
  80. package/dist/resolver/target.js.map +1 -0
  81. package/dist/resolver/types.d.ts +13 -0
  82. package/dist/telemetry/credentials.d.ts +43 -0
  83. package/dist/telemetry/credentials.js +87 -0
  84. package/dist/telemetry/credentials.js.map +1 -0
  85. package/dist/telemetry/deliver.d.ts +109 -0
  86. package/dist/telemetry/deliver.js +404 -0
  87. package/dist/telemetry/deliver.js.map +1 -0
  88. package/dist/telemetry/envelope.d.ts +107 -0
  89. package/dist/telemetry/envelope.js +190 -0
  90. package/dist/telemetry/envelope.js.map +1 -0
  91. package/dist/telemetry/events.d.ts +41 -0
  92. package/dist/telemetry/events.js +47 -0
  93. package/dist/telemetry/events.js.map +1 -0
  94. package/dist/telemetry/notice.d.ts +14 -0
  95. package/dist/telemetry/notice.js +58 -0
  96. package/dist/telemetry/notice.js.map +1 -0
  97. package/dist/telemetry/outbox.d.ts +166 -0
  98. package/dist/telemetry/outbox.js +664 -0
  99. package/dist/telemetry/outbox.js.map +1 -0
  100. package/dist/telemetry/scrub.d.ts +43 -0
  101. package/dist/telemetry/scrub.js +179 -0
  102. package/dist/telemetry/scrub.js.map +1 -0
  103. package/dist/telemetry/sink.d.ts +93 -0
  104. package/dist/telemetry/sink.js +228 -0
  105. package/dist/telemetry/sink.js.map +1 -0
  106. package/package.json +1 -1
package/README.md CHANGED
@@ -86,10 +86,17 @@ Review a PR, a local diff, or uncommitted work.
86
86
  | `--json-file <path>` | Write JSON output to a file |
87
87
  | `--markdown <path>` | Write Markdown report to a file |
88
88
  | `--ci` | Exit non-zero if critical/important findings exist |
89
+ | `--head-sha <sha>` | Exact head commit a patch file was taken from (patch files only) |
90
+ | `--base-sha <sha>` | Exact base commit a patch file was taken from (patch files only) |
91
+ | `--expect-head-sha <sha>` | Fail fast unless the resolved head commit equals this SHA |
92
+ | `--spec-source <source>` | Where `--spec` came from: `flag`, `repo_file`, or `harness_issue:<ID>` |
93
+ | `--converge-target <key>` / `--round <n>` / `--attempt <n>` | Converge context recorded in the report (or `RCL_CONVERGE_TARGET` / `_ROUND` / `_ATTEMPT`) |
89
94
  | `--config <path>` | Path to a config file |
90
95
 
91
96
  `--role`, `--roles`, and `--reviewer` are mutually exclusive. So are a positional target, `--staged`, and `--working-tree` — pick exactly one review source. Untracked files are invisible to `git diff` and therefore not reviewed.
92
97
 
98
+ **Self-describing reports (3.0).** Every report carries a `run` header: a client run id (UUIDv7), the rcl version, the target with its exact `head_sha`/`base_sha` (from GitHub for PRs, from `git rev-parse HEAD` and the merge-base with the remote default branch for `--staged`/`--working-tree`, from `--head-sha`/`--base-sha` for patch files) and a `diff_sha256`, the roster with each seat's lane (`blocking`, `secondary`, `async`, `verification`), a config digest with thresholds and gating inline, spec and context-file digests, a best-effort `runner` claim (`agent` / `ci` / `human`), timing, the CI verdict (computed even without `--ci`), and the converge context when run under rcl-converge. Every finding carries its stable converge `identity`, and every reviewer call records token `usage` where the provider reports it. Reports without a `run` header (pre-3.0) still load everywhere.
99
+
93
100
  **Examples:**
94
101
 
95
102
  ```bash
@@ -238,6 +245,53 @@ rcl converge-verdict --target rcl-30 --round 2 \
238
245
 
239
246
  ---
240
247
 
248
+ ### `rcl telemetry status` and `rcl telemetry flush`
249
+
250
+ Evidence delivery to Harness (epic IO-12475). In a repository that carries
251
+ `.harness-cli/config.json` and with a `harness login` (or `HARNESS_API_TOKEN` +
252
+ `HARNESS_API_URL` in CI), every `rcl review` / `rcl review-plan` records the
253
+ run on Harness after the report is written: the self-describing `run` header,
254
+ one row per consensus finding (with its stable identity), one row per reviewer
255
+ call (status, latency, token usage), the report's `stats`, and — at the default
256
+ `full` level — the JSON and Markdown reports exactly as written, digest-checked
257
+ by the server. The converge commands report their events (attempt claims, cap
258
+ changes, processed rounds, verdicts, resolutions) the same way. Never sent:
259
+ provider API keys, `GITHUB_TOKEN`, the Harness credential, environment
260
+ variables, prompts or raw model answers; every free-text field is truncated
261
+ and scrubbed for key-shaped strings before it leaves the process.
262
+
263
+ The review never blocks on the network. A delivery Harness could not take is
264
+ spooled to `~/.rcl/outbox/<run id>/` and retried, with its original run id,
265
+ at the start of every rcl command (bounded to five seconds) or by
266
+ `rcl telemetry flush`. One dim status line says what happened:
267
+ `Evidence recorded: <url>`, `Evidence spooled (Harness unreachable); run rcl
268
+ telemetry flush`, or `Evidence not sent: <host> has not enabled review
269
+ evidence for this organization`. `--evidence-required` exits 4 when the
270
+ evidence is incomplete: the envelope was spooled or refused, the organization
271
+ has evidence off, or a declared artifact did not land (a patch file then needs
272
+ `--head-sha`, and the flag contradicts `--no-telemetry` / `RCL_TELEMETRY=off`).
273
+ Only a spooled delivery is worth `rcl telemetry flush --run <id>`; the status
274
+ line says which. Under `--ci` the gate verdict keeps its exit code and the
275
+ evidence failure is printed beside it. The first delivery from a machine
276
+ prints a one-time notice naming the host and what is sent
277
+ (`~/.rcl/telemetry-notice` records it).
278
+
279
+ ```bash
280
+ rcl telemetry status # level, credential source, what waits in the outbox
281
+ rcl telemetry flush # deliver everything spooled, to completion
282
+ rcl telemetry flush --run <run id> # one run only
283
+ rcl review owner/repo#7 --no-telemetry # keep this review on the machine
284
+ ```
285
+
286
+ ```yaml
287
+ # .review-council.yml
288
+ harness:
289
+ telemetry: full # off | envelope | findings | full (default)
290
+ parseFailures: false # send a parse-failed call's raw answer (scrubbed, 32 KB cap)
291
+ ```
292
+
293
+ ---
294
+
241
295
  ### `rcl models`
242
296
 
243
297
  The tool's own memory of which reviewers earn their seat. Every reviewer call
@@ -390,6 +444,9 @@ For the full algorithm, see [CONSENSUS_V2_SPEC.md](./CONSENSUS_V2_SPEC.md).
390
444
  | `GITHUB_TOKEN` | GitHub personal access token (PR fetch and post) |
391
445
  | `RCL_DEBUG` | Set to any value to print full error stack traces |
392
446
  | `RCL_NO_HARNESS_KEYS` | Set to any value to disable Harness key distribution (below) |
447
+ | `RCL_TELEMETRY` | `off` keeps every review on the machine (see `rcl telemetry`) |
448
+ | `HARNESS_API_TOKEN` | CI credential for evidence delivery; requires `HARNESS_API_URL` — never pairs with the stored login host |
449
+ | `HARNESS_API_URL` | The Harness host `HARNESS_API_TOKEN` was minted by |
393
450
 
394
451
  The default blocking council is direct-API only (Anthropic, OpenAI, Google) —
395
452
  no default review round ever waits on an OpenRouter-routed call. The default
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Where rcl keeps its per-machine state (model stats, the telemetry outbox,
3
+ * the consent notice): `RCL_DATA_DIR`, or `~/.rcl`. Shared here so no
4
+ * feature module depends on another for the location.
5
+ */
6
+ export declare function resolveDataDir(env?: NodeJS.ProcessEnv): string;
@@ -0,0 +1,12 @@
1
+ import { homedir } from 'node:os';
2
+ import { join } from 'node:path';
3
+ /**
4
+ * Where rcl keeps its per-machine state (model stats, the telemetry outbox,
5
+ * the consent notice): `RCL_DATA_DIR`, or `~/.rcl`. Shared here so no
6
+ * feature module depends on another for the location.
7
+ */
8
+ export function resolveDataDir(env = process.env) {
9
+ const override = env['RCL_DATA_DIR']?.trim();
10
+ return override && override.length > 0 ? override : join(homedir(), '.rcl');
11
+ }
12
+ //# sourceMappingURL=data-dir.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-dir.js","sourceRoot":"","sources":["../../src/config/data-dir.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,MAAyB,OAAO,CAAC,GAAG;IACjE,MAAM,QAAQ,GAAG,GAAG,CAAC,cAAc,CAAC,EAAE,IAAI,EAAE,CAAC;IAC7C,OAAO,QAAQ,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,MAAM,CAAC,CAAC;AAC9E,CAAC"}
@@ -18,6 +18,10 @@ export declare function findHarnessRepoConfig(startDir: string): string | null;
18
18
  * harness-cli side (exactly {url, token}) — see its core/credentials.ts.
19
19
  */
20
20
  export declare function defaultCredentialsPath(env: Record<string, string | undefined>): string;
21
+ export declare function readStoredCredentials(path: string): Promise<{
22
+ url: string;
23
+ token: string;
24
+ } | null>;
21
25
  /**
22
26
  * The one entry point: called before config loading (default-model
23
27
  * degradation for a missing OPENROUTER_API_KEY happens there, so the key
@@ -58,7 +58,7 @@ export function defaultCredentialsPath(env) {
58
58
  const base = xdg !== undefined && xdg !== '' && isAbsolute(xdg) ? xdg : join(homedir(), '.config');
59
59
  return join(base, 'harness', 'credentials.json');
60
60
  }
61
- async function readStoredCredentials(path) {
61
+ export async function readStoredCredentials(path) {
62
62
  try {
63
63
  const parsed = JSON.parse(await readFile(path, 'utf-8'));
64
64
  if (typeof parsed === 'object' && parsed !== null) {
@@ -1 +1 @@
1
- {"version":3,"file":"harness.js","sourceRoot":"","sources":["../../src/config/harness.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"harness.js","sourceRoot":"","sources":["../../src/config/harness.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,MAAM,CAAC;AAExD;;;;;;;;;;;;;;;;;GAiBG;AAEH,6EAA6E;AAC7E,MAAM,iBAAiB,GAA2B;IAChD,SAAS,EAAE,mBAAmB;IAC9B,MAAM,EAAE,gBAAgB;IACxB,MAAM,EAAE,gBAAgB;IACxB,UAAU,EAAE,oBAAoB;CACjC,CAAC;AAEF,+EAA+E;AAC/E,MAAM,gBAAgB,GAAG,KAAK,CAAC;AAiB/B,sEAAsE;AACtE,MAAM,UAAU,qBAAqB,CAAC,QAAgB;IACpD,IAAI,GAAG,GAAG,QAAQ,CAAC;IACnB,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;IACjC,SAAS,CAAC;QACR,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,cAAc,EAAE,aAAa,CAAC,CAAC;QAC3D,IAAI,CAAC;YACH,kEAAkE;YAClE,6BAA6B;YAC7B,UAAU,CAAC,SAAS,CAAC,CAAC;YACtB,OAAO,SAAS,CAAC;QACnB,CAAC;QAAC,MAAM,CAAC;YACP,eAAe;QACjB,CAAC;QACD,IAAI,GAAG,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QAC9B,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IACrB,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,GAAuC;IAC5E,MAAM,GAAG,GAAG,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,EAAE,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;IACnG,OAAO,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,kBAAkB,CAAC,CAAC;AACnD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,IAAY;IACtD,IAAI,CAAC;QACH,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;QAClE,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YAClD,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,MAAiC,CAAC;YACzD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,GAAG,KAAK,EAAE,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;gBACvF,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC;YACjD,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,iDAAiD;IACnD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,KAAK,UAAU,cAAc,CAC3B,OAAe,EACf,KAAa,EACb,SAAuB;IAEvB,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,GAAG,OAAO,oBAAoB,EAAE;YAC/D,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE;YAC7C,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,gBAAgB,CAAC;SAC9C,CAAC,CAAC;QACH,IAAI,CAAC,QAAQ,CAAC,EAAE;YAAE,OAAO,IAAI,CAAC;QAC9B,MAAM,IAAI,GAAY,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC5C,MAAM,IAAI,GAAI,IAAsC,EAAE,IAAI,EAAE,IAAI,CAAC;QACjE,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QAC3D,MAAM,GAAG,GAA2B,EAAE,CAAC;QACvC,KAAK,MAAM,CAAC,QAAQ,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACnD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,EAAE;gBAAE,GAAG,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC;QACjE,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAAC,MAAM,CAAC;QACP,qEAAqE;QACrE,0BAA0B;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,GAAuC;IAC/D,MAAM,KAAK,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;IAChE,OAAO,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC;SACrC,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE;QAC7B,0DAA0D;QAC1D,IAAI,QAAQ,KAAK,QAAQ,IAAI,KAAK,CAAC,gBAAgB,CAAC;YAAE,OAAO,KAAK,CAAC;QACnE,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACxB,CAAC,CAAC;SACD,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC;AACnC,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,UAA6B,EAAE;IACzE,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IAEvC,IAAI,CAAC,GAAG,CAAC,qBAAqB,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAEvE,MAAM,OAAO,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAElD,IAAI,qBAAqB,CAAC,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI;QAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAE1F,MAAM,WAAW,GAAG,MAAM,qBAAqB,CAC7C,OAAO,CAAC,eAAe,IAAI,sBAAsB,CAAC,GAAG,CAAC,CACvD,CAAC;IACF,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;QACzB,OAAO;YACL,QAAQ,EAAE,EAAE;YACZ,IAAI,EAAE,WAAW,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,6FAA6F;SAClK,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,WAAW,CAAC,GAAG,EAAE,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,SAAS,IAAI,KAAK,CAAC,CAAC;IAClG,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,mCAAmC,WAAW,CAAC,GAAG,2CAA2C,EAAE,CAAC;IAC/H,CAAC;IAED,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,MAAM,QAAQ,IAAI,OAAO,EAAE,CAAC;QAC/B,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC3B,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACtB,GAAG,CAAC,iBAAiB,CAAC,QAAQ,CAAE,CAAC,GAAG,GAAG,CAAC;YACxC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,OAAO;QACL,QAAQ;QACR,IAAI,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,yBAAyB,WAAW,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS;KACjH,CAAC;AACJ,CAAC"}
@@ -7,4 +7,5 @@ import { type Config } from './schema.js';
7
7
  export declare class ConfigError extends Error {
8
8
  constructor(message: string);
9
9
  }
10
+ export declare const SEARCH_PLACES: string[];
10
11
  export declare function loadConfig(configPath?: string, searchFrom?: string): Promise<Config>;
@@ -16,7 +16,7 @@ export class ConfigError extends Error {
16
16
  // unsupported for discovery: rcl is routinely run inside untrusted
17
17
  // checkouts, and search-loading attacker-controlled JS would execute it
18
18
  // with the user's API keys in env.
19
- const SEARCH_PLACES = [
19
+ export const SEARCH_PLACES = [
20
20
  '.review-council.yml',
21
21
  '.review-council.yaml',
22
22
  '.review-council.json',
@@ -1 +1 @@
1
- {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"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"}
@@ -57,6 +57,23 @@ export declare const GatingSchema: z.ZodObject<{
57
57
  verificationModel: z.ZodOptional<z.ZodString>;
58
58
  verificationTimeout: z.ZodOptional<z.ZodNumber>;
59
59
  }, z.core.$strip>;
60
+ /**
61
+ * Evidence delivery to Harness (epic IO-12475, section 8.6). `telemetry`
62
+ * is the payload tier: `off` sends nothing, `envelope` the run header and
63
+ * stats, `findings` adds findings and calls, `full` (default) also uploads
64
+ * the JSON and Markdown reports. `parseFailures` opts in to sending a
65
+ * parse-failed call's raw model answer (fenced code and key-shaped strings
66
+ * removed, 32 KB cap).
67
+ */
68
+ export declare const HarnessSchema: z.ZodObject<{
69
+ telemetry: z.ZodOptional<z.ZodEnum<{
70
+ findings: "findings";
71
+ off: "off";
72
+ envelope: "envelope";
73
+ full: "full";
74
+ }>>;
75
+ parseFailures: z.ZodOptional<z.ZodBoolean>;
76
+ }, z.core.$strip>;
60
77
  export declare const ConfigSchema: z.ZodObject<{
61
78
  models: z.ZodOptional<z.ZodArray<z.ZodString>>;
62
79
  secondaryModels: z.ZodOptional<z.ZodArray<z.ZodString>>;
@@ -110,6 +127,15 @@ export declare const ConfigSchema: z.ZodObject<{
110
127
  context: z.ZodOptional<z.ZodArray<z.ZodString>>;
111
128
  spec: z.ZodOptional<z.ZodString>;
112
129
  focus: z.ZodOptional<z.ZodArray<z.ZodString>>;
130
+ harness: z.ZodOptional<z.ZodObject<{
131
+ telemetry: z.ZodOptional<z.ZodEnum<{
132
+ findings: "findings";
133
+ off: "off";
134
+ envelope: "envelope";
135
+ full: "full";
136
+ }>>;
137
+ parseFailures: z.ZodOptional<z.ZodBoolean>;
138
+ }, z.core.$strip>>;
113
139
  }, z.core.$strip>;
114
140
  export type Config = z.infer<typeof ConfigSchema>;
115
141
  export type ReviewerPair = z.infer<typeof ReviewerPairSchema>;
@@ -53,6 +53,18 @@ export const GatingSchema = z.object({
53
53
  /** Per-call timeout (ms) for the verification pass. */
54
54
  verificationTimeout: z.number().positive().optional(),
55
55
  });
56
+ /**
57
+ * Evidence delivery to Harness (epic IO-12475, section 8.6). `telemetry`
58
+ * is the payload tier: `off` sends nothing, `envelope` the run header and
59
+ * stats, `findings` adds findings and calls, `full` (default) also uploads
60
+ * the JSON and Markdown reports. `parseFailures` opts in to sending a
61
+ * parse-failed call's raw model answer (fenced code and key-shaped strings
62
+ * removed, 32 KB cap).
63
+ */
64
+ export const HarnessSchema = z.object({
65
+ telemetry: z.enum(['off', 'envelope', 'findings', 'full']).optional(),
66
+ parseFailures: z.boolean().optional(),
67
+ });
56
68
  export const ConfigSchema = z.object({
57
69
  models: z.array(z.string()).optional(),
58
70
  secondaryModels: z.array(z.string()).optional(),
@@ -86,5 +98,6 @@ export const ConfigSchema = z.object({
86
98
  context: z.array(z.string()).optional(),
87
99
  spec: z.string().optional(),
88
100
  focus: z.array(z.string()).optional(),
101
+ harness: HarnessSchema.optional(),
89
102
  });
90
103
  //# sourceMappingURL=schema.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ export interface FindingLocation {
2
+ file: string;
3
+ category: string;
4
+ startLine: number;
5
+ endLine: number;
6
+ }
7
+ export interface IdentityEntry extends FindingLocation {
8
+ key: string;
9
+ }
10
+ /** Deterministic 16-hex-char identity for a finding's anchor. */
11
+ export declare function stableFindingKey(f: FindingLocation): string;
12
+ /**
13
+ * Match a finding against persisted entries by location: same file, same
14
+ * category, line ranges overlapping within `lineWindow`. Overlap matching
15
+ * (not just the hash) keeps identity stable across bucket boundaries when
16
+ * fixes shift lines slightly. Returns the best-overlapping entry.
17
+ */
18
+ export declare function matchFinding(f: FindingLocation, entries: readonly IdentityEntry[], lineWindow: number): IdentityEntry | undefined;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding-identity.js","sourceRoot":"","sources":["../../src/consensus/finding-identity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C;;;;;GAKG;AAEH,4EAA4E;AAC5E,MAAM,mBAAmB,GAAG,EAAE,CAAC;AAa/B,iEAAiE;AACjE,MAAM,UAAU,gBAAgB,CAAC,CAAkB;IACjD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,GAAG,mBAAmB,CAAC,CAAC;IAC7D,OAAO,UAAU,CAAC,QAAQ,CAAC;SACxB,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,QAAQ,IAAI,MAAM,EAAE,CAAC;SAC3C,MAAM,CAAC,KAAK,CAAC;SACb,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAClB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAC1B,CAAkB,EAClB,OAAiC,EACjC,UAAkB;IAElB,IAAI,IAA+B,CAAC;IACpC,IAAI,YAAY,GAAG,QAAQ,CAAC;IAC5B,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,IAAI,KAAK,CAAC,QAAQ,KAAK,CAAC,CAAC,QAAQ;YAAE,SAAS;QACrE,IAAI,CAAC,YAAY,CAAC,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC;YAAE,SAAS;QAClD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC;QACzD,IAAI,QAAQ,GAAG,YAAY,EAAE,CAAC;YAC5B,IAAI,GAAG,KAAK,CAAC;YACb,YAAY,GAAG,QAAQ,CAAC;QAC1B,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -100,10 +100,10 @@ export declare const DEFAULT_GATING_CONFIG: {
100
100
  export declare function resolveGatingConfig(input: GatingConfigInput | undefined, rosterModels?: readonly string[]): ResolvedGatingConfig;
101
101
  /**
102
102
  * Reduce a unified diff to the hunks that overlap the findings' line ranges.
103
- * Blind tail-truncation could cut the exact hunk a finding refers to and let
104
- * the verifier judge (and refute) from unrelated context. Returns the whole
105
- * patch when it has no hunk headers (plan pseudo-files), and '' when no hunk
106
- * overlaps — the caller then treats the finding as having no usable context.
103
+ * Oversized hunks are excerpted around every requested range with accurate
104
+ * synthetic headers. Returns short non-hunk content unchanged for backward
105
+ * compatibility, and '' when trustworthy context cannot fit in the bound —
106
+ * the caller then keeps the finding gating without invoking the verifier.
107
107
  */
108
108
  export declare function relevantPatchExcerpt(patch: string, ranges: Array<{
109
109
  start: number;
@@ -1,6 +1,7 @@
1
1
  import { defaultAdapterFactory } from '../dispatch/runner.js';
2
2
  import { detectProvider } from '../roles/dispatcher.js';
3
3
  import { neutralizeDelimiters, wrapDiff } from '../prompts/hardening.js';
4
+ import { formatSyntheticHunkHeader, parseUnifiedDiff, } from '../prepare/unified-diff.js';
4
5
  const DIRECT_PROVIDERS = new Set(['anthropic', 'openai', 'google']);
5
6
  export const DEFAULT_GATING_CONFIG = {
6
7
  mode: 'verified-consensus',
@@ -69,35 +70,225 @@ When unsure, answer "confirmed".`;
69
70
  const MAX_PATCH_CHARS = 4_000;
70
71
  /** Lines of slack when matching a finding's range against a hunk's span. */
71
72
  const HUNK_MARGIN_LINES = 16;
73
+ function isChangedLine(line) {
74
+ return !line.marker && line.oldCount !== line.newCount;
75
+ }
76
+ function replacementBlock(body, index) {
77
+ let start = index;
78
+ while (start > 0) {
79
+ const previous = body[start - 1];
80
+ if (isChangedLine(previous)) {
81
+ start -= 1;
82
+ }
83
+ else if (previous.marker && start > 1 && isChangedLine(body[start - 2])) {
84
+ start -= 2;
85
+ }
86
+ else {
87
+ break;
88
+ }
89
+ }
90
+ let end = index + 1;
91
+ while (end < body.length) {
92
+ const next = body[end];
93
+ if (isChangedLine(next)) {
94
+ end += 1;
95
+ }
96
+ else if (next.marker && end > start && isChangedLine(body[end - 1])) {
97
+ end += 1;
98
+ }
99
+ else {
100
+ break;
101
+ }
102
+ }
103
+ return {
104
+ start,
105
+ end,
106
+ hasDeletion: body
107
+ .slice(start, end)
108
+ .some((line) => line.oldCount === 1 && line.newCount === 0),
109
+ };
110
+ }
111
+ function windowForMatches(hunk, hunkIndex, matches) {
112
+ const first = matches[0];
113
+ const last = matches.at(-1);
114
+ if (first === undefined || last === undefined)
115
+ return undefined;
116
+ let start = first;
117
+ let end = last + 1;
118
+ let processedBlockEnd = 0;
119
+ for (const index of matches) {
120
+ // requiredWindow collects matches in body order. Once one changed line
121
+ // expands to its contiguous replacement block, later matches inside that
122
+ // block cannot widen the required evidence and must not rescan it.
123
+ if (index < processedBlockEnd)
124
+ continue;
125
+ const line = hunk.body[index];
126
+ if (!isChangedLine(line))
127
+ continue;
128
+ const block = replacementBlock(hunk.body, index);
129
+ processedBlockEnd = block.end;
130
+ if (block.hasDeletion) {
131
+ start = Math.min(start, block.start);
132
+ end = Math.max(end, block.end);
133
+ }
134
+ }
135
+ return { hunkIndex, start, end };
136
+ }
137
+ function hunkDistance(hunk, range) {
138
+ // A zero-count range is anchored after newStart and its deletion body uses
139
+ // newStart + 1 as the effective new-file coordinate. Treat both sides of
140
+ // that boundary as adjacent so either conventional line reference keeps
141
+ // the complete removal in view.
142
+ const hunkStart = hunk.newStart;
143
+ let hunkEnd = hunk.newCount === 0 ? hunk.newStart + 1 : hunk.newStart + hunk.newCount - 1;
144
+ // A deletion after the hunk's final new-file line is anchored at the next
145
+ // coordinate. Parsed body coordinates are monotonic; only a legal trailing
146
+ // no-newline marker can follow the last real line.
147
+ const last = hunk.body.at(-1);
148
+ const lastBodyLine = last?.marker ? hunk.body.at(-2) : last;
149
+ if (lastBodyLine)
150
+ hunkEnd = Math.max(hunkEnd, lastBodyLine.newLine);
151
+ if (range.end < hunkStart)
152
+ return hunkStart - range.end;
153
+ if (range.start > hunkEnd)
154
+ return range.start - hunkEnd;
155
+ return 0;
156
+ }
157
+ function requiredWindow(hunk, hunkIndex, range) {
158
+ const exact = [];
159
+ for (let index = 0; index < hunk.body.length; index += 1) {
160
+ const line = hunk.body[index];
161
+ if (!line.marker && line.newLine >= range.start && line.newLine <= range.end) {
162
+ exact.push(index);
163
+ }
164
+ }
165
+ // Deletions and the following new-file line share a coordinate. Keep the
166
+ // whole span: omitting either side can let a verifier refute a finding from
167
+ // incomplete replacement evidence. If it cannot fit, the caller fails
168
+ // closed instead of sending a partial removal.
169
+ if (exact.length > 0) {
170
+ return windowForMatches(hunk, hunkIndex, exact);
171
+ }
172
+ const closest = [];
173
+ let closestDistance = Number.POSITIVE_INFINITY;
174
+ for (let index = 0; index < hunk.body.length; index += 1) {
175
+ const line = hunk.body[index];
176
+ if (line.marker)
177
+ continue;
178
+ const distance = line.newLine < range.start
179
+ ? range.start - line.newLine
180
+ : line.newLine > range.end
181
+ ? line.newLine - range.end
182
+ : 0;
183
+ if (distance < closestDistance) {
184
+ closestDistance = distance;
185
+ closest.length = 0;
186
+ closest.push(index);
187
+ }
188
+ else if (distance === closestDistance) {
189
+ closest.push(index);
190
+ }
191
+ }
192
+ return windowForMatches(hunk, hunkIndex, closest);
193
+ }
194
+ function mergeWindows(windows) {
195
+ const sorted = [...windows].sort((left, right) => left.hunkIndex - right.hunkIndex || left.start - right.start);
196
+ const merged = [];
197
+ for (const window of sorted) {
198
+ const previous = merged.at(-1);
199
+ if (previous && previous.hunkIndex === window.hunkIndex && window.start <= previous.end) {
200
+ previous.end = Math.max(previous.end, window.end);
201
+ }
202
+ else {
203
+ merged.push({ ...window });
204
+ }
205
+ }
206
+ return merged;
207
+ }
208
+ function expandWindows(hunks, required, margin) {
209
+ const expanded = required.map((window) => {
210
+ const body = hunks[window.hunkIndex].body;
211
+ let start = Math.max(0, window.start - margin);
212
+ let end = Math.min(body.length, window.end + margin);
213
+ while (start > 0 && body[start].marker)
214
+ start -= 1;
215
+ while (end < body.length && body[end].marker)
216
+ end += 1;
217
+ return { hunkIndex: window.hunkIndex, start, end };
218
+ });
219
+ return mergeWindows(expanded);
220
+ }
221
+ function renderWindows(hunks, windows) {
222
+ return windows
223
+ .map((window) => {
224
+ const hunk = hunks[window.hunkIndex];
225
+ const body = hunk.body.slice(window.start, window.end);
226
+ const header = formatSyntheticHunkHeader(body);
227
+ if (!header)
228
+ return '';
229
+ return [header, ...body.map((line) => line.text)].join('\n');
230
+ })
231
+ .join('\n');
232
+ }
72
233
  /**
73
234
  * Reduce a unified diff to the hunks that overlap the findings' line ranges.
74
- * Blind tail-truncation could cut the exact hunk a finding refers to and let
75
- * the verifier judge (and refute) from unrelated context. Returns the whole
76
- * patch when it has no hunk headers (plan pseudo-files), and '' when no hunk
77
- * overlaps — the caller then treats the finding as having no usable context.
235
+ * Oversized hunks are excerpted around every requested range with accurate
236
+ * synthetic headers. Returns short non-hunk content unchanged for backward
237
+ * compatibility, and '' when trustworthy context cannot fit in the bound —
238
+ * the caller then keeps the finding gating without invoking the verifier.
78
239
  */
79
240
  export function relevantPatchExcerpt(patch, ranges) {
80
- const hunks = [];
81
- let current;
82
- for (const line of patch.split('\n')) {
83
- const header = /^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@/.exec(line);
84
- if (header) {
85
- current = {
86
- startNew: Number(header[1]),
87
- countNew: header[2] !== undefined ? Number(header[2]) : 1,
88
- text: [line],
89
- };
90
- hunks.push(current);
91
- }
92
- else if (current) {
93
- current.text.push(line);
241
+ if (ranges.length === 0)
242
+ return '';
243
+ if (!/^@@ -\d+(?:,\d+)? \+\d+(?:,\d+)? @@/m.test(patch)) {
244
+ return patch.length <= MAX_PATCH_CHARS ? patch : '';
245
+ }
246
+ if (ranges.some(({ start, end }) => !Number.isSafeInteger(start) || !Number.isSafeInteger(end) || start < 1 || end < start)) {
247
+ return '';
248
+ }
249
+ const parsed = parseUnifiedDiff(patch);
250
+ if (!parsed.ok)
251
+ return '';
252
+ const { hunks } = parsed.diff;
253
+ const required = [];
254
+ const selectedHunks = new Set();
255
+ for (const range of ranges) {
256
+ const distances = hunks.map((hunk) => hunkDistance(hunk, range));
257
+ const overlapping = distances
258
+ .map((distance, index) => ({ distance, index }))
259
+ .filter(({ distance }) => distance === 0);
260
+ const closestDistance = distances.reduce((closest, distance) => Math.min(closest, distance), Number.POSITIVE_INFINITY);
261
+ const matches = overlapping.length > 0
262
+ ? overlapping
263
+ : distances
264
+ .map((distance, index) => ({ distance, index }))
265
+ .filter(({ distance }) => distance === closestDistance && distance <= HUNK_MARGIN_LINES);
266
+ if (matches.length === 0)
267
+ return '';
268
+ for (const { index } of matches) {
269
+ const window = requiredWindow(hunks[index], index, range);
270
+ if (!window)
271
+ return '';
272
+ required.push(window);
273
+ selectedHunks.add(index);
94
274
  }
95
275
  }
96
- if (hunks.length === 0)
97
- return patch;
98
- const selected = hunks.filter((h) => ranges.some((r) => h.startNew - HUNK_MARGIN_LINES <= r.end &&
99
- r.start - HUNK_MARGIN_LINES <= h.startNew + h.countNew));
100
- return selected.map((h) => h.text.join('\n')).join('\n');
276
+ const selected = [...selectedHunks]
277
+ .sort((left, right) => left - right)
278
+ .map((index) => {
279
+ const hunk = hunks[index];
280
+ return [hunk.originalHeader, ...hunk.body.map((line) => line.text)].join('\n');
281
+ })
282
+ .join('\n');
283
+ if (selected.length <= MAX_PATCH_CHARS)
284
+ return selected;
285
+ const minimal = mergeWindows(required);
286
+ for (let margin = HUNK_MARGIN_LINES; margin >= 0; margin -= 1) {
287
+ const excerpt = renderWindows(hunks, expandWindows(hunks, minimal, margin));
288
+ if (excerpt.length <= MAX_PATCH_CHARS)
289
+ return excerpt;
290
+ }
291
+ return '';
101
292
  }
102
293
  function buildVerifierPrompt(candidates, patches) {
103
294
  // Finding text originates from council models reading an untrusted diff —
@@ -108,8 +299,7 @@ function buildVerifierPrompt(candidates, patches) {
108
299
  });
109
300
  lines.push('## The change under review (relevant files, untrusted content)', '');
110
301
  for (const [filename, patch] of patches) {
111
- const bounded = patch.length > MAX_PATCH_CHARS ? `${patch.slice(0, MAX_PATCH_CHARS)}\n… (truncated)` : patch;
112
- lines.push(`### ${neutralizeDelimiters(filename)}`, wrapDiff(bounded), '');
302
+ lines.push(`### ${neutralizeDelimiters(filename)}`, wrapDiff(patch), '');
113
303
  }
114
304
  return lines.join('\n');
115
305
  }
@@ -239,7 +429,7 @@ export async function applyGating(findings, options) {
239
429
  }
240
430
  else {
241
431
  markUnavailable(findingIndex, fullPatches.has(f.file)
242
- ? 'finding lines match no hunk in the diff — not sent to the verifier'
432
+ ? 'no hunk context fits the safe verifier bound — not sent to the verifier'
243
433
  : 'no diff context for this file — not sent to the verifier');
244
434
  }
245
435
  }