opencode-swarm 7.125.0 → 7.125.2
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/.opencode/skills/swarm-pr-feedback/SKILL.md +11 -127
- package/.opencode/skills/swarm-pr-feedback/references/bot-claim-verification.md +71 -0
- package/.opencode/skills/swarm-pr-feedback/references/operational-gotchas.md +49 -0
- package/.opencode/skills/swarm-pr-review/SKILL.md +6 -346
- package/.opencode/skills/swarm-pr-review/references/parser-dry-run.md +235 -0
- package/.opencode/skills/swarm-pr-review/references/prompt-templates.md +103 -0
- package/.opencode/skills/writing-tests/SKILL.md +4 -123
- package/.opencode/skills/writing-tests/references/mock-and-seam-inventory.md +43 -0
- package/dist/cli/{config-doctor-be9sxqx8.js → config-doctor-8df6hk58.js} +2 -2
- package/dist/cli/{curation-policy-52kt6d7t.js → curation-policy-7pvghg6f.js} +2 -2
- package/dist/cli/{curator-hbst8nbc.js → curator-dw2zb74h.js} +13 -13
- package/dist/cli/{curator-llm-factory-frde1955.js → curator-llm-factory-bntt6v8j.js} +13 -13
- package/dist/cli/{evidence-summary-service-9hq7n9k9.js → evidence-summary-service-v4h2w487.js} +1 -1
- package/dist/cli/{guardrail-explain-112kqmbc.js → guardrail-explain-vmr4db9n.js} +14 -14
- package/dist/cli/{guardrail-log-c8zcab91.js → guardrail-log-8prd6cnc.js} +3 -3
- package/dist/cli/{hive-promoter-448xs2tp.js → hive-promoter-xymt9vf2.js} +13 -13
- package/dist/cli/{index-jh6s75f6.js → index-1s7jzcsy.js} +1 -1
- package/dist/cli/{index-09vd53pz.js → index-39p1yyag.js} +1 -1
- package/dist/cli/{index-dx2c2wjt.js → index-7mtvvt8p.js} +2 -2
- package/dist/cli/{index-67hqr2zv.js → index-7ne6q2a0.js} +1 -1
- package/dist/cli/{index-amspa811.js → index-8ed9rz7y.js} +122 -45
- package/dist/cli/{index-0y6tmm9v.js → index-92xyawa7.js} +1 -1
- package/dist/cli/{index-7j3sm7h8.js → index-em4h33my.js} +2 -2
- package/dist/cli/{index-4rzzzjtg.js → index-fs02c7tz.js} +277 -16
- package/dist/cli/{index-kt0awv1n.js → index-j8ptbcxz.js} +1 -1
- package/dist/cli/{index-yt1v62pv.js → index-pgya7cnn.js} +4 -4
- package/dist/cli/{index-vtwqjr4z.js → index-ptmhxsaf.js} +3 -3
- package/dist/cli/{index-xattnmyb.js → index-qcrah1jk.js} +6 -2
- package/dist/cli/{index-6vfvc36k.js → index-sxdh19nk.js} +1 -1
- package/dist/cli/{index-n6chz2g8.js → index-tdpct4cz.js} +1 -1
- package/dist/cli/{index-99ed0h32.js → index-v3f7jvm8.js} +5 -5
- package/dist/cli/{index-9hbwa5x1.js → index-yrk6hfp1.js} +15 -15
- package/dist/cli/{index-958hf0yr.js → index-zbsxek49.js} +2 -2
- package/dist/cli/index.js +13 -13
- package/dist/cli/{knowledge-escalator-htafbhxg.js → knowledge-escalator-47hfstmk.js} +3 -3
- package/dist/cli/{knowledge-events-havw8c4t.js → knowledge-events-j5dpp72w.js} +1 -1
- package/dist/cli/{knowledge-store-hqngpt2v.js → knowledge-store-58gt7m85.js} +1 -1
- package/dist/cli/{knowledge-validator-g7mpnazh.js → knowledge-validator-jjxw5mwc.js} +4 -4
- package/dist/cli/{scan-cursor-sx7cvh8v.js → scan-cursor-h8we8dfv.js} +2 -2
- package/dist/cli/{schema-2418eqy3.js → schema-xpqbhcyp.js} +1 -1
- package/dist/cli/{skill-generator-zggy797r.js → skill-generator-k8d0vff0.js} +5 -5
- package/dist/commands/close.d.ts +4 -2
- package/dist/config/schema.d.ts +8 -0
- package/dist/evidence/documents-retention.d.ts +116 -0
- package/dist/evidence/manager.d.ts +17 -0
- package/dist/hooks/knowledge-application-gate.d.ts +8 -2
- package/dist/hooks/knowledge-application.d.ts +2 -0
- package/dist/index.js +376 -368
- package/dist/state.d.ts +33 -2
- package/package.json +1 -1
|
@@ -649,7 +649,7 @@ rather than preview-text extraction:
|
|
|
649
649
|
4. Stage reviewer-sized chunks, but do not dispatch reviewers yet. Phase 4 must
|
|
650
650
|
complete trigger accounting and settle every launched micro-lane first.
|
|
651
651
|
|
|
652
|
-
If a lane has `output_degraded: true`, `transcript_incomplete: true`, or no usable `output_ref`, apply the COVERAGE GATE
|
|
652
|
+
If a lane has `output_degraded: true`, `transcript_incomplete: true`, or no usable `output_ref`, apply the COVERAGE GATE (Phase 3). Do not use blocking or direct-Task fallbacks, mark affected candidates UNVERIFIED to proceed, or infer candidate absence from a preview.
|
|
653
653
|
|
|
654
654
|
After candidate parsing and before reviewer dispatch, persist the post-explorer
|
|
655
655
|
candidate ledger using the Review Finding Persistence contract. This is the
|
|
@@ -782,12 +782,7 @@ errors, zero malformed rows, and a complete, non-degraded source:
|
|
|
782
782
|
[CLEAN] | micro_lane | coverage_scope | evidence
|
|
783
783
|
```
|
|
784
784
|
|
|
785
|
-
Header-only or malformed zero output is `UNATTESTED` and
|
|
786
|
-
canonical COVERAGE GATE retry path. Only the structured async PR-workflow path
|
|
787
|
-
preserves the required `L1`, exact-head, batch, and workflow-lane provenance;
|
|
788
|
-
the active controller rejects blocking and direct-Task substitutes. Task-derived
|
|
789
|
-
findings or CLEAN prose cannot satisfy Phase 4; if bounded structured retries
|
|
790
|
-
cannot produce an artifact, the phase is BLOCKED.
|
|
785
|
+
Header-only or malformed zero output is `UNATTESTED`; apply the COVERAGE GATE (Phase 3). The structured async PR-workflow path is required to preserve `L1`, exact-head, batch, and workflow-lane provenance; the active controller rejects blocking and direct-Task substitutes. Task-derived findings or CLEAN prose cannot satisfy Phase 4.
|
|
791
786
|
|
|
792
787
|
Each micro-lane receives:
|
|
793
788
|
|
|
@@ -1041,7 +1036,7 @@ BLOCKED. Terminal critic rows are cross-field checked: `DISPROVED` requires
|
|
|
1041
1036
|
`NONE`, `UPHELD` requires CRITICAL/HIGH/MEDIUM, and `DOWNGRADED` cannot remain
|
|
1042
1037
|
CRITICAL.
|
|
1043
1038
|
|
|
1044
|
-
**COVERAGE GATE alignment:** Critic lane failures
|
|
1039
|
+
**COVERAGE GATE alignment:** Critic lane failures apply the COVERAGE GATE (Phase 3) using `dispatch_lanes_async` with `mode: "swarm-pr-review:critic"` and the same exact `pr_head_sha`. Do NOT mark findings UNVERIFIED or continue past the gap. The orchestrator NEVER fabricates a critic verdict by parsing prose, by tolerating a planning preamble, by presenting partial findings, or by silently accepting reduced coverage.
|
|
1045
1040
|
|
|
1046
1041
|
Refuted findings become `DISPROVED` or `ADVISORY`, depending on critic rationale. Downgrades must be listed in the final validation provenance.
|
|
1047
1042
|
|
|
@@ -1170,240 +1165,7 @@ Update the verdict only after re-verifying all previously blocking findings.
|
|
|
1170
1165
|
|
|
1171
1166
|
---
|
|
1172
1167
|
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
This section demonstrates the new parser-based extraction path end-to-end
|
|
1176
|
-
using synthetic data. It is concrete enough to implement the same pattern in
|
|
1177
|
-
another skill.
|
|
1178
|
-
|
|
1179
|
-
### Scenario
|
|
1180
|
-
|
|
1181
|
-
A PR review has dispatched six base explorer lanes via `dispatch_lanes_async`.
|
|
1182
|
-
The batch completed and `collect_lane_results` returned:
|
|
1183
|
-
|
|
1184
|
-
```json
|
|
1185
|
-
{
|
|
1186
|
-
"batch_id": "batch-a1b2c3",
|
|
1187
|
-
"lane_results": [
|
|
1188
|
-
{
|
|
1189
|
-
"lane_id": "pr_review_lane1_correctness",
|
|
1190
|
-
"status": "completed",
|
|
1191
|
-
"output_ref": "L1:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
|
|
1192
|
-
"output_degraded": false
|
|
1193
|
-
},
|
|
1194
|
-
{
|
|
1195
|
-
"lane_id": "pr_review_lane2_security",
|
|
1196
|
-
"status": "completed",
|
|
1197
|
-
"output_ref": "L1:dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd:eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
|
1198
|
-
"output_degraded": false
|
|
1199
|
-
}
|
|
1200
|
-
]
|
|
1201
|
-
}
|
|
1202
|
-
```
|
|
1203
|
-
|
|
1204
|
-
### Step 1 — Call the parser
|
|
1205
|
-
|
|
1206
|
-
The orchestrator calls `parse_lane_candidates` for each `output_ref`:
|
|
1207
|
-
|
|
1208
|
-
```json
|
|
1209
|
-
{
|
|
1210
|
-
"tool": "parse_lane_candidates",
|
|
1211
|
-
"arguments": {
|
|
1212
|
-
"output_ref": "L1:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
|
|
1213
|
-
"producer": "swarm-pr-review",
|
|
1214
|
-
"expected_family": "base_explorer"
|
|
1215
|
-
}
|
|
1216
|
-
}
|
|
1217
|
-
```
|
|
1218
|
-
|
|
1219
|
-
### Step 2 — Structured response
|
|
1220
|
-
|
|
1221
|
-
The parser returns a `ParseResultWithSidecar`. On success, `error` and `error_code` are absent:
|
|
1222
|
-
|
|
1223
|
-
```json
|
|
1224
|
-
{
|
|
1225
|
-
"candidates": [
|
|
1226
|
-
{
|
|
1227
|
-
"record_type": "candidate",
|
|
1228
|
-
"row_format_family": "base_explorer",
|
|
1229
|
-
"row_format_version": 1,
|
|
1230
|
-
"record_version": { "major": 1, "minor": 1 },
|
|
1231
|
-
"source_output_ref": "L1:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
|
|
1232
|
-
"source_batch_id": "B-2025-06-22-001",
|
|
1233
|
-
"source_lane_id": "explorer-1",
|
|
1234
|
-
"source_agent": "paid_explorer",
|
|
1235
|
-
"source_digest": "sha256:abc123def456...",
|
|
1236
|
-
"extracted_from_partial_source": false,
|
|
1237
|
-
"sessionId": "ses_01HXYZ...",
|
|
1238
|
-
"parentSessionId": "ses_01HABC...",
|
|
1239
|
-
"producer": "swarm-pr-review",
|
|
1240
|
-
"candidate_id": "C-001",
|
|
1241
|
-
"lane": "Lane 1: Correctness and edge cases",
|
|
1242
|
-
"micro_lane": null,
|
|
1243
|
-
"severity": "HIGH",
|
|
1244
|
-
"category": "null-safety",
|
|
1245
|
-
"file_line": "src/utils/cache.ts:142",
|
|
1246
|
-
"claim": "Uncached getter may return undefined on cold start",
|
|
1247
|
-
"evidence_summary": "The `getCached` function returns `cache[key]` without a fallback when the cache is empty.",
|
|
1248
|
-
"impact_context": "Downstream callers in `src/handlers/*.ts` expect a defined value and call `.toString()` directly.",
|
|
1249
|
-
"invariant_violated": null,
|
|
1250
|
-
"confidence": "HIGH"
|
|
1251
|
-
},
|
|
1252
|
-
{
|
|
1253
|
-
"record_type": "candidate",
|
|
1254
|
-
"row_format_family": "base_explorer",
|
|
1255
|
-
"row_format_version": 1,
|
|
1256
|
-
"record_version": { "major": 1, "minor": 1 },
|
|
1257
|
-
"source_output_ref": "L1:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
|
|
1258
|
-
"source_batch_id": "B-2025-06-22-001",
|
|
1259
|
-
"source_lane_id": "explorer-1",
|
|
1260
|
-
"source_agent": "paid_explorer",
|
|
1261
|
-
"source_digest": "sha256:abc123def456...",
|
|
1262
|
-
"extracted_from_partial_source": false,
|
|
1263
|
-
"sessionId": "ses_01HXYZ...",
|
|
1264
|
-
"parentSessionId": "ses_01HABC...",
|
|
1265
|
-
"producer": "swarm-pr-review",
|
|
1266
|
-
"candidate_id": "C-002",
|
|
1267
|
-
"lane": "Lane 1: Correctness and edge cases",
|
|
1268
|
-
"micro_lane": null,
|
|
1269
|
-
"severity": "MEDIUM",
|
|
1270
|
-
"category": "async-ordering",
|
|
1271
|
-
"file_line": "src/services/queue.ts:88",
|
|
1272
|
-
"claim": "Race between `drain` and `processNext` may drop items",
|
|
1273
|
-
"evidence_summary": "`drain` sets `active = false` before awaiting `processNext`, which also checks `active`.",
|
|
1274
|
-
"impact_context": "Items submitted during the drain window are silently dropped.",
|
|
1275
|
-
"invariant_violated": null,
|
|
1276
|
-
"confidence": "MEDIUM"
|
|
1277
|
-
}
|
|
1278
|
-
],
|
|
1279
|
-
"invocation_envelope": {
|
|
1280
|
-
"record_type": "invocation",
|
|
1281
|
-
"source_output_ref": "L1:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
|
|
1282
|
-
"source_batch_id": "B-2025-06-22-001",
|
|
1283
|
-
"source_lane_id": "explorer-1",
|
|
1284
|
-
"source_agent": "paid_explorer",
|
|
1285
|
-
"source_digest": "sha256:abc123def456...",
|
|
1286
|
-
"row_format_version": 1,
|
|
1287
|
-
"record_version": { "major": 1, "minor": 1 },
|
|
1288
|
-
"sessionId": "ses_01HXYZ...",
|
|
1289
|
-
"parentSessionId": "ses_01HABC...",
|
|
1290
|
-
"producer": "swarm-pr-review",
|
|
1291
|
-
"produced_at": "2025-06-22T14:30:00.000Z",
|
|
1292
|
-
"format_families_detected": ["base_explorer"],
|
|
1293
|
-
"candidate_count": 2,
|
|
1294
|
-
"parse_errors": 0,
|
|
1295
|
-
"malformed_rows": 0,
|
|
1296
|
-
"clean_attestation_count": 0
|
|
1297
|
-
},
|
|
1298
|
-
"diagnostics": {
|
|
1299
|
-
"candidate_count": 2,
|
|
1300
|
-
"parse_errors": 0,
|
|
1301
|
-
"parse_error_details": [],
|
|
1302
|
-
"malformed_rows": 0,
|
|
1303
|
-
"duplicate_id_count": 0,
|
|
1304
|
-
"duplicate_id_warnings": [],
|
|
1305
|
-
"degraded_source_count": 0,
|
|
1306
|
-
"incomplete_source_count": 0,
|
|
1307
|
-
"format_families_detected": ["base_explorer"],
|
|
1308
|
-
"clean_attestation_count": 0
|
|
1309
|
-
}
|
|
1310
|
-
}
|
|
1311
|
-
```
|
|
1312
|
-
> **Note**: callers pass `expected_family` for each dispatch batch. A recognizable
|
|
1313
|
-
> conflicting header fails closed with `expected-family-mismatch`; when the flag
|
|
1314
|
-
> is absent, the recognized header controls the mapping and positional detection
|
|
1315
|
-
> is only a legacy unknown-header fallback. Marker-prefixed data rows remain
|
|
1316
|
-
> accepted for compatibility. Valid canonical rows produce `parse_errors: 0`.
|
|
1317
|
-
|
|
1318
|
-
On refusal (e.g. `output_ref` does not exist), `error` and `error_code` are present; `candidates` is `[]`; `invocation_envelope` and `diagnostics` are populated with empty fields for traceability:
|
|
1319
|
-
|
|
1320
|
-
```json
|
|
1321
|
-
{
|
|
1322
|
-
"error": "Artifact reference not found in store",
|
|
1323
|
-
"error_code": "ref-not-found",
|
|
1324
|
-
"candidates": [],
|
|
1325
|
-
"invocation_envelope": {
|
|
1326
|
-
"record_type": "invocation",
|
|
1327
|
-
"source_output_ref": "L1:1111111111111111111111111111111111111111111111111111111111111111:2222222222222222222222222222222222222222222222222222222222222222:3333333333333333333333333333333333333333333333333333333333333333",
|
|
1328
|
-
"source_batch_id": "",
|
|
1329
|
-
"source_lane_id": "",
|
|
1330
|
-
"source_agent": "",
|
|
1331
|
-
"source_digest": "",
|
|
1332
|
-
"row_format_version": 1,
|
|
1333
|
-
"record_version": { "major": 1, "minor": 1 },
|
|
1334
|
-
"produced_at": "2025-06-22T14:30:00.000Z",
|
|
1335
|
-
"format_families_detected": [],
|
|
1336
|
-
"candidate_count": 0,
|
|
1337
|
-
"parse_errors": 0,
|
|
1338
|
-
"malformed_rows": 0,
|
|
1339
|
-
"clean_attestation_count": 0
|
|
1340
|
-
},
|
|
1341
|
-
"diagnostics": {
|
|
1342
|
-
"candidate_count": 0,
|
|
1343
|
-
"parse_errors": 0,
|
|
1344
|
-
"parse_error_details": [],
|
|
1345
|
-
"malformed_rows": 0,
|
|
1346
|
-
"duplicate_id_count": 0,
|
|
1347
|
-
"duplicate_id_warnings": [],
|
|
1348
|
-
"degraded_source_count": 0,
|
|
1349
|
-
"incomplete_source_count": 0,
|
|
1350
|
-
"format_families_detected": [],
|
|
1351
|
-
"clean_attestation_count": 0
|
|
1352
|
-
}
|
|
1353
|
-
}
|
|
1354
|
-
```
|
|
1355
|
-
|
|
1356
|
-
### Step 3 — Filter and group
|
|
1357
|
-
|
|
1358
|
-
The orchestrator filters the returned `candidates[]` array by `producer: "swarm-pr-review"` and the exact allowed `source_batch_id` / `source_lane_id` tuples, then groups
|
|
1359
|
-
the candidates. In this synthetic example, the two candidates above are grouped
|
|
1360
|
-
by file area:
|
|
1361
|
-
|
|
1362
|
-
- **Chunk A — `src/utils/`** (1 candidate): C-001
|
|
1363
|
-
- **Chunk B — `src/services/`** (1 candidate): C-002
|
|
1364
|
-
|
|
1365
|
-
If there were more candidates, the orchestrator would also group by category
|
|
1366
|
-
(e.g., `null-safety`, `async-ordering`) and cap each chunk at 50 candidates.
|
|
1367
|
-
|
|
1368
|
-
### Step 4 — Dispatch reviewer lanes
|
|
1369
|
-
|
|
1370
|
-
The orchestrator dispatches one reviewer lane per chunk:
|
|
1371
|
-
|
|
1372
|
-
```text
|
|
1373
|
-
You are the independent reviewer. Validate only the candidates assigned below.
|
|
1374
|
-
Do not search for new issues except where needed to validate reachability or
|
|
1375
|
-
mitigation. Do not trust explorer severity.
|
|
1376
|
-
|
|
1377
|
-
Context pack summary:
|
|
1378
|
-
- scope: ...
|
|
1379
|
-
- obligations: ...
|
|
1380
|
-
- impact cone: ...
|
|
1381
|
-
- deterministic signals: ...
|
|
1382
|
-
- relevant Swarm artifacts / knowledge: ...
|
|
1383
|
-
- base_ref: <commit SHA of base branch>
|
|
1384
|
-
- head_ref: <commit SHA of PR head branch>
|
|
1385
|
-
|
|
1386
|
-
Candidates (Chunk A — src/utils/):
|
|
1387
|
-
- C-001 | HIGH | null-safety | src/utils/cache.ts:142 | Uncached getter may return undefined on cold start
|
|
1388
|
-
|
|
1389
|
-
For each candidate, return:
|
|
1390
|
-
[REVIEWED] | candidate_id | CONFIRMED/DISPROVED/UNVERIFIED/PRE_EXISTING | evidence_type | final_severity | introduced_by_pr | file:line | rationale | falsification_probe | reviewer_id
|
|
1391
|
-
|
|
1392
|
-
You must check caller context, reachability, schema/middleware/framework mitigations, state-machine constraints, test coverage, PR-introducedness, and severity.
|
|
1393
|
-
|
|
1394
|
-
IMPORTANT: If a finding claims behavior is "new" or "introduced by the PR", you MUST read the equivalent code on the base branch (git show <base_ref>:<file>) to verify it was not present before. A reviewer claim of "this is new" is invalid without base-branch evidence. Do not compare the new code to an idealized baseline — compare it to what actually existed on the base branch at the time of the PR.
|
|
1395
|
-
```
|
|
1396
|
-
|
|
1397
|
-
### Key invariants
|
|
1398
|
-
|
|
1399
|
-
- The parser reads the **full artifact**, not a preview. Truncation in the
|
|
1400
|
-
`dispatch_lanes` preview does not affect candidate extraction.
|
|
1401
|
-
- The orchestrator never classifies candidates — it only filters, groups, and
|
|
1402
|
-
routes them.
|
|
1403
|
-
- Each reviewer receives a bounded chunk. A chunk with more than 50 candidates
|
|
1404
|
-
is split before dispatch.
|
|
1405
|
-
- The `invocation_envelope` in the parser response provides audit provenance
|
|
1406
|
-
for every extracted candidate.
|
|
1168
|
+
For the full parser-based candidate extraction dry-run example, read `references/parser-dry-run.md`.
|
|
1407
1169
|
|
|
1408
1170
|
---
|
|
1409
1171
|
|
|
@@ -1522,7 +1284,7 @@ If any reviewer lane lacks a parseable `[REVIEWED]` row after bounded
|
|
|
1522
1284
|
re-dispatch, the reviewer dimension is BLOCKED. Do not infer or silently
|
|
1523
1285
|
downgrade a verdict.
|
|
1524
1286
|
|
|
1525
|
-
**COVERAGE GATE CONDITION:** If ANY validation dimension shows incomplete coverage (lanes that failed and were not closed by retry or verified equivalent alternative, CI that did not run, tools that were unavailable after retry), the Pre-Synthesis Gate FAILS. Do not proceed to final output. Surface
|
|
1287
|
+
**COVERAGE GATE CONDITION:** If ANY validation dimension shows incomplete coverage (lanes that failed and were not closed by retry or verified equivalent alternative, CI that did not run, tools that were unavailable after retry), the Pre-Synthesis Gate FAILS — apply the COVERAGE GATE (Phase 3). Do not proceed to final output. Surface unclosed gaps with exact failing dimensions and retry/equivalence evidence.
|
|
1526
1288
|
|
|
1527
1289
|
---
|
|
1528
1290
|
|
|
@@ -1630,109 +1392,7 @@ Use this exact continuation prompt format:
|
|
|
1630
1392
|
|
|
1631
1393
|
---
|
|
1632
1394
|
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
Use this template when dispatching reviewer subagents:
|
|
1636
|
-
|
|
1637
|
-
```text
|
|
1638
|
-
You are the independent reviewer. Validate only the candidates assigned below.
|
|
1639
|
-
Do not search for new issues except where needed to validate reachability or mitigation.
|
|
1640
|
-
Do not trust explorer severity.
|
|
1641
|
-
|
|
1642
|
-
Context pack summary:
|
|
1643
|
-
- scope: ...
|
|
1644
|
-
- obligations: ...
|
|
1645
|
-
- impact cone: ...
|
|
1646
|
-
- deterministic signals: ...
|
|
1647
|
-
- relevant Swarm artifacts / knowledge: ...
|
|
1648
|
-
- base_ref: <commit SHA of base branch>
|
|
1649
|
-
- head_ref: <commit SHA of PR head branch>
|
|
1650
|
-
|
|
1651
|
-
Candidates:
|
|
1652
|
-
- ...
|
|
1653
|
-
|
|
1654
|
-
For each candidate, return:
|
|
1655
|
-
[REVIEWED] | candidate_id | CONFIRMED/DISPROVED/UNVERIFIED/PRE_EXISTING | evidence_type | final_severity | introduced_by_pr | file:line | rationale | falsification_probe | reviewer_id
|
|
1656
|
-
|
|
1657
|
-
You must check caller context, reachability, schema/middleware/framework mitigations, state-machine constraints, test coverage, PR-introducedness, and severity.
|
|
1658
|
-
|
|
1659
|
-
IMPORTANT: If a finding claims behavior is "new" or "introduced by the PR", you MUST read the equivalent code on the base branch (git show <base_ref>:<file>) to verify it was not present before. A reviewer claim of "this is new" is invalid without base-branch evidence. Do not compare the new code to an idealized baseline — compare it to what actually existed on the base branch at the time of the PR.
|
|
1660
|
-
```
|
|
1661
|
-
|
|
1662
|
-
---
|
|
1663
|
-
|
|
1664
|
-
# Critic Prompt Template
|
|
1665
|
-
|
|
1666
|
-
Use this template when dispatching critic subagents:
|
|
1667
|
-
|
|
1668
|
-
```text
|
|
1669
|
-
You are the adversarial critic. Challenge only reviewer-confirmed findings assigned below.
|
|
1670
|
-
Your goal is to reduce false positives, severity inflation, and non-actionable reports.
|
|
1671
|
-
|
|
1672
|
-
For each finding, challenge:
|
|
1673
|
-
- whether evidence proves the claim,
|
|
1674
|
-
- whether the path is reachable,
|
|
1675
|
-
- whether mitigations apply,
|
|
1676
|
-
- whether severity is inflated,
|
|
1677
|
-
- whether it is PR-introduced,
|
|
1678
|
-
- whether suggested fixes are safe/actionable,
|
|
1679
|
-
- whether related files were missed,
|
|
1680
|
-
- whether multiple findings should be grouped.
|
|
1681
|
-
|
|
1682
|
-
Return:
|
|
1683
|
-
[CRITIC] | finding_id | UPHELD/DOWNGRADED/DISPROVED/NEEDS_MORE_EVIDENCE | final_severity | reason | required_report_change
|
|
1684
|
-
|
|
1685
|
-
REQUIRED FINAL LINE — your final line MUST be exactly the row above (no variations, no labeled fields, no placeholders):
|
|
1686
|
-
[CRITIC] | finding_id | UPHELD/DOWNGRADED/DISPROVED/NEEDS_MORE_EVIDENCE | final_severity | reason | required_report_change
|
|
1687
|
-
|
|
1688
|
-
A response without this exact row is treated as a planning preamble and re-dispatched. Do not output only a planning or investigation message.
|
|
1689
|
-
```
|
|
1690
|
-
|
|
1691
|
-
---
|
|
1692
|
-
|
|
1693
|
-
# Explorer Prompt Template
|
|
1694
|
-
|
|
1695
|
-
Use this template when dispatching base explorer or micro-lane agents:
|
|
1696
|
-
|
|
1697
|
-
```text
|
|
1698
|
-
You are an explorer. Optimize for recall, not final judgment.
|
|
1699
|
-
Return candidates only. Do not use CONFIRMED, DISPROVED, or PRE_EXISTING.
|
|
1700
|
-
|
|
1701
|
-
Lane:
|
|
1702
|
-
Scope:
|
|
1703
|
-
base_ref:
|
|
1704
|
-
head_ref:
|
|
1705
|
-
Obligations:
|
|
1706
|
-
Changed files/hunks:
|
|
1707
|
-
Impact cone:
|
|
1708
|
-
Relevant deterministic signals:
|
|
1709
|
-
Relevant Swarm artifacts / knowledge:
|
|
1710
|
-
Checklist:
|
|
1711
|
-
|
|
1712
|
-
You must inspect or mark unavailable:
|
|
1713
|
-
1. changed hunk,
|
|
1714
|
-
2. caller/consumer,
|
|
1715
|
-
3. callee/dependency,
|
|
1716
|
-
4. sibling implementation or prior pattern,
|
|
1717
|
-
5. nearest test or missing-test location,
|
|
1718
|
-
6. deterministic signals,
|
|
1719
|
-
7. Swarm artifacts/knowledge,
|
|
1720
|
-
8. the exact `base_sha...pr_head_sha` merge-base range and both endpoint revisions.
|
|
1721
|
-
|
|
1722
|
-
Return:
|
|
1723
|
-
[CANDIDATE] | candidate_id | lane | severity | category | file:line | claim | evidence_summary | impact_context | confidence
|
|
1724
|
-
Emit the marker-bearing header once, then unprefixed data rows.
|
|
1725
|
-
For a clean micro-lane, emit `[CLEAN] | micro_lane | coverage_scope | evidence`.
|
|
1726
|
-
For a clean base lane, emit `[CLEAN] | workflow_lane | coverage_scope | evidence`.
|
|
1727
|
-
```
|
|
1728
|
-
|
|
1729
|
-
The orchestrator extracts candidates from the full lane artifact via
|
|
1730
|
-
`parse_lane_candidates` as the primary mechanism. The `[CANDIDATE]` row
|
|
1731
|
-
format above is a fallback convention for environments where the parser is
|
|
1732
|
-
unavailable. Explorers should still emit structured records regardless of
|
|
1733
|
-
whether the parser is present.
|
|
1734
|
-
|
|
1735
|
-
Do not let speed degrade validation quality.
|
|
1395
|
+
For reviewer, critic, and explorer prompt templates, read `references/prompt-templates.md`.
|
|
1736
1396
|
|
|
1737
1397
|
After metrics and durable review artifacts are complete, but before emitting the
|
|
1738
1398
|
user-facing final report, call `complete_pr_workflow` with mode `PR_REVIEW` and
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
# Dry-Run: Parser-Based Candidate Extraction
|
|
2
|
+
|
|
3
|
+
This section demonstrates the new parser-based extraction path end-to-end
|
|
4
|
+
using synthetic data. It is concrete enough to implement the same pattern in
|
|
5
|
+
another skill.
|
|
6
|
+
|
|
7
|
+
### Scenario
|
|
8
|
+
|
|
9
|
+
A PR review has dispatched six base explorer lanes via `dispatch_lanes_async`.
|
|
10
|
+
The batch completed and `collect_lane_results` returned:
|
|
11
|
+
|
|
12
|
+
```json
|
|
13
|
+
{
|
|
14
|
+
"batch_id": "batch-a1b2c3",
|
|
15
|
+
"lane_results": [
|
|
16
|
+
{
|
|
17
|
+
"lane_id": "pr_review_lane1_correctness",
|
|
18
|
+
"status": "completed",
|
|
19
|
+
"output_ref": "L1:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
|
|
20
|
+
"output_degraded": false
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"lane_id": "pr_review_lane2_security",
|
|
24
|
+
"status": "completed",
|
|
25
|
+
"output_ref": "L1:dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd:eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
|
26
|
+
"output_degraded": false
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Step 1 — Call the parser
|
|
33
|
+
|
|
34
|
+
The orchestrator calls `parse_lane_candidates` for each `output_ref`:
|
|
35
|
+
|
|
36
|
+
```json
|
|
37
|
+
{
|
|
38
|
+
"tool": "parse_lane_candidates",
|
|
39
|
+
"arguments": {
|
|
40
|
+
"output_ref": "L1:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
|
|
41
|
+
"producer": "swarm-pr-review",
|
|
42
|
+
"expected_family": "base_explorer"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Step 2 — Structured response
|
|
48
|
+
|
|
49
|
+
The parser returns a `ParseResultWithSidecar`. On success, `error` and `error_code` are absent:
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
{
|
|
53
|
+
"candidates": [
|
|
54
|
+
{
|
|
55
|
+
"record_type": "candidate",
|
|
56
|
+
"row_format_family": "base_explorer",
|
|
57
|
+
"row_format_version": 1,
|
|
58
|
+
"record_version": { "major": 1, "minor": 1 },
|
|
59
|
+
"source_output_ref": "L1:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
|
|
60
|
+
"source_batch_id": "B-2025-06-22-001",
|
|
61
|
+
"source_lane_id": "explorer-1",
|
|
62
|
+
"source_agent": "paid_explorer",
|
|
63
|
+
"source_digest": "sha256:abc123def456...",
|
|
64
|
+
"extracted_from_partial_source": false,
|
|
65
|
+
"sessionId": "ses_01HXYZ...",
|
|
66
|
+
"parentSessionId": "ses_01HABC...",
|
|
67
|
+
"producer": "swarm-pr-review",
|
|
68
|
+
"candidate_id": "C-001",
|
|
69
|
+
"lane": "Lane 1: Correctness and edge cases",
|
|
70
|
+
"micro_lane": null,
|
|
71
|
+
"severity": "HIGH",
|
|
72
|
+
"category": "null-safety",
|
|
73
|
+
"file_line": "src/utils/cache.ts:142",
|
|
74
|
+
"claim": "Uncached getter may return undefined on cold start",
|
|
75
|
+
"evidence_summary": "The `getCached` function returns `cache[key]` without a fallback when the cache is empty.",
|
|
76
|
+
"impact_context": "Downstream callers in `src/handlers/*.ts` expect a defined value and call `.toString()` directly.",
|
|
77
|
+
"invariant_violated": null,
|
|
78
|
+
"confidence": "HIGH"
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"record_type": "candidate",
|
|
82
|
+
"row_format_family": "base_explorer",
|
|
83
|
+
"row_format_version": 1,
|
|
84
|
+
"record_version": { "major": 1, "minor": 1 },
|
|
85
|
+
"source_output_ref": "L1:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
|
|
86
|
+
"source_batch_id": "B-2025-06-22-001",
|
|
87
|
+
"source_lane_id": "explorer-1",
|
|
88
|
+
"source_agent": "paid_explorer",
|
|
89
|
+
"source_digest": "sha256:abc123def456...",
|
|
90
|
+
"extracted_from_partial_source": false,
|
|
91
|
+
"sessionId": "ses_01HXYZ...",
|
|
92
|
+
"parentSessionId": "ses_01HABC...",
|
|
93
|
+
"producer": "swarm-pr-review",
|
|
94
|
+
"candidate_id": "C-002",
|
|
95
|
+
"lane": "Lane 1: Correctness and edge cases",
|
|
96
|
+
"micro_lane": null,
|
|
97
|
+
"severity": "MEDIUM",
|
|
98
|
+
"category": "async-ordering",
|
|
99
|
+
"file_line": "src/services/queue.ts:88",
|
|
100
|
+
"claim": "Race between `drain` and `processNext` may drop items",
|
|
101
|
+
"evidence_summary": "`drain` sets `active = false` before awaiting `processNext`, which also checks `active`.",
|
|
102
|
+
"impact_context": "Items submitted during the drain window are silently dropped.",
|
|
103
|
+
"invariant_violated": null,
|
|
104
|
+
"confidence": "MEDIUM"
|
|
105
|
+
}
|
|
106
|
+
],
|
|
107
|
+
"invocation_envelope": {
|
|
108
|
+
"record_type": "invocation",
|
|
109
|
+
"source_output_ref": "L1:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
|
|
110
|
+
"source_batch_id": "B-2025-06-22-001",
|
|
111
|
+
"source_lane_id": "explorer-1",
|
|
112
|
+
"source_agent": "paid_explorer",
|
|
113
|
+
"source_digest": "sha256:abc123def456...",
|
|
114
|
+
"row_format_version": 1,
|
|
115
|
+
"record_version": { "major": 1, "minor": 1 },
|
|
116
|
+
"sessionId": "ses_01HXYZ...",
|
|
117
|
+
"parentSessionId": "ses_01HABC...",
|
|
118
|
+
"producer": "swarm-pr-review",
|
|
119
|
+
"produced_at": "2025-06-22T14:30:00.000Z",
|
|
120
|
+
"format_families_detected": ["base_explorer"],
|
|
121
|
+
"candidate_count": 2,
|
|
122
|
+
"parse_errors": 0,
|
|
123
|
+
"malformed_rows": 0,
|
|
124
|
+
"clean_attestation_count": 0
|
|
125
|
+
},
|
|
126
|
+
"diagnostics": {
|
|
127
|
+
"candidate_count": 2,
|
|
128
|
+
"parse_errors": 0,
|
|
129
|
+
"parse_error_details": [],
|
|
130
|
+
"malformed_rows": 0,
|
|
131
|
+
"duplicate_id_count": 0,
|
|
132
|
+
"duplicate_id_warnings": [],
|
|
133
|
+
"degraded_source_count": 0,
|
|
134
|
+
"incomplete_source_count": 0,
|
|
135
|
+
"format_families_detected": ["base_explorer"],
|
|
136
|
+
"clean_attestation_count": 0
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
> **Note**: callers pass `expected_family` for each dispatch batch. A recognizable
|
|
141
|
+
> conflicting header fails closed with `expected-family-mismatch`; when the flag
|
|
142
|
+
> is absent, the recognized header controls the mapping and positional detection
|
|
143
|
+
> is only a legacy unknown-header fallback. Marker-prefixed data rows remain
|
|
144
|
+
> accepted for compatibility. Valid canonical rows produce `parse_errors: 0`.
|
|
145
|
+
|
|
146
|
+
On refusal (e.g. `output_ref` does not exist), `error` and `error_code` are present; `candidates` is `[]`; `invocation_envelope` and `diagnostics` are populated with empty fields for traceability:
|
|
147
|
+
|
|
148
|
+
```json
|
|
149
|
+
{
|
|
150
|
+
"error": "Artifact reference not found in store",
|
|
151
|
+
"error_code": "ref-not-found",
|
|
152
|
+
"candidates": [],
|
|
153
|
+
"invocation_envelope": {
|
|
154
|
+
"record_type": "invocation",
|
|
155
|
+
"source_output_ref": "L1:1111111111111111111111111111111111111111111111111111111111111111:2222222222222222222222222222222222222222222222222222222222222222:3333333333333333333333333333333333333333333333333333333333333333",
|
|
156
|
+
"source_batch_id": "",
|
|
157
|
+
"source_lane_id": "",
|
|
158
|
+
"source_agent": "",
|
|
159
|
+
"source_digest": "",
|
|
160
|
+
"row_format_version": 1,
|
|
161
|
+
"record_version": { "major": 1, "minor": 1 },
|
|
162
|
+
"produced_at": "2025-06-22T14:30:00.000Z",
|
|
163
|
+
"format_families_detected": [],
|
|
164
|
+
"candidate_count": 0,
|
|
165
|
+
"parse_errors": 0,
|
|
166
|
+
"malformed_rows": 0,
|
|
167
|
+
"clean_attestation_count": 0
|
|
168
|
+
},
|
|
169
|
+
"diagnostics": {
|
|
170
|
+
"candidate_count": 0,
|
|
171
|
+
"parse_errors": 0,
|
|
172
|
+
"parse_error_details": [],
|
|
173
|
+
"malformed_rows": 0,
|
|
174
|
+
"duplicate_id_count": 0,
|
|
175
|
+
"duplicate_id_warnings": [],
|
|
176
|
+
"degraded_source_count": 0,
|
|
177
|
+
"incomplete_source_count": 0,
|
|
178
|
+
"format_families_detected": [],
|
|
179
|
+
"clean_attestation_count": 0
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Step 3 — Filter and group
|
|
185
|
+
|
|
186
|
+
The orchestrator filters the returned `candidates[]` array by `producer: "swarm-pr-review"` and the exact allowed `source_batch_id` / `source_lane_id` tuples, then groups
|
|
187
|
+
the candidates. In this synthetic example, the two candidates above are grouped
|
|
188
|
+
by file area:
|
|
189
|
+
|
|
190
|
+
- **Chunk A — `src/utils/`** (1 candidate): C-001
|
|
191
|
+
- **Chunk B — `src/services/`** (1 candidate): C-002
|
|
192
|
+
|
|
193
|
+
If there were more candidates, the orchestrator would also group by category
|
|
194
|
+
(e.g., `null-safety`, `async-ordering`) and cap each chunk at 50 candidates.
|
|
195
|
+
|
|
196
|
+
### Step 4 — Dispatch reviewer lanes
|
|
197
|
+
|
|
198
|
+
The orchestrator dispatches one reviewer lane per chunk:
|
|
199
|
+
|
|
200
|
+
```text
|
|
201
|
+
You are the independent reviewer. Validate only the candidates assigned below.
|
|
202
|
+
Do not search for new issues except where needed to validate reachability or
|
|
203
|
+
mitigation. Do not trust explorer severity.
|
|
204
|
+
|
|
205
|
+
Context pack summary:
|
|
206
|
+
- scope: ...
|
|
207
|
+
- obligations: ...
|
|
208
|
+
- impact cone: ...
|
|
209
|
+
- deterministic signals: ...
|
|
210
|
+
- relevant Swarm artifacts / knowledge: ...
|
|
211
|
+
- base_ref: <commit SHA of base branch>
|
|
212
|
+
- head_ref: <commit SHA of PR head branch>
|
|
213
|
+
|
|
214
|
+
Candidates (Chunk A — src/utils/):
|
|
215
|
+
- C-001 | HIGH | null-safety | src/utils/cache.ts:142 | Uncached getter may return undefined on cold start
|
|
216
|
+
|
|
217
|
+
For each candidate, return:
|
|
218
|
+
[REVIEWED] | candidate_id | CONFIRMED/DISPROVED/UNVERIFIED/PRE_EXISTING | evidence_type | final_severity | introduced_by_pr | file:line | rationale | falsification_probe | reviewer_id
|
|
219
|
+
|
|
220
|
+
You must check caller context, reachability, schema/middleware/framework mitigations, state-machine constraints, test coverage, PR-introducedness, and severity.
|
|
221
|
+
|
|
222
|
+
IMPORTANT: If a finding claims behavior is "new" or "introduced by the PR", you MUST read the equivalent code on the base branch (git show <base_ref>:<file>) to verify it was not present before. A reviewer claim of "this is new" is invalid without base-branch evidence. Do not compare the new code to an idealized baseline — compare it to what actually existed on the base branch at the time of the PR.
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Key invariants
|
|
226
|
+
|
|
227
|
+
- The parser reads the **full artifact**, not a preview. Truncation in the
|
|
228
|
+
`dispatch_lanes` preview does not affect candidate extraction.
|
|
229
|
+
- The orchestrator never classifies candidates — it only filters, groups, and
|
|
230
|
+
routes them.
|
|
231
|
+
- Each reviewer receives a bounded chunk. A chunk with more than 50 candidates
|
|
232
|
+
is split before dispatch.
|
|
233
|
+
- The `invocation_envelope` in the parser response provides audit provenance
|
|
234
|
+
for every extracted candidate.
|
|
235
|
+
|