opencode-swarm 7.160.0 → 7.160.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/critic-gate/SKILL.md +8 -1
- package/.opencode/skills/execute/SKILL.md +4 -3
- package/.opencode/skills/phase-wrap/SKILL.md +2 -0
- package/.opencode/skills/running-tests/SKILL.md +6 -0
- package/.opencode/skills/swarm-implement/SKILL.md +2 -0
- package/.opencode/skills/swarm-pr-review/SKILL.md +29 -29
- package/.opencode/skills/swarm-pr-review/references/prompt-templates.md +21 -5
- package/dist/agents/architect.d.ts +1 -1
- package/dist/background/pending-delegations.d.ts +46 -1
- package/dist/background/pr-review-contract.d.ts +245 -2
- package/dist/build/command-resolution.d.ts +13 -0
- package/dist/build/discovery.d.ts +11 -4
- package/dist/cli/{coder-settlement-zn552sp9.js → coder-settlement-gzar5ypz.js} +9 -9
- package/dist/cli/{config-doctor-ddtdz2g0.js → config-doctor-ancn1sj7.js} +3 -3
- package/dist/cli/{core-embasn2j.js → core-bhmqtxev.js} +2 -2
- package/dist/cli/{curation-policy-agr6ga1s.js → curation-policy-47przjwg.js} +4 -4
- package/dist/cli/curator-llm-factory-6mw01jx1.js +67 -0
- package/dist/cli/{curator-dgp6dxxn.js → curator-sgmynbpm.js} +32 -32
- package/dist/cli/{dispatch-7r46tfr9.js → dispatch-q4v8x2pk.js} +1 -1
- package/dist/cli/{evidence-summary-service-sbnyann4.js → evidence-summary-service-1pcfsqhv.js} +13 -13
- package/dist/cli/{gate-evidence-5v67a1dz.js → gate-evidence-w0kjqmew.js} +5 -5
- package/dist/cli/guardrail-explain-k99eje1y.js +68 -0
- package/dist/cli/{guardrail-log-zbnbff1y.js → guardrail-log-md5gcpk7.js} +7 -7
- package/dist/cli/{guardrail-reset-3cnz54hx.js → guardrail-reset-3385eqmq.js} +32 -32
- package/dist/cli/{hive-promoter-7cr7t2kg.js → hive-promoter-r0ekyn5m.js} +32 -32
- package/dist/cli/{index-wzx6atbv.js → index-2123hwbj.js} +3 -3
- package/dist/cli/{index-nj6rmyeh.js → index-3146wmgv.js} +352 -149
- package/dist/cli/{index-5m7qjj29.js → index-3a35tt6a.js} +6 -6
- package/dist/cli/{index-q6gjwy7m.js → index-497a3hhj.js} +2 -2
- package/dist/cli/{index-7qv869f0.js → index-4d8cq6e1.js} +5 -5
- package/dist/cli/{index-w699ekk9.js → index-4dcz9fpn.js} +2 -2
- package/dist/cli/{index-zjvf7edj.js → index-5th50g17.js} +1 -1
- package/dist/cli/{index-va1edd2n.js → index-5xfx5sbw.js} +5 -5
- package/dist/cli/{index-1f4n43yz.js → index-6scakreq.js} +5 -4
- package/dist/cli/{index-962jgzdq.js → index-717pmdce.js} +1 -1
- package/dist/cli/{index-rq7k03rk.js → index-7ezv5j23.js} +1 -1
- package/dist/cli/{index-4mm22fzj.js → index-7h2armwf.js} +1 -1
- package/dist/cli/{index-gt8cxfbp.js → index-am5bz6mf.js} +2 -2
- package/dist/cli/{index-cn233hsy.js → index-awjx0wgk.js} +1 -1
- package/dist/cli/{index-h3re5c78.js → index-c9zp4xwc.js} +12 -1
- package/dist/cli/{index-p39xem8b.js → index-dh5q6z7y.js} +3 -3
- package/dist/cli/{index-xs15netk.js → index-j3ss86kf.js} +1 -1
- package/dist/cli/{index-d9s5hb0m.js → index-k0qy284k.js} +5 -5
- package/dist/cli/{index-sy5aeegg.js → index-k50kxd3w.js} +866 -37
- package/dist/cli/{index-fzkx24q5.js → index-kqzba6ex.js} +2 -2
- package/dist/cli/{index-e75bzfgd.js → index-mmr96pwr.js} +1 -1
- package/dist/cli/{index-85qjc7b2.js → index-nk498mx6.js} +1 -1
- package/dist/cli/{index-9fspg1xw.js → index-prv20xq6.js} +1 -1
- package/dist/cli/{index-ebz97mks.js → index-q8hm27yj.js} +8 -1
- package/dist/cli/{index-8bjv01t8.js → index-re338hf1.js} +4 -4
- package/dist/cli/{index-rnyt2z5r.js → index-s7w6ntw6.js} +321 -448
- package/dist/cli/{index-jmths6jj.js → index-vsy942dt.js} +34 -34
- package/dist/cli/{index-rhc8jve7.js → index-vv760pbg.js} +2 -2
- package/dist/cli/{index-3yh737hc.js → index-war2dt6a.js} +6 -6
- package/dist/cli/{index-yrar1ask.js → index-xkmzsfg5.js} +3 -3
- package/dist/cli/{index-3055dgzp.js → index-xsd7y4hp.js} +4 -4
- package/dist/cli/{index-py6bqwnb.js → index-xtwny1ae.js} +16 -2
- package/dist/cli/{index-9q6w7kke.js → index-yd6y4qr7.js} +1 -1
- package/dist/cli/{index-kkfgygvn.js → index-yp81ebrx.js} +4 -4
- package/dist/cli/{index-9k3zc2t8.js → index-zbnf26br.js} +6 -6
- package/dist/cli/{index-s7w428r3.js → index-znf683sm.js} +1 -1
- package/dist/cli/index.js +32 -32
- package/dist/cli/{knowledge-escalator-zksm9833.js → knowledge-escalator-saekqp8t.js} +12 -12
- package/dist/cli/{knowledge-events-ayta750w.js → knowledge-events-ej8yz3yq.js} +10 -10
- package/dist/cli/{knowledge-link-7c7fjnzc.js → knowledge-link-xezm8hr3.js} +3 -3
- package/dist/cli/{knowledge-store-q5axge8b.js → knowledge-store-3jamj5n4.js} +4 -4
- package/dist/cli/{knowledge-validator-3rrbva2p.js → knowledge-validator-26w2mvqv.js} +6 -6
- package/dist/cli/{model-preflight-x9szw1v4.js → model-preflight-yqqchzjn.js} +1 -1
- package/dist/cli/{pending-delegations-kc7tzxg9.js → pending-delegations-7xak7g59.js} +5 -3
- package/dist/cli/{pr-review-reentry-authorization-vag5gh50.js → pr-review-reentry-authorization-v97q63q4.js} +34 -33
- package/dist/cli/{pr-subscriptions-wbdw9a82.js → pr-subscriptions-asjevc5p.js} +3 -3
- package/dist/cli/{runner-p9wg6z34.js → runner-wsdcy2d6.js} +4 -4
- package/dist/cli/{scan-cursor-4fjwtt1k.js → scan-cursor-1agr50f8.js} +5 -5
- package/dist/cli/{schema-d0nbzj5k.js → schema-z0ygrqgy.js} +4 -2
- package/dist/cli/{scope-persistence-bckcbc8h.js → scope-persistence-tncg38by.js} +8 -8
- package/dist/cli/{skill-generator-kebhevet.js → skill-generator-jq20a09m.js} +14 -14
- package/dist/cli/{worktree-collision-ownership-h8qswnrp.js → worktree-collision-ownership-b9cp9zvw.js} +4 -4
- package/dist/cli/{worktree-isolation-q0kbmadz.js → worktree-isolation-dzyxf8hn.js} +32 -32
- package/dist/config/constants.d.ts +8 -0
- package/dist/config/evidence-schema.d.ts +21 -0
- package/dist/config/schema.d.ts +8 -0
- package/dist/hooks/pr-workflow-gate.d.ts +25 -1
- package/dist/index.js +333 -319
- package/dist/lang/default-backend.d.ts +1 -13
- package/dist/tools/build-check.d.ts +4 -0
- package/dist/tools/dispatch-lanes.d.ts +27 -3
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/manifest.d.ts +1 -0
- package/dist/tools/sast-baseline.d.ts +2 -0
- package/dist/tools/sast-scan.d.ts +2 -2
- package/dist/tools/submit-pr-review-result.d.ts +5 -0
- package/dist/tools/test-runner.d.ts +2 -0
- package/dist/tools/tool-metadata.d.ts +8 -0
- package/opencode-swarm.schema.json +4 -0
- package/package.json +1 -1
- package/dist/cli/curator-llm-factory-7cwvmc46.js +0 -67
- package/dist/cli/guardrail-explain-2gwarnca.js +0 -68
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
} from "./index-r3mvsbtq.js";
|
|
11
11
|
import {
|
|
12
12
|
observeDelegationLedgerPressure
|
|
13
|
-
} from "./index-
|
|
13
|
+
} from "./index-mmr96pwr.js";
|
|
14
14
|
import {
|
|
15
15
|
EvidenceLockTimeoutError,
|
|
16
16
|
withEvidenceLock
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
init_zod
|
|
21
21
|
} from "./index-bpmtbmy9.js";
|
|
22
22
|
import {
|
|
23
|
+
criticalWarn,
|
|
23
24
|
init_logger,
|
|
24
25
|
warn
|
|
25
26
|
} from "./index-zgwm4ryv.js";
|
|
@@ -29,7 +30,7 @@ import {
|
|
|
29
30
|
|
|
30
31
|
// src/background/pending-delegations.ts
|
|
31
32
|
init_zod();
|
|
32
|
-
import { createHash as
|
|
33
|
+
import { createHash as createHash3 } from "crypto";
|
|
33
34
|
import * as fs2 from "fs";
|
|
34
35
|
import * as path2 from "path";
|
|
35
36
|
import { isDeepStrictEqual } from "util";
|
|
@@ -392,6 +393,638 @@ function parsePrReviewCollectionReceiptFooter(binding, result) {
|
|
|
392
393
|
const payload = parsed.data;
|
|
393
394
|
return payload.parentSessionId === binding.parentSessionId && payload.batchId === (binding.batchId ?? binding.callID) && payload.laneId === (binding.laneId ?? binding.correlationId) && payload.mode === binding.mode && payload.workflowLane === binding.workflowLane && payload.outputDigest === result.digest ? payload : null;
|
|
394
395
|
}
|
|
396
|
+
|
|
397
|
+
// src/background/pr-review-contract.ts
|
|
398
|
+
init_zod();
|
|
399
|
+
import { createHash as createHash2 } from "crypto";
|
|
400
|
+
var PR_REVIEW_REVIEWER_CLASSIFICATIONS = [
|
|
401
|
+
"CONFIRMED",
|
|
402
|
+
"DISPROVED",
|
|
403
|
+
"UNVERIFIED",
|
|
404
|
+
"PRE_EXISTING"
|
|
405
|
+
];
|
|
406
|
+
var PR_REVIEW_REVIEWER_EVIDENCE_TYPES = [
|
|
407
|
+
"STRUCTURALLY_PROVEN",
|
|
408
|
+
"EXECUTION_PROVEN",
|
|
409
|
+
"STATIC_TRACE_PROVEN",
|
|
410
|
+
"PLAUSIBLE_BUT_UNVERIFIED"
|
|
411
|
+
];
|
|
412
|
+
var PR_REVIEW_SEVERITIES = [
|
|
413
|
+
"CRITICAL",
|
|
414
|
+
"HIGH",
|
|
415
|
+
"MEDIUM",
|
|
416
|
+
"LOW",
|
|
417
|
+
"INFO",
|
|
418
|
+
"NONE"
|
|
419
|
+
];
|
|
420
|
+
var PR_REVIEW_CRITIC_STATUSES = [
|
|
421
|
+
"UPHELD",
|
|
422
|
+
"DOWNGRADED",
|
|
423
|
+
"DISPROVED",
|
|
424
|
+
"NEEDS_MORE_EVIDENCE"
|
|
425
|
+
];
|
|
426
|
+
var PR_REVIEW_FINDING_STATUSES = [
|
|
427
|
+
"PENDING",
|
|
428
|
+
"CONFIRMED",
|
|
429
|
+
"DISPROVED",
|
|
430
|
+
"PRE_EXISTING"
|
|
431
|
+
];
|
|
432
|
+
var PR_REVIEW_FINDING_ACTIONS = [
|
|
433
|
+
"route_to_reviewer",
|
|
434
|
+
"route_to_critic",
|
|
435
|
+
"report",
|
|
436
|
+
"suppress_with_reason",
|
|
437
|
+
"handoff_to_feedback"
|
|
438
|
+
];
|
|
439
|
+
var PR_REVIEW_ARTIFACT_BOUNDARIES = [
|
|
440
|
+
"post_explorer",
|
|
441
|
+
"post_reviewer",
|
|
442
|
+
"post_critic"
|
|
443
|
+
];
|
|
444
|
+
var PR_REVIEW_BASE_DIMENSION_IDS = [
|
|
445
|
+
"intent-architecture",
|
|
446
|
+
"correctness-state",
|
|
447
|
+
"tests-falsifiability",
|
|
448
|
+
"security-trust",
|
|
449
|
+
"reliability-performance",
|
|
450
|
+
"compatibility-delivery"
|
|
451
|
+
];
|
|
452
|
+
var PR_REVIEW_RISK_IMPACTS = [
|
|
453
|
+
"ORDINARY",
|
|
454
|
+
"HIGH_IMPACT",
|
|
455
|
+
"UNKNOWN"
|
|
456
|
+
];
|
|
457
|
+
var PR_REVIEW_RISK_TAGS = [
|
|
458
|
+
"SECURITY",
|
|
459
|
+
"AUTH_PERMISSIONS",
|
|
460
|
+
"STATE_INTEGRITY",
|
|
461
|
+
"WRITE_PATH",
|
|
462
|
+
"EVIDENCE_INTEGRITY",
|
|
463
|
+
"GIT",
|
|
464
|
+
"CONFIGURATION"
|
|
465
|
+
];
|
|
466
|
+
var PR_REVIEW_RESULT_LANE_MODES = [
|
|
467
|
+
"swarm-pr-review:base",
|
|
468
|
+
"swarm-pr-review:micro"
|
|
469
|
+
];
|
|
470
|
+
var PR_REVIEW_RESULT_OUTCOMES = [
|
|
471
|
+
"CLEAN",
|
|
472
|
+
"FINDINGS",
|
|
473
|
+
"INCOMPLETE"
|
|
474
|
+
];
|
|
475
|
+
var PR_REVIEW_RESULT_FINDING_SEVERITIES = [
|
|
476
|
+
"CRITICAL",
|
|
477
|
+
"HIGH",
|
|
478
|
+
"MEDIUM",
|
|
479
|
+
"LOW",
|
|
480
|
+
"INFO"
|
|
481
|
+
];
|
|
482
|
+
var PR_REVIEW_RESULT_UNRESOLVED_REASONS = [
|
|
483
|
+
"NOT_EXECUTED",
|
|
484
|
+
"PARTIAL_OUTPUT",
|
|
485
|
+
"CONTRACT_FAILURE",
|
|
486
|
+
"RESOURCE_LIMIT",
|
|
487
|
+
"DEADLINE_EXCEEDED",
|
|
488
|
+
"STALE_BINDING",
|
|
489
|
+
"PARENT_CANCELLED"
|
|
490
|
+
];
|
|
491
|
+
var MAX_PR_REVIEW_RESULT_OWNED_LANES = 11;
|
|
492
|
+
var MAX_PR_REVIEW_RESULT_FINDINGS = 256;
|
|
493
|
+
var MAX_PR_REVIEW_RESULT_RECEIPT_BYTES = 64 * 1024;
|
|
494
|
+
function prReviewLegacyTranscriptCompatibilityEnabled(value) {
|
|
495
|
+
return value === true;
|
|
496
|
+
}
|
|
497
|
+
var PrReviewResultLaneIdSchema = exports_external.string().trim().min(1).max(120);
|
|
498
|
+
var PrReviewResultChildSessionSchema = exports_external.string().trim().min(1).max(256);
|
|
499
|
+
var PrReviewResultShaSchema = exports_external.string().trim().regex(/^[0-9a-f]{6,64}$/i);
|
|
500
|
+
var PrReviewResultDigestSchema = exports_external.string().trim().regex(/^[0-9a-f]{64}$/i);
|
|
501
|
+
function addDuplicateIssue(ctx, path2, label, value) {
|
|
502
|
+
ctx.addIssue({
|
|
503
|
+
code: exports_external.ZodIssueCode.custom,
|
|
504
|
+
path: path2,
|
|
505
|
+
message: `${label} must not contain duplicate value "${value}"`
|
|
506
|
+
});
|
|
507
|
+
}
|
|
508
|
+
function assertUniqueStrings(values, ctx, path2, label) {
|
|
509
|
+
const seen = new Set;
|
|
510
|
+
for (const value of values) {
|
|
511
|
+
if (seen.has(value)) {
|
|
512
|
+
addDuplicateIssue(ctx, path2, label, value);
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
seen.add(value);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
var PrReviewResultLocationSchema = exports_external.discriminatedUnion("kind", [
|
|
519
|
+
exports_external.object({
|
|
520
|
+
kind: exports_external.literal("local"),
|
|
521
|
+
file: exports_external.string().trim().min(1).max(4096),
|
|
522
|
+
line: exports_external.number().int().positive().max(1e6).optional(),
|
|
523
|
+
endLine: exports_external.number().int().positive().max(1e6).optional(),
|
|
524
|
+
column: exports_external.number().int().positive().max(1e4).optional(),
|
|
525
|
+
endColumn: exports_external.number().int().positive().max(1e4).optional()
|
|
526
|
+
}).strict().superRefine((value, ctx) => {
|
|
527
|
+
if (value.endLine !== undefined && value.line !== undefined && value.endLine < value.line) {
|
|
528
|
+
ctx.addIssue({
|
|
529
|
+
code: exports_external.ZodIssueCode.custom,
|
|
530
|
+
path: ["endLine"],
|
|
531
|
+
message: "endLine must be greater than or equal to line"
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
if (value.endColumn !== undefined && value.column !== undefined && value.endColumn < value.column) {
|
|
535
|
+
ctx.addIssue({
|
|
536
|
+
code: exports_external.ZodIssueCode.custom,
|
|
537
|
+
path: ["endColumn"],
|
|
538
|
+
message: "endColumn must be greater than or equal to column"
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
}),
|
|
542
|
+
exports_external.object({
|
|
543
|
+
kind: exports_external.literal("non_local"),
|
|
544
|
+
label: exports_external.string().trim().min(1).max(200),
|
|
545
|
+
detail: exports_external.string().trim().min(1).max(2000)
|
|
546
|
+
}).strict()
|
|
547
|
+
]);
|
|
548
|
+
var PrReviewResultFindingSchema = exports_external.object({
|
|
549
|
+
id: exports_external.string().trim().min(1).max(128),
|
|
550
|
+
workflowLane: PrReviewResultLaneIdSchema,
|
|
551
|
+
severity: exports_external.enum(PR_REVIEW_RESULT_FINDING_SEVERITIES),
|
|
552
|
+
riskImpact: exports_external.enum(PR_REVIEW_RISK_IMPACTS),
|
|
553
|
+
riskTags: exports_external.array(exports_external.enum(PR_REVIEW_RISK_TAGS)).max(PR_REVIEW_RISK_TAGS.length),
|
|
554
|
+
title: exports_external.string().trim().min(1).max(200),
|
|
555
|
+
body: exports_external.string().trim().min(1).max(4000),
|
|
556
|
+
evidence: exports_external.string().trim().min(1).max(4000),
|
|
557
|
+
location: PrReviewResultLocationSchema
|
|
558
|
+
}).strict().superRefine((value, ctx) => {
|
|
559
|
+
assertUniqueStrings(value.riskTags, ctx, ["riskTags"], "riskTags");
|
|
560
|
+
});
|
|
561
|
+
var PrReviewCleanAttestationSchema = exports_external.object({
|
|
562
|
+
workflowLane: PrReviewResultLaneIdSchema,
|
|
563
|
+
coverageScope: exports_external.string().trim().min(12).max(2000),
|
|
564
|
+
evidence: exports_external.string().trim().min(20).max(4000)
|
|
565
|
+
}).strict();
|
|
566
|
+
var PrReviewUnresolvedLaneSchema = exports_external.object({
|
|
567
|
+
workflowLane: PrReviewResultLaneIdSchema,
|
|
568
|
+
reason: exports_external.enum(PR_REVIEW_RESULT_UNRESOLVED_REASONS),
|
|
569
|
+
detail: exports_external.string().trim().min(1).max(4000)
|
|
570
|
+
}).strict();
|
|
571
|
+
var PrReviewLaneResultEnvelopeSchema = exports_external.object({
|
|
572
|
+
schemaVersion: exports_external.literal(1),
|
|
573
|
+
outcome: exports_external.enum(PR_REVIEW_RESULT_OUTCOMES),
|
|
574
|
+
creditedLanes: exports_external.array(PrReviewResultLaneIdSchema).max(MAX_PR_REVIEW_RESULT_OWNED_LANES),
|
|
575
|
+
findings: exports_external.array(PrReviewResultFindingSchema).max(MAX_PR_REVIEW_RESULT_FINDINGS),
|
|
576
|
+
cleanAttestations: exports_external.array(PrReviewCleanAttestationSchema).max(MAX_PR_REVIEW_RESULT_OWNED_LANES),
|
|
577
|
+
unresolved: exports_external.array(PrReviewUnresolvedLaneSchema).max(MAX_PR_REVIEW_RESULT_OWNED_LANES)
|
|
578
|
+
}).strict().superRefine((value, ctx) => {
|
|
579
|
+
assertUniqueStrings(value.creditedLanes, ctx, ["creditedLanes"], "creditedLanes");
|
|
580
|
+
const findingIds = value.findings.map((finding) => finding.id);
|
|
581
|
+
assertUniqueStrings(findingIds, ctx, ["findings"], "findings");
|
|
582
|
+
const findingLanes = value.findings.map((finding) => finding.workflowLane);
|
|
583
|
+
assertUniqueStrings(value.cleanAttestations.map((entry) => entry.workflowLane), ctx, ["cleanAttestations"], "cleanAttestations");
|
|
584
|
+
assertUniqueStrings(value.unresolved.map((entry) => entry.workflowLane), ctx, ["unresolved"], "unresolved");
|
|
585
|
+
for (const lane of findingLanes) {
|
|
586
|
+
if (value.cleanAttestations.some((entry) => entry.workflowLane === lane)) {
|
|
587
|
+
ctx.addIssue({
|
|
588
|
+
code: exports_external.ZodIssueCode.custom,
|
|
589
|
+
path: ["findings"],
|
|
590
|
+
message: `workflow lane "${lane}" cannot be both CLEAN and FINDINGS`
|
|
591
|
+
});
|
|
592
|
+
return;
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
const coveredLanes = new Set([
|
|
596
|
+
...findingLanes,
|
|
597
|
+
...value.cleanAttestations.map((entry) => entry.workflowLane)
|
|
598
|
+
]);
|
|
599
|
+
for (const lane of value.creditedLanes) {
|
|
600
|
+
if (!coveredLanes.has(lane)) {
|
|
601
|
+
ctx.addIssue({
|
|
602
|
+
code: exports_external.ZodIssueCode.custom,
|
|
603
|
+
path: ["creditedLanes"],
|
|
604
|
+
message: `credited workflow lane "${lane}" must be backed by a finding or CLEAN attestation`
|
|
605
|
+
});
|
|
606
|
+
return;
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
for (const lane of coveredLanes) {
|
|
610
|
+
if (!value.creditedLanes.includes(lane)) {
|
|
611
|
+
ctx.addIssue({
|
|
612
|
+
code: exports_external.ZodIssueCode.custom,
|
|
613
|
+
path: ["creditedLanes"],
|
|
614
|
+
message: `covered workflow lane "${lane}" must appear in creditedLanes`
|
|
615
|
+
});
|
|
616
|
+
return;
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
for (const lane of value.unresolved.map((entry) => entry.workflowLane)) {
|
|
620
|
+
if (coveredLanes.has(lane)) {
|
|
621
|
+
ctx.addIssue({
|
|
622
|
+
code: exports_external.ZodIssueCode.custom,
|
|
623
|
+
path: ["unresolved"],
|
|
624
|
+
message: `workflow lane "${lane}" cannot be both credited and unresolved`
|
|
625
|
+
});
|
|
626
|
+
return;
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
const totalCovered = value.creditedLanes.length + value.unresolved.length;
|
|
630
|
+
if (totalCovered === 0) {
|
|
631
|
+
ctx.addIssue({
|
|
632
|
+
code: exports_external.ZodIssueCode.custom,
|
|
633
|
+
path: ["creditedLanes"],
|
|
634
|
+
message: "result envelope must cover at least one workflow lane"
|
|
635
|
+
});
|
|
636
|
+
return;
|
|
637
|
+
}
|
|
638
|
+
if (value.outcome === "CLEAN") {
|
|
639
|
+
if (value.findings.length > 0 || value.unresolved.length > 0) {
|
|
640
|
+
ctx.addIssue({
|
|
641
|
+
code: exports_external.ZodIssueCode.custom,
|
|
642
|
+
path: ["outcome"],
|
|
643
|
+
message: "CLEAN outcome cannot include findings or unresolved lanes"
|
|
644
|
+
});
|
|
645
|
+
}
|
|
646
|
+
if (value.cleanAttestations.length !== value.creditedLanes.length) {
|
|
647
|
+
ctx.addIssue({
|
|
648
|
+
code: exports_external.ZodIssueCode.custom,
|
|
649
|
+
path: ["cleanAttestations"],
|
|
650
|
+
message: "CLEAN outcome must attest every credited workflow lane exactly once"
|
|
651
|
+
});
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
if (value.outcome === "FINDINGS") {
|
|
655
|
+
if (value.findings.length === 0) {
|
|
656
|
+
ctx.addIssue({
|
|
657
|
+
code: exports_external.ZodIssueCode.custom,
|
|
658
|
+
path: ["findings"],
|
|
659
|
+
message: "FINDINGS outcome requires at least one finding"
|
|
660
|
+
});
|
|
661
|
+
}
|
|
662
|
+
if (value.unresolved.length > 0) {
|
|
663
|
+
ctx.addIssue({
|
|
664
|
+
code: exports_external.ZodIssueCode.custom,
|
|
665
|
+
path: ["unresolved"],
|
|
666
|
+
message: "FINDINGS outcome cannot include unresolved lanes"
|
|
667
|
+
});
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
if (value.outcome === "INCOMPLETE" && value.unresolved.length === 0) {
|
|
671
|
+
ctx.addIssue({
|
|
672
|
+
code: exports_external.ZodIssueCode.custom,
|
|
673
|
+
path: ["unresolved"],
|
|
674
|
+
message: "INCOMPLETE outcome requires at least one unresolved lane"
|
|
675
|
+
});
|
|
676
|
+
}
|
|
677
|
+
});
|
|
678
|
+
function serializedPrReviewResultReceiptBytes(value) {
|
|
679
|
+
return new TextEncoder().encode(JSON.stringify(value)).byteLength;
|
|
680
|
+
}
|
|
681
|
+
function prReviewLaneResultEnvelopeDigest(value) {
|
|
682
|
+
return createHash2("sha256").update(JSON.stringify(value)).digest("hex");
|
|
683
|
+
}
|
|
684
|
+
var PrReviewResultReceiptSchema = exports_external.object({
|
|
685
|
+
schemaVersion: exports_external.literal(1),
|
|
686
|
+
mode: exports_external.enum(PR_REVIEW_RESULT_LANE_MODES),
|
|
687
|
+
workflowInstanceId: exports_external.string().trim().min(1).max(256),
|
|
688
|
+
workflowRevision: exports_external.number().int().nonnegative(),
|
|
689
|
+
batchId: exports_external.string().trim().min(1).max(120),
|
|
690
|
+
laneId: exports_external.string().trim().min(1).max(120),
|
|
691
|
+
workflowLane: PrReviewResultLaneIdSchema,
|
|
692
|
+
ownedWorkflowLanes: exports_external.array(PrReviewResultLaneIdSchema).min(1).max(MAX_PR_REVIEW_RESULT_OWNED_LANES),
|
|
693
|
+
baseSha: PrReviewResultShaSchema,
|
|
694
|
+
headSha: PrReviewResultShaSchema,
|
|
695
|
+
dispatchRevisionDigest: PrReviewResultDigestSchema,
|
|
696
|
+
childSessionId: PrReviewResultChildSessionSchema,
|
|
697
|
+
generation: exports_external.number().int().positive().max(1e6),
|
|
698
|
+
semanticEnvelopeDigest: PrReviewResultDigestSchema,
|
|
699
|
+
envelope: PrReviewLaneResultEnvelopeSchema
|
|
700
|
+
}).strict().superRefine((value, ctx) => {
|
|
701
|
+
assertUniqueStrings(value.ownedWorkflowLanes, ctx, ["ownedWorkflowLanes"], "ownedWorkflowLanes");
|
|
702
|
+
if (!value.ownedWorkflowLanes.includes(value.workflowLane)) {
|
|
703
|
+
ctx.addIssue({
|
|
704
|
+
code: exports_external.ZodIssueCode.custom,
|
|
705
|
+
path: ["workflowLane"],
|
|
706
|
+
message: "workflowLane must be included in ownedWorkflowLanes"
|
|
707
|
+
});
|
|
708
|
+
}
|
|
709
|
+
const covered = new Set([
|
|
710
|
+
...value.envelope.creditedLanes,
|
|
711
|
+
...value.envelope.unresolved.map((entry) => entry.workflowLane)
|
|
712
|
+
]);
|
|
713
|
+
if (covered.size !== value.ownedWorkflowLanes.length) {
|
|
714
|
+
ctx.addIssue({
|
|
715
|
+
code: exports_external.ZodIssueCode.custom,
|
|
716
|
+
path: ["envelope"],
|
|
717
|
+
message: "envelope credited and unresolved workflow lanes must exactly partition ownedWorkflowLanes"
|
|
718
|
+
});
|
|
719
|
+
return;
|
|
720
|
+
}
|
|
721
|
+
for (const lane of value.ownedWorkflowLanes) {
|
|
722
|
+
if (!covered.has(lane)) {
|
|
723
|
+
ctx.addIssue({
|
|
724
|
+
code: exports_external.ZodIssueCode.custom,
|
|
725
|
+
path: ["ownedWorkflowLanes"],
|
|
726
|
+
message: `owned workflow lane "${lane}" is missing from the envelope coverage`
|
|
727
|
+
});
|
|
728
|
+
return;
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
const expectedDigest = prReviewLaneResultEnvelopeDigest(value.envelope);
|
|
732
|
+
if (value.semanticEnvelopeDigest !== expectedDigest) {
|
|
733
|
+
ctx.addIssue({
|
|
734
|
+
code: exports_external.ZodIssueCode.custom,
|
|
735
|
+
path: ["semanticEnvelopeDigest"],
|
|
736
|
+
message: "semanticEnvelopeDigest must match the canonical envelope digest"
|
|
737
|
+
});
|
|
738
|
+
}
|
|
739
|
+
const bytes = serializedPrReviewResultReceiptBytes(value);
|
|
740
|
+
if (bytes > MAX_PR_REVIEW_RESULT_RECEIPT_BYTES) {
|
|
741
|
+
ctx.addIssue({
|
|
742
|
+
code: exports_external.ZodIssueCode.custom,
|
|
743
|
+
path: [],
|
|
744
|
+
message: `receipt exceeds the ${MAX_PR_REVIEW_RESULT_RECEIPT_BYTES}-byte bound`
|
|
745
|
+
});
|
|
746
|
+
}
|
|
747
|
+
});
|
|
748
|
+
var PR_REVIEW_FINDINGS_MAX_BYTES = 10 * 1024 * 1024;
|
|
749
|
+
var PR_REVIEW_FINDINGS_WRITE_MAX_BYTES = 3 * 1024 * 1024;
|
|
750
|
+
var PR_REVIEW_HANDOFF_MAX_BYTES = 128 * 1024;
|
|
751
|
+
var PR_REVIEW_HANDOFF_WRITE_MAX_BYTES = 120 * 1024;
|
|
752
|
+
var PR_REVIEW_DISCARDED_EXAMPLE_ITEM_ID = "discarded-id";
|
|
753
|
+
function serializedPrReviewArtifactInputBytes(value) {
|
|
754
|
+
return new TextEncoder().encode(JSON.stringify(value)).byteLength;
|
|
755
|
+
}
|
|
756
|
+
var PrReviewRunIdSchema = exports_external.string().regex(/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/, "run_id must be a safe relative identifier");
|
|
757
|
+
var PrReviewFindingSchema = exports_external.object({
|
|
758
|
+
finding_id: exports_external.string().trim().min(1).max(128),
|
|
759
|
+
status: exports_external.enum(PR_REVIEW_FINDING_STATUSES),
|
|
760
|
+
file_line: exports_external.string().trim().min(1).max(1000),
|
|
761
|
+
evidence: exports_external.string().trim().min(1).max(20000),
|
|
762
|
+
next_action: exports_external.enum(PR_REVIEW_FINDING_ACTIONS),
|
|
763
|
+
severity: exports_external.enum(PR_REVIEW_SEVERITIES).optional(),
|
|
764
|
+
category: exports_external.string().trim().min(1).max(128).optional(),
|
|
765
|
+
risk_impact: exports_external.enum(PR_REVIEW_RISK_IMPACTS).optional(),
|
|
766
|
+
risk_tags: exports_external.array(exports_external.enum(PR_REVIEW_RISK_TAGS)).max(PR_REVIEW_RISK_TAGS.length).optional()
|
|
767
|
+
}).strict().superRefine((value, ctx) => {
|
|
768
|
+
if (value.status !== "CONFIRMED")
|
|
769
|
+
return;
|
|
770
|
+
if (value.risk_impact === undefined) {
|
|
771
|
+
ctx.addIssue({
|
|
772
|
+
code: "custom",
|
|
773
|
+
path: ["risk_impact"],
|
|
774
|
+
message: "is required on every newly written CONFIRMED finding (issue #2383 typed critic routing)"
|
|
775
|
+
});
|
|
776
|
+
}
|
|
777
|
+
if (value.risk_tags === undefined) {
|
|
778
|
+
ctx.addIssue({
|
|
779
|
+
code: "custom",
|
|
780
|
+
path: ["risk_tags"],
|
|
781
|
+
message: "is required on every newly written CONFIRMED finding (issue #2383 typed critic routing)"
|
|
782
|
+
});
|
|
783
|
+
}
|
|
784
|
+
});
|
|
785
|
+
function prReviewFindingRequiresCritic(input) {
|
|
786
|
+
if (input.classification !== "CONFIRMED")
|
|
787
|
+
return false;
|
|
788
|
+
const impact = input.risk_impact ?? "UNKNOWN";
|
|
789
|
+
const tags = input.risk_tags ?? [];
|
|
790
|
+
if (impact === "UNKNOWN")
|
|
791
|
+
return true;
|
|
792
|
+
if (input.severity === undefined)
|
|
793
|
+
return true;
|
|
794
|
+
if (input.severity === "CRITICAL" || input.severity === "HIGH")
|
|
795
|
+
return true;
|
|
796
|
+
if (input.severity === "MEDIUM") {
|
|
797
|
+
return impact === "HIGH_IMPACT" || tags.length > 0;
|
|
798
|
+
}
|
|
799
|
+
return false;
|
|
800
|
+
}
|
|
801
|
+
var PrReviewHandoffSchema = exports_external.object({
|
|
802
|
+
pr_url: exports_external.string().url().max(2000),
|
|
803
|
+
finding_ids: exports_external.array(exports_external.string().trim().min(1).max(128)).min(1).max(1000),
|
|
804
|
+
summary: exports_external.string().trim().min(1).max(20000),
|
|
805
|
+
provenance: exports_external.array(exports_external.string().trim().min(1).max(4000)).min(1).max(1000)
|
|
806
|
+
}).strict();
|
|
807
|
+
var PrReviewPartialBaseCoverageSchema = exports_external.object({
|
|
808
|
+
unresolved_dimensions: exports_external.array(exports_external.enum(PR_REVIEW_BASE_DIMENSION_IDS)).min(1).max(PR_REVIEW_BASE_DIMENSION_IDS.length)
|
|
809
|
+
}).strict().superRefine((value, ctx) => {
|
|
810
|
+
const seen = new Set;
|
|
811
|
+
for (const dimension of value.unresolved_dimensions) {
|
|
812
|
+
if (seen.has(dimension)) {
|
|
813
|
+
ctx.addIssue({
|
|
814
|
+
code: "custom",
|
|
815
|
+
path: ["unresolved_dimensions"],
|
|
816
|
+
message: `must not contain duplicate dimension "${dimension}"`
|
|
817
|
+
});
|
|
818
|
+
return;
|
|
819
|
+
}
|
|
820
|
+
seen.add(dimension);
|
|
821
|
+
}
|
|
822
|
+
});
|
|
823
|
+
var WritePrReviewArtifactArgsSchema = exports_external.discriminatedUnion("kind", [
|
|
824
|
+
exports_external.object({
|
|
825
|
+
kind: exports_external.literal("findings"),
|
|
826
|
+
run_id: PrReviewRunIdSchema.optional(),
|
|
827
|
+
pr_head_sha: exports_external.string().trim().regex(/^[0-9a-f]{6,64}$/i),
|
|
828
|
+
boundary: exports_external.enum(PR_REVIEW_ARTIFACT_BOUNDARIES),
|
|
829
|
+
records: exports_external.array(PrReviewFindingSchema).min(1).max(1000),
|
|
830
|
+
partial_base_coverage: PrReviewPartialBaseCoverageSchema.optional()
|
|
831
|
+
}).strict(),
|
|
832
|
+
exports_external.object({
|
|
833
|
+
kind: exports_external.literal("handoff"),
|
|
834
|
+
run_id: PrReviewRunIdSchema.optional(),
|
|
835
|
+
pr_head_sha: exports_external.string().trim().regex(/^[0-9a-f]{6,64}$/i),
|
|
836
|
+
handoff: PrReviewHandoffSchema
|
|
837
|
+
}).strict()
|
|
838
|
+
]).superRefine((value, ctx) => {
|
|
839
|
+
if (value.kind === "findings" && value.partial_base_coverage !== undefined && value.boundary !== "post_explorer") {
|
|
840
|
+
ctx.addIssue({
|
|
841
|
+
code: "custom",
|
|
842
|
+
path: ["partial_base_coverage"],
|
|
843
|
+
message: "is valid only for the post_explorer boundary"
|
|
844
|
+
});
|
|
845
|
+
}
|
|
846
|
+
const bytes = serializedPrReviewArtifactInputBytes(value);
|
|
847
|
+
const maxBytes = value.kind === "findings" ? PR_REVIEW_FINDINGS_WRITE_MAX_BYTES : PR_REVIEW_HANDOFF_WRITE_MAX_BYTES;
|
|
848
|
+
if (bytes > maxBytes) {
|
|
849
|
+
ctx.addIssue({
|
|
850
|
+
code: "custom",
|
|
851
|
+
path: [value.kind === "findings" ? "records" : "handoff"],
|
|
852
|
+
message: `serialized UTF-8 payload must be at most ${maxBytes} bytes (got ${bytes})`
|
|
853
|
+
});
|
|
854
|
+
}
|
|
855
|
+
});
|
|
856
|
+
var introducedByPrSchema = exports_external.string().regex(/^(?:introduced_by_pr\s*:\s*)?(?:YES|NO|UNKNOWN)$/i);
|
|
857
|
+
var PrReviewRiskTagsFieldPattern = new RegExp(`^(?:(?:${PR_REVIEW_RISK_TAGS.join("|")})(?:,(?:${PR_REVIEW_RISK_TAGS.join("|")}))*)?$`);
|
|
858
|
+
var PrReviewRiskTagsFieldSchema = exports_external.string().regex(PrReviewRiskTagsFieldPattern, `must be a comma-separated subset of the canonical risk tags (${PR_REVIEW_RISK_TAGS.join(", ")}), or empty`);
|
|
859
|
+
var PR_REVIEW_REVIEWER_LEGACY_FIELD_COUNT = 10;
|
|
860
|
+
function parsePrReviewRiskTagsField(field) {
|
|
861
|
+
const trimmed = field.trim();
|
|
862
|
+
if (!trimmed)
|
|
863
|
+
return [];
|
|
864
|
+
return trimmed.split(",").map((tag) => tag.trim());
|
|
865
|
+
}
|
|
866
|
+
var PrReviewReviewerVerdictFieldsSchema = exports_external.tuple([
|
|
867
|
+
exports_external.literal("[REVIEWED]"),
|
|
868
|
+
exports_external.string().min(1),
|
|
869
|
+
exports_external.enum(PR_REVIEW_REVIEWER_CLASSIFICATIONS),
|
|
870
|
+
exports_external.enum(PR_REVIEW_REVIEWER_EVIDENCE_TYPES),
|
|
871
|
+
exports_external.enum(PR_REVIEW_SEVERITIES),
|
|
872
|
+
introducedByPrSchema,
|
|
873
|
+
exports_external.string().min(1),
|
|
874
|
+
exports_external.string().min(8),
|
|
875
|
+
exports_external.string().min(5),
|
|
876
|
+
exports_external.string().min(3),
|
|
877
|
+
exports_external.enum(PR_REVIEW_RISK_IMPACTS),
|
|
878
|
+
PrReviewRiskTagsFieldSchema
|
|
879
|
+
]).superRefine((fields, ctx) => {
|
|
880
|
+
if (fields[2] === "DISPROVED" && fields[4] !== "NONE") {
|
|
881
|
+
ctx.addIssue({
|
|
882
|
+
code: "custom",
|
|
883
|
+
path: [4],
|
|
884
|
+
message: "DISPROVED reviewer severity must be NONE"
|
|
885
|
+
});
|
|
886
|
+
}
|
|
887
|
+
});
|
|
888
|
+
var PrReviewCriticVerdictFieldsSchema = exports_external.tuple([
|
|
889
|
+
exports_external.literal("[CRITIC]"),
|
|
890
|
+
exports_external.string().min(1),
|
|
891
|
+
exports_external.enum(PR_REVIEW_CRITIC_STATUSES),
|
|
892
|
+
exports_external.enum(PR_REVIEW_SEVERITIES),
|
|
893
|
+
exports_external.string().min(6),
|
|
894
|
+
exports_external.string().min(6)
|
|
895
|
+
]).superRefine((fields, ctx) => {
|
|
896
|
+
const status = fields[2];
|
|
897
|
+
const severity = fields[3];
|
|
898
|
+
if (status === "NEEDS_MORE_EVIDENCE") {
|
|
899
|
+
ctx.addIssue({
|
|
900
|
+
code: "custom",
|
|
901
|
+
path: [2],
|
|
902
|
+
message: "NEEDS_MORE_EVIDENCE is not a terminal transport verdict"
|
|
903
|
+
});
|
|
904
|
+
}
|
|
905
|
+
if (status === "DISPROVED" && severity !== "NONE") {
|
|
906
|
+
ctx.addIssue({
|
|
907
|
+
code: "custom",
|
|
908
|
+
path: [3],
|
|
909
|
+
message: "DISPROVED critic severity must be NONE"
|
|
910
|
+
});
|
|
911
|
+
}
|
|
912
|
+
if (status === "UPHELD" && !["CRITICAL", "HIGH", "MEDIUM"].includes(severity)) {
|
|
913
|
+
ctx.addIssue({
|
|
914
|
+
code: "custom",
|
|
915
|
+
path: [3],
|
|
916
|
+
message: "UPHELD critic severity must be CRITICAL, HIGH, or MEDIUM"
|
|
917
|
+
});
|
|
918
|
+
}
|
|
919
|
+
if (status === "DOWNGRADED" && severity === "CRITICAL") {
|
|
920
|
+
ctx.addIssue({
|
|
921
|
+
code: "custom",
|
|
922
|
+
path: [3],
|
|
923
|
+
message: "DOWNGRADED critic severity cannot be CRITICAL"
|
|
924
|
+
});
|
|
925
|
+
}
|
|
926
|
+
});
|
|
927
|
+
var PR_REVIEW_VERDICT_ROW_DESCRIPTORS = {
|
|
928
|
+
reviewer: {
|
|
929
|
+
marker: "[REVIEWED]",
|
|
930
|
+
fieldCount: 12,
|
|
931
|
+
fieldRoles: [
|
|
932
|
+
"marker",
|
|
933
|
+
"item_id",
|
|
934
|
+
"classification",
|
|
935
|
+
"evidence_type",
|
|
936
|
+
"severity",
|
|
937
|
+
"introduced_by_pr",
|
|
938
|
+
"file:line",
|
|
939
|
+
"rationale",
|
|
940
|
+
"probe",
|
|
941
|
+
"reviewer_notes",
|
|
942
|
+
"risk_impact",
|
|
943
|
+
"risk_tags"
|
|
944
|
+
],
|
|
945
|
+
schema: PrReviewReviewerVerdictFieldsSchema
|
|
946
|
+
},
|
|
947
|
+
critic: {
|
|
948
|
+
marker: "[CRITIC]",
|
|
949
|
+
fieldCount: 6,
|
|
950
|
+
fieldRoles: [
|
|
951
|
+
"marker",
|
|
952
|
+
"item_id",
|
|
953
|
+
"status",
|
|
954
|
+
"severity",
|
|
955
|
+
"rationale",
|
|
956
|
+
"required_change"
|
|
957
|
+
],
|
|
958
|
+
schema: PrReviewCriticVerdictFieldsSchema
|
|
959
|
+
}
|
|
960
|
+
};
|
|
961
|
+
function parsePrReviewVerdictRow(line, kind) {
|
|
962
|
+
const descriptor = PR_REVIEW_VERDICT_ROW_DESCRIPTORS[kind];
|
|
963
|
+
const fields = [];
|
|
964
|
+
let current = "";
|
|
965
|
+
let usedCanonicalEscape = false;
|
|
966
|
+
for (let index = 0;index < line.length; index++) {
|
|
967
|
+
const char = line[index];
|
|
968
|
+
if (char === "\\") {
|
|
969
|
+
const next = line[index + 1];
|
|
970
|
+
if (next === "\\") {
|
|
971
|
+
current += "\\";
|
|
972
|
+
usedCanonicalEscape = true;
|
|
973
|
+
index++;
|
|
974
|
+
continue;
|
|
975
|
+
}
|
|
976
|
+
if (next === "|") {
|
|
977
|
+
current += "|";
|
|
978
|
+
usedCanonicalEscape = true;
|
|
979
|
+
index++;
|
|
980
|
+
continue;
|
|
981
|
+
}
|
|
982
|
+
if (next === "n") {
|
|
983
|
+
current += `
|
|
984
|
+
`;
|
|
985
|
+
usedCanonicalEscape = true;
|
|
986
|
+
index++;
|
|
987
|
+
continue;
|
|
988
|
+
}
|
|
989
|
+
if (next === "r") {
|
|
990
|
+
current += "\r";
|
|
991
|
+
usedCanonicalEscape = true;
|
|
992
|
+
index++;
|
|
993
|
+
continue;
|
|
994
|
+
}
|
|
995
|
+
current += "\\";
|
|
996
|
+
continue;
|
|
997
|
+
}
|
|
998
|
+
if (char === "|") {
|
|
999
|
+
fields.push(current.trim());
|
|
1000
|
+
current = "";
|
|
1001
|
+
continue;
|
|
1002
|
+
}
|
|
1003
|
+
current += char;
|
|
1004
|
+
}
|
|
1005
|
+
fields.push(current.trim());
|
|
1006
|
+
if (fields[0] !== descriptor.marker)
|
|
1007
|
+
return null;
|
|
1008
|
+
if (kind === "reviewer" && fields.length === PR_REVIEW_REVIEWER_LEGACY_FIELD_COUNT) {
|
|
1009
|
+
fields.push("UNKNOWN", "");
|
|
1010
|
+
}
|
|
1011
|
+
if (fields.length > descriptor.fieldCount) {
|
|
1012
|
+
const retained = fields.slice(0, descriptor.fieldCount - 1);
|
|
1013
|
+
retained.push(fields.slice(descriptor.fieldCount - 1).join("|"));
|
|
1014
|
+
return {
|
|
1015
|
+
marker: descriptor.marker,
|
|
1016
|
+
fields: retained,
|
|
1017
|
+
recoveredOverflow: true,
|
|
1018
|
+
overflowClass: fields.length === descriptor.fieldCount + 1 && fields[fields.length - 1] === "" ? "legacy-fidelity-safe" : "legacy-lossy"
|
|
1019
|
+
};
|
|
1020
|
+
}
|
|
1021
|
+
return {
|
|
1022
|
+
marker: descriptor.marker,
|
|
1023
|
+
fields,
|
|
1024
|
+
recoveredOverflow: false,
|
|
1025
|
+
overflowClass: fields.length === descriptor.fieldCount ? usedCanonicalEscape ? "canonical" : "legacy-fidelity-safe" : "legacy-lossy"
|
|
1026
|
+
};
|
|
1027
|
+
}
|
|
395
1028
|
// src/background/pending-delegations.ts
|
|
396
1029
|
var BACKGROUND_DELEGATIONS_FILE = "background-delegations.jsonl";
|
|
397
1030
|
var BACKGROUND_DELEGATION_FALLBACK_DIR = "background-delegation-fallback";
|
|
@@ -405,6 +1038,8 @@ var MAX_BACKGROUND_ADVISORY_CHARS = 4000;
|
|
|
405
1038
|
var LEGACY_CODER_SETTLEMENT_PENDING_ADVISORY_MARKER = "legacy coder settlement transfer is pending";
|
|
406
1039
|
var MAX_BACKGROUND_DELEGATION_GENERATION = 1e6;
|
|
407
1040
|
var MAX_RECOVERY_FALLBACK_BYTES = 1024 * 1024;
|
|
1041
|
+
var MAX_TRACKED_LENIENT_LEDGER_SIGNALS = 32;
|
|
1042
|
+
var LENIENT_LEDGER_SIGNAL_SOURCE = "lenient-read";
|
|
408
1043
|
var DELEGATION_COMPACTION_LOW_WATER_BYTES = 256 * 1024;
|
|
409
1044
|
var DELEGATION_COMPACTION_HIGH_WATER_BYTES = 1024 * 1024;
|
|
410
1045
|
var MAX_CHECKPOINT_BYTES = 2 * 1024 * 1024;
|
|
@@ -457,6 +1092,7 @@ var ResultSchema = exports_external.object({
|
|
|
457
1092
|
outputArtifactError: exports_external.string().optional(),
|
|
458
1093
|
transcriptIncomplete: exports_external.boolean().optional(),
|
|
459
1094
|
messageCount: exports_external.number().optional(),
|
|
1095
|
+
prReviewResultReceipt: PrReviewResultReceiptSchema.optional(),
|
|
460
1096
|
workflowLaneFailureClass: exports_external.enum(["contract", "resource", "deadline"]).optional(),
|
|
461
1097
|
terminalErrorClass: exports_external.object({
|
|
462
1098
|
kind: exports_external.enum(["provider", "aborted", "output_length", "unknown"]),
|
|
@@ -652,7 +1288,12 @@ var PromptSchema = exports_external.object({
|
|
|
652
1288
|
digest: exports_external.string()
|
|
653
1289
|
}).strict();
|
|
654
1290
|
var RecordSchema = exports_external.object({
|
|
655
|
-
schemaVersion: exports_external.union([
|
|
1291
|
+
schemaVersion: exports_external.union([
|
|
1292
|
+
exports_external.literal(1),
|
|
1293
|
+
exports_external.literal(2),
|
|
1294
|
+
exports_external.literal(3),
|
|
1295
|
+
exports_external.literal(4)
|
|
1296
|
+
]),
|
|
656
1297
|
correlationId: exports_external.string().min(1),
|
|
657
1298
|
jobId: exports_external.string().nullable(),
|
|
658
1299
|
subagentSessionId: exports_external.string().min(1),
|
|
@@ -679,6 +1320,7 @@ var RecordSchema = exports_external.object({
|
|
|
679
1320
|
mode: exports_external.string().optional(),
|
|
680
1321
|
workflowLane: exports_external.string().optional(),
|
|
681
1322
|
ownedWorkflowLanes: exports_external.array(exports_external.string().min(1).max(120)).min(1).max(11).optional(),
|
|
1323
|
+
prReviewLegacyTranscriptCompatibility: exports_external.boolean().optional(),
|
|
682
1324
|
promptHash: exports_external.string().optional(),
|
|
683
1325
|
workspace: WorkspaceSchema.optional(),
|
|
684
1326
|
taskChangeContext: TaskChangeContextSchema.optional(),
|
|
@@ -861,7 +1503,7 @@ function readDelegationCheckpoint(directory) {
|
|
|
861
1503
|
return { kind: "ok", checkpoint: parsed.data, bytes };
|
|
862
1504
|
}
|
|
863
1505
|
function sha256Hex(data) {
|
|
864
|
-
return
|
|
1506
|
+
return createHash3("sha256").update(data).digest("hex");
|
|
865
1507
|
}
|
|
866
1508
|
function checkpointPayloadChecksum(checkpoint) {
|
|
867
1509
|
return sha256Hex(JSON.stringify([
|
|
@@ -879,6 +1521,8 @@ function checkpointPayloadChecksum(checkpoint) {
|
|
|
879
1521
|
}
|
|
880
1522
|
var CHECKPOINT_REBIND_HINT = "remove .swarm/background-delegations.manifest.json (manifest only) after verifying no in-flight background delegations; recovery then falls back to the full-ledger read. Only if you also want to discard pre-cut closed summaries and audit history \u2014 which for a compacted (rolled) ledger exist ONLY in .swarm/background-delegations.checkpoint.json \u2014 remove the checkpoint too or use the full reset below";
|
|
881
1523
|
var CHECKPOINT_RESET_HINT = "the rolled tail no longer carries pre-checkpoint state: stop swarm processes, verify no in-flight background delegations, and remove .swarm/background-delegations.manifest.json, .swarm/background-delegations.checkpoint.json, and .swarm/background-delegations.jsonl to reset the store (or restore them from backup)";
|
|
1524
|
+
var lenientLedgerSignalByRoot = new Map;
|
|
1525
|
+
var lenientLedgerSignalOrder = [];
|
|
882
1526
|
function loadFoldedState(directory, options) {
|
|
883
1527
|
const manifestRead = readDelegationManifest(directory);
|
|
884
1528
|
if (manifestRead.kind === "invalid") {
|
|
@@ -968,9 +1612,13 @@ function loadFoldedState(directory, options) {
|
|
|
968
1612
|
for (const summary of checkpoint.closed) {
|
|
969
1613
|
records.set(summary.correlationId, summary);
|
|
970
1614
|
}
|
|
971
|
-
const
|
|
1615
|
+
const lenientSkips = emptyLenientLedgerSkipCounts();
|
|
1616
|
+
const foldError = foldLedgerTail(records, tail, options.strict, checkpoint, lenientSkips);
|
|
972
1617
|
if (foldError)
|
|
973
1618
|
return { status: "uncertain", reason: foldError };
|
|
1619
|
+
if (!options.strict) {
|
|
1620
|
+
recordLenientLedgerSkips(directory, mode, lenientSkips);
|
|
1621
|
+
}
|
|
974
1622
|
return {
|
|
975
1623
|
status: "ok",
|
|
976
1624
|
mode,
|
|
@@ -1005,7 +1653,7 @@ function readBoundedRecentLedgerWindow(directory, size) {
|
|
|
1005
1653
|
const firstNewline = window.indexOf(10);
|
|
1006
1654
|
return firstNewline === -1 ? Buffer.alloc(0) : window.subarray(firstNewline + 1);
|
|
1007
1655
|
}
|
|
1008
|
-
function foldLedgerTail(records, tail, strict, checkpoint) {
|
|
1656
|
+
function foldLedgerTail(records, tail, strict, checkpoint, lenientSkips) {
|
|
1009
1657
|
let lineNumber = 0;
|
|
1010
1658
|
for (const line of tail.toString("utf-8").split(`
|
|
1011
1659
|
`)) {
|
|
@@ -1020,6 +1668,8 @@ function foldLedgerTail(records, tail, strict, checkpoint) {
|
|
|
1020
1668
|
if (strict) {
|
|
1021
1669
|
return `background delegation ledger has malformed JSON at line ${lineNumber}`;
|
|
1022
1670
|
}
|
|
1671
|
+
if (lenientSkips)
|
|
1672
|
+
lenientSkips.malformedJson += 1;
|
|
1023
1673
|
continue;
|
|
1024
1674
|
}
|
|
1025
1675
|
const parsed = RecordSchema.safeParse(parsedJson);
|
|
@@ -1027,6 +1677,8 @@ function foldLedgerTail(records, tail, strict, checkpoint) {
|
|
|
1027
1677
|
if (strict) {
|
|
1028
1678
|
return `background delegation ledger has an invalid record at line ${lineNumber}`;
|
|
1029
1679
|
}
|
|
1680
|
+
if (lenientSkips)
|
|
1681
|
+
lenientSkips.invalidRecord += 1;
|
|
1030
1682
|
continue;
|
|
1031
1683
|
}
|
|
1032
1684
|
const existing = checkpoint ? records.get(parsed.data.correlationId) : undefined;
|
|
@@ -1055,7 +1707,9 @@ function loadLegacyLedger(directory, strict) {
|
|
|
1055
1707
|
};
|
|
1056
1708
|
}
|
|
1057
1709
|
const records2 = new Map;
|
|
1058
|
-
const
|
|
1710
|
+
const lenientSkips = emptyLenientLedgerSkipCounts();
|
|
1711
|
+
const foldError2 = foldLedgerTail(records2, Buffer.from(raw2, "utf-8"), false, undefined, lenientSkips);
|
|
1712
|
+
recordLenientLedgerSkips(directory, "legacy-ledger", lenientSkips);
|
|
1059
1713
|
return {
|
|
1060
1714
|
status: "ok",
|
|
1061
1715
|
mode: "legacy",
|
|
@@ -1145,6 +1799,48 @@ function recordLedgerUncertainty(directory, reason, source, repairHint) {
|
|
|
1145
1799
|
});
|
|
1146
1800
|
} catch {}
|
|
1147
1801
|
}
|
|
1802
|
+
function emptyLenientLedgerSkipCounts() {
|
|
1803
|
+
return { malformedJson: 0, invalidRecord: 0 };
|
|
1804
|
+
}
|
|
1805
|
+
function shouldEmitLenientLedgerSignal(directory, signature) {
|
|
1806
|
+
const key = canonicalRootKeyFresh(directory);
|
|
1807
|
+
const existing = lenientLedgerSignalByRoot.get(key);
|
|
1808
|
+
if (existing === signature)
|
|
1809
|
+
return false;
|
|
1810
|
+
if (!existing) {
|
|
1811
|
+
if (lenientLedgerSignalOrder.length >= MAX_TRACKED_LENIENT_LEDGER_SIGNALS) {
|
|
1812
|
+
const evicted = lenientLedgerSignalOrder.shift();
|
|
1813
|
+
if (evicted)
|
|
1814
|
+
lenientLedgerSignalByRoot.delete(evicted);
|
|
1815
|
+
}
|
|
1816
|
+
lenientLedgerSignalOrder.push(key);
|
|
1817
|
+
}
|
|
1818
|
+
lenientLedgerSignalByRoot.set(key, signature);
|
|
1819
|
+
return true;
|
|
1820
|
+
}
|
|
1821
|
+
function recordLenientLedgerSkips(directory, source, counts) {
|
|
1822
|
+
const skipped = counts.malformedJson + counts.invalidRecord;
|
|
1823
|
+
if (skipped <= 0)
|
|
1824
|
+
return;
|
|
1825
|
+
const reason = `background delegation ledger skipped ${skipped} malformed/invalid row${skipped === 1 ? "" : "s"} ` + `during lenient ${source} read (${counts.malformedJson} malformed JSON, ${counts.invalidRecord} invalid records)`;
|
|
1826
|
+
const signature = `${source}:${counts.malformedJson}:${counts.invalidRecord}`;
|
|
1827
|
+
if (shouldEmitLenientLedgerSignal(directory, signature)) {
|
|
1828
|
+
criticalWarn(`[background] ${reason}`);
|
|
1829
|
+
}
|
|
1830
|
+
try {
|
|
1831
|
+
const current = readDelegationHealthArtifact(directory);
|
|
1832
|
+
if (current?.lastUncertainty && current.lastUncertainty.source !== LENIENT_LEDGER_SIGNAL_SOURCE) {
|
|
1833
|
+
return;
|
|
1834
|
+
}
|
|
1835
|
+
writeDelegationHealthArtifact(directory, {
|
|
1836
|
+
lastUncertainty: {
|
|
1837
|
+
reason,
|
|
1838
|
+
at: Date.now(),
|
|
1839
|
+
source: LENIENT_LEDGER_SIGNAL_SOURCE
|
|
1840
|
+
}
|
|
1841
|
+
});
|
|
1842
|
+
} catch {}
|
|
1843
|
+
}
|
|
1148
1844
|
function isUnsettledWorktreeOwner(record) {
|
|
1149
1845
|
return Boolean(record.worktree) && !(record.coderSettlement?.state === "settled" && record.coderSettlement.outcome?.kind === "standard-worktree" && (record.coderSettlement.outcome.result === "merged" || record.coderSettlement.outcome.result === "unchanged"));
|
|
1150
1846
|
}
|
|
@@ -1175,7 +1871,7 @@ function buildClosedSummary(record) {
|
|
|
1175
1871
|
if (summary.terminalResult) {
|
|
1176
1872
|
summary.terminalResult = {
|
|
1177
1873
|
...summary.terminalResult,
|
|
1178
|
-
result:
|
|
1874
|
+
result: dropTerminalResultBody(summary.terminalResult.result)
|
|
1179
1875
|
};
|
|
1180
1876
|
}
|
|
1181
1877
|
const parsed = RecordSchema.safeParse(summary);
|
|
@@ -1197,6 +1893,10 @@ function dropResultBody(result) {
|
|
|
1197
1893
|
} = result;
|
|
1198
1894
|
return rest;
|
|
1199
1895
|
}
|
|
1896
|
+
function dropTerminalResultBody(result) {
|
|
1897
|
+
const { prReviewResultReceipt: _receipt, ...rest } = dropResultBody(result);
|
|
1898
|
+
return rest;
|
|
1899
|
+
}
|
|
1200
1900
|
function dropRetainedPrReviewReceipt(record) {
|
|
1201
1901
|
const compact = (result) => {
|
|
1202
1902
|
const payload = parsePrReviewCollectionReceiptFooter(record, result);
|
|
@@ -1222,7 +1922,7 @@ function dropRetainedPrReviewReceipt(record) {
|
|
|
1222
1922
|
...record.terminalResult ? {
|
|
1223
1923
|
terminalResult: {
|
|
1224
1924
|
...record.terminalResult,
|
|
1225
|
-
result:
|
|
1925
|
+
result: dropTerminalResultBody(record.terminalResult.result)
|
|
1226
1926
|
}
|
|
1227
1927
|
} : {}
|
|
1228
1928
|
};
|
|
@@ -1587,6 +2287,9 @@ function buildPendingRecord(input, now) {
|
|
|
1587
2287
|
...input.mode ? { mode: input.mode } : {},
|
|
1588
2288
|
...input.workflowLane ? { workflowLane: input.workflowLane } : {},
|
|
1589
2289
|
...input.ownedWorkflowLanes?.length ? { ownedWorkflowLanes: [...input.ownedWorkflowLanes] } : {},
|
|
2290
|
+
...input.prReviewLegacyTranscriptCompatibility !== undefined ? {
|
|
2291
|
+
prReviewLegacyTranscriptCompatibility: input.prReviewLegacyTranscriptCompatibility
|
|
2292
|
+
} : {},
|
|
1590
2293
|
...input.promptHash ? { promptHash: input.promptHash } : {},
|
|
1591
2294
|
...input.workspace ? { workspace: input.workspace } : {},
|
|
1592
2295
|
...input.taskChangeContext ? { taskChangeContext: input.taskChangeContext } : {},
|
|
@@ -1679,7 +2382,7 @@ function buildPromptSnapshot(text, maxChars) {
|
|
|
1679
2382
|
text: bounded,
|
|
1680
2383
|
chars: text.length,
|
|
1681
2384
|
truncated,
|
|
1682
|
-
digest:
|
|
2385
|
+
digest: createHash3("sha256").update(text).digest("hex")
|
|
1683
2386
|
};
|
|
1684
2387
|
}
|
|
1685
2388
|
async function appendDelegationTransition(directory, correlationId, transition) {
|
|
@@ -1703,7 +2406,7 @@ async function appendDelegationTransition(directory, correlationId, transition)
|
|
|
1703
2406
|
}
|
|
1704
2407
|
next = {
|
|
1705
2408
|
...current,
|
|
1706
|
-
schemaVersion: current.schemaVersion === 1 ? 2 : current.schemaVersion,
|
|
2409
|
+
schemaVersion: transition.result?.prReviewResultReceipt ? 4 : current.schemaVersion === 1 ? 2 : current.schemaVersion,
|
|
1707
2410
|
status: transition.status,
|
|
1708
2411
|
updatedAt: now,
|
|
1709
2412
|
...transition.completedAt !== undefined ? { completedAt: transition.completedAt } : transition.status === "completed" || transition.status === "error" ? { completedAt: now } : {},
|
|
@@ -1718,6 +2421,87 @@ async function appendDelegationTransition(directory, correlationId, transition)
|
|
|
1718
2421
|
return null;
|
|
1719
2422
|
}
|
|
1720
2423
|
}
|
|
2424
|
+
async function publishPrReviewResultReceipt(directory, input) {
|
|
2425
|
+
const parsed = PrReviewResultReceiptSchema.safeParse(input.receipt);
|
|
2426
|
+
if (!parsed.success) {
|
|
2427
|
+
return { status: "conflict", reason: "receipt schema validation failed" };
|
|
2428
|
+
}
|
|
2429
|
+
let outcome = {
|
|
2430
|
+
status: "uncertain",
|
|
2431
|
+
reason: "receipt publication did not complete"
|
|
2432
|
+
};
|
|
2433
|
+
try {
|
|
2434
|
+
await withEvidenceLock(directory, BACKGROUND_DELEGATIONS_FILE, STORE_LOCK_AGENT, STORE_LOCK_TASK, async () => {
|
|
2435
|
+
const records = loadRecordsForWrite(directory);
|
|
2436
|
+
if (records === null) {
|
|
2437
|
+
outcome = {
|
|
2438
|
+
status: "uncertain",
|
|
2439
|
+
reason: "delegation state is uncertain"
|
|
2440
|
+
};
|
|
2441
|
+
return;
|
|
2442
|
+
}
|
|
2443
|
+
const target = findReceiptPublicationTarget(records, input);
|
|
2444
|
+
if (target.count !== 1 || !target.record) {
|
|
2445
|
+
outcome = {
|
|
2446
|
+
status: "not_found",
|
|
2447
|
+
reason: `expected one exact delegation record, found ${target.count}`
|
|
2448
|
+
};
|
|
2449
|
+
return;
|
|
2450
|
+
}
|
|
2451
|
+
const current = target.record;
|
|
2452
|
+
if (current.result?.prReviewResultReceipt) {
|
|
2453
|
+
const existing = current.result.prReviewResultReceipt;
|
|
2454
|
+
if (samePrReviewReceiptSemantics(existing, parsed.data)) {
|
|
2455
|
+
outcome = { status: "duplicate", record: current };
|
|
2456
|
+
} else {
|
|
2457
|
+
outcome = {
|
|
2458
|
+
status: "conflict",
|
|
2459
|
+
reason: "a different bound receipt is already recorded"
|
|
2460
|
+
};
|
|
2461
|
+
}
|
|
2462
|
+
return;
|
|
2463
|
+
}
|
|
2464
|
+
if (current.status !== "pending" && current.status !== "running") {
|
|
2465
|
+
outcome = {
|
|
2466
|
+
status: "terminal",
|
|
2467
|
+
reason: `delegation is already ${current.status}`
|
|
2468
|
+
};
|
|
2469
|
+
return;
|
|
2470
|
+
}
|
|
2471
|
+
const owned = current.ownedWorkflowLanes?.length ? current.ownedWorkflowLanes : current.workflowLane ? [current.workflowLane] : [];
|
|
2472
|
+
const sameOwned = owned.length === parsed.data.ownedWorkflowLanes.length && owned.every((lane) => parsed.data.ownedWorkflowLanes.includes(lane));
|
|
2473
|
+
if (parsed.data.workflowInstanceId !== input.expectedWorkflowInstanceId || parsed.data.workflowRevision !== input.expectedWorkflowRevision || parsed.data.baseSha !== input.expectedBaseSha || current.mode !== parsed.data.mode || current.workflowLane !== parsed.data.workflowLane || !sameOwned || current.workspace?.prHeadSha !== parsed.data.headSha || current.workspace?.gitHead !== parsed.data.headSha || (current.generation ?? 1) !== parsed.data.generation) {
|
|
2474
|
+
outcome = {
|
|
2475
|
+
status: "conflict",
|
|
2476
|
+
reason: "receipt does not match immutable delegation identity"
|
|
2477
|
+
};
|
|
2478
|
+
return;
|
|
2479
|
+
}
|
|
2480
|
+
const next = {
|
|
2481
|
+
...current,
|
|
2482
|
+
schemaVersion: 4,
|
|
2483
|
+
updatedAt: Date.now(),
|
|
2484
|
+
result: {
|
|
2485
|
+
...current.result ?? {
|
|
2486
|
+
chars: 0,
|
|
2487
|
+
truncated: false,
|
|
2488
|
+
digest: createHash3("sha256").update("").digest("hex")
|
|
2489
|
+
},
|
|
2490
|
+
prReviewResultReceipt: parsed.data
|
|
2491
|
+
}
|
|
2492
|
+
};
|
|
2493
|
+
appendRecord(directory, next);
|
|
2494
|
+
maybeCompactDelegationsLocked(directory);
|
|
2495
|
+
outcome = { status: "recorded", record: next };
|
|
2496
|
+
});
|
|
2497
|
+
return outcome;
|
|
2498
|
+
} catch (error) {
|
|
2499
|
+
return {
|
|
2500
|
+
status: "uncertain",
|
|
2501
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
2502
|
+
};
|
|
2503
|
+
}
|
|
2504
|
+
}
|
|
1721
2505
|
function buildBackgroundCompletionEventId(input) {
|
|
1722
2506
|
const canonical = JSON.stringify([
|
|
1723
2507
|
input.correlationId,
|
|
@@ -1725,16 +2509,59 @@ function buildBackgroundCompletionEventId(input) {
|
|
|
1725
2509
|
input.status,
|
|
1726
2510
|
input.resultDigest
|
|
1727
2511
|
]);
|
|
1728
|
-
return `bgc1:${
|
|
2512
|
+
return `bgc1:${createHash3("sha256").update(canonical).digest("hex")}`;
|
|
1729
2513
|
}
|
|
1730
2514
|
function sameJson(left, right) {
|
|
1731
2515
|
return JSON.stringify(left) === JSON.stringify(right);
|
|
1732
2516
|
}
|
|
2517
|
+
function canonicalJson(value) {
|
|
2518
|
+
if (Array.isArray(value)) {
|
|
2519
|
+
return value.map(canonicalJson).sort((left, right) => {
|
|
2520
|
+
const leftJson = JSON.stringify(left);
|
|
2521
|
+
const rightJson = JSON.stringify(right);
|
|
2522
|
+
return leftJson < rightJson ? -1 : leftJson > rightJson ? 1 : 0;
|
|
2523
|
+
});
|
|
2524
|
+
}
|
|
2525
|
+
if (value && typeof value === "object") {
|
|
2526
|
+
return Object.fromEntries(Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, entry]) => [key, canonicalJson(entry)]));
|
|
2527
|
+
}
|
|
2528
|
+
return value;
|
|
2529
|
+
}
|
|
2530
|
+
function sameCanonicalJson(left, right) {
|
|
2531
|
+
return JSON.stringify(canonicalJson(left)) === JSON.stringify(canonicalJson(right));
|
|
2532
|
+
}
|
|
2533
|
+
function samePrReviewReceiptSemantics(left, right) {
|
|
2534
|
+
const { semanticEnvelopeDigest: _leftDigest, ...leftSemantic } = left;
|
|
2535
|
+
const { semanticEnvelopeDigest: _rightDigest, ...rightSemantic } = right;
|
|
2536
|
+
return sameCanonicalJson(leftSemantic, rightSemantic);
|
|
2537
|
+
}
|
|
1733
2538
|
function sameTerminalEvent(left, right) {
|
|
1734
2539
|
return left.eventId === right.eventId && left.status === right.status && sameRetainedResult(left.result, right.result);
|
|
1735
2540
|
}
|
|
1736
2541
|
function sameRetainedResult(left, right) {
|
|
1737
|
-
return left.chars === right.chars && left.truncated === right.truncated && left.digest === right.digest && left.outputRef === right.outputRef && left.outputPreviewChars === right.outputPreviewChars && left.outputDegraded === right.outputDegraded && left.outputArtifactError === right.outputArtifactError && left.transcriptIncomplete === right.transcriptIncomplete && left.messageCount === right.messageCount && left.workflowLaneFailureClass === right.workflowLaneFailureClass && sameJson(left.salvagedWorkflowLanes, right.salvagedWorkflowLanes) && sameJson(left.salvagedWorkflowLaneRecoveries, right.salvagedWorkflowLaneRecoveries);
|
|
2542
|
+
return left.chars === right.chars && left.truncated === right.truncated && left.digest === right.digest && left.outputRef === right.outputRef && left.outputPreviewChars === right.outputPreviewChars && left.outputDegraded === right.outputDegraded && left.outputArtifactError === right.outputArtifactError && left.transcriptIncomplete === right.transcriptIncomplete && left.messageCount === right.messageCount && sameJson(left.prReviewResultReceipt, right.prReviewResultReceipt) && left.workflowLaneFailureClass === right.workflowLaneFailureClass && sameJson(left.salvagedWorkflowLanes, right.salvagedWorkflowLanes) && sameJson(left.salvagedWorkflowLaneRecoveries, right.salvagedWorkflowLaneRecoveries);
|
|
2543
|
+
}
|
|
2544
|
+
function recordedPrReviewResultReceipt(record) {
|
|
2545
|
+
return record.result?.prReviewResultReceipt ?? record.terminalResult?.result.prReviewResultReceipt;
|
|
2546
|
+
}
|
|
2547
|
+
function mergeRecordedPrReviewResultReceipt(record, result) {
|
|
2548
|
+
const existing = recordedPrReviewResultReceipt(record);
|
|
2549
|
+
if (!existing || result.prReviewResultReceipt)
|
|
2550
|
+
return result;
|
|
2551
|
+
return { ...result, prReviewResultReceipt: existing };
|
|
2552
|
+
}
|
|
2553
|
+
function findReceiptPublicationTarget(records, input) {
|
|
2554
|
+
let count = 0;
|
|
2555
|
+
let record = null;
|
|
2556
|
+
for (const candidate of records) {
|
|
2557
|
+
if (candidate.parentSessionId !== input.parentSessionId || candidate.subagentSessionId !== input.childSessionId || candidate.batchId !== input.batchId || candidate.laneId !== input.laneId) {
|
|
2558
|
+
continue;
|
|
2559
|
+
}
|
|
2560
|
+
count += 1;
|
|
2561
|
+
if (count === 1)
|
|
2562
|
+
record = candidate;
|
|
2563
|
+
}
|
|
2564
|
+
return { count, record: count === 1 ? record : null };
|
|
1738
2565
|
}
|
|
1739
2566
|
function settlementProvenanceFor(record) {
|
|
1740
2567
|
const baseline = record.taskChangeContext?.baseline;
|
|
@@ -1773,9 +2600,11 @@ async function claimTerminalResult(directory, correlationId, terminalResult) {
|
|
|
1773
2600
|
const current = findRecordForWrite(records, correlationId);
|
|
1774
2601
|
if (!current)
|
|
1775
2602
|
return;
|
|
2603
|
+
const normalizedResult = mergeRecordedPrReviewResultReceipt(current, parsedTerminal.data.result);
|
|
2604
|
+
const normalizedTerminal = normalizedResult === parsedTerminal.data.result ? parsedTerminal.data : { ...parsedTerminal.data, result: normalizedResult };
|
|
1776
2605
|
if (current.terminalResult) {
|
|
1777
|
-
if (!sameTerminalEvent(current.terminalResult,
|
|
1778
|
-
warn(`[background] claimTerminalResult: different terminal event for ` + `correlationId=${correlationId}; ` + `existing={status: ${current.terminalResult.status}, eventId: ${current.terminalResult.eventId}} ` + `incoming={status: ${
|
|
2606
|
+
if (!sameTerminalEvent(current.terminalResult, normalizedTerminal)) {
|
|
2607
|
+
warn(`[background] claimTerminalResult: different terminal event for ` + `correlationId=${correlationId}; ` + `existing={status: ${current.terminalResult.status}, eventId: ${current.terminalResult.eventId}} ` + `incoming={status: ${normalizedTerminal.status}, eventId: ${normalizedTerminal.eventId}}; ` + `rejected`);
|
|
1779
2608
|
incrementLateTerminalCount(directory);
|
|
1780
2609
|
return;
|
|
1781
2610
|
}
|
|
@@ -1796,18 +2625,18 @@ async function claimTerminalResult(directory, correlationId, terminalResult) {
|
|
|
1796
2625
|
state: "pending",
|
|
1797
2626
|
provenance,
|
|
1798
2627
|
observedFiles: null,
|
|
1799
|
-
updatedAt:
|
|
2628
|
+
updatedAt: normalizedTerminal.recordedAt
|
|
1800
2629
|
};
|
|
1801
2630
|
}
|
|
1802
2631
|
}
|
|
1803
|
-
const foldUpdatedAt = Math.max(
|
|
2632
|
+
const foldUpdatedAt = Math.max(normalizedTerminal.recordedAt, current.updatedAt);
|
|
1804
2633
|
const next = {
|
|
1805
2634
|
...current,
|
|
1806
|
-
schemaVersion: 3,
|
|
1807
|
-
status:
|
|
1808
|
-
terminalResult:
|
|
1809
|
-
result:
|
|
1810
|
-
completedAt:
|
|
2635
|
+
schemaVersion: normalizedTerminal.result.prReviewResultReceipt ? 4 : current.schemaVersion === 4 ? 4 : 3,
|
|
2636
|
+
status: normalizedTerminal.status,
|
|
2637
|
+
terminalResult: normalizedTerminal,
|
|
2638
|
+
result: normalizedTerminal.result,
|
|
2639
|
+
completedAt: normalizedTerminal.recordedAt,
|
|
1811
2640
|
updatedAt: foldUpdatedAt,
|
|
1812
2641
|
...coderSettlement ? { coderSettlement } : {}
|
|
1813
2642
|
};
|
|
@@ -1885,7 +2714,7 @@ async function claimCoderSettlement(directory, correlationId, operationId, input
|
|
|
1885
2714
|
};
|
|
1886
2715
|
const next = {
|
|
1887
2716
|
...current,
|
|
1888
|
-
schemaVersion: 3,
|
|
2717
|
+
schemaVersion: current.schemaVersion === 4 ? 4 : 3,
|
|
1889
2718
|
coderSettlement: settlement,
|
|
1890
2719
|
updatedAt: settlement.updatedAt
|
|
1891
2720
|
};
|
|
@@ -1993,7 +2822,7 @@ async function updateCoderSettlement(directory, correlationId, input) {
|
|
|
1993
2822
|
};
|
|
1994
2823
|
const next = {
|
|
1995
2824
|
...current,
|
|
1996
|
-
schemaVersion: 3,
|
|
2825
|
+
schemaVersion: current.schemaVersion === 4 ? 4 : 3,
|
|
1997
2826
|
coderSettlement: settlement,
|
|
1998
2827
|
updatedAt
|
|
1999
2828
|
};
|
|
@@ -2077,7 +2906,7 @@ async function updateLegacyCoderSettlementTransfer(directory, correlationId, tra
|
|
|
2077
2906
|
const updatedAt = Date.now();
|
|
2078
2907
|
const next = transfer ? {
|
|
2079
2908
|
...current,
|
|
2080
|
-
schemaVersion: 3,
|
|
2909
|
+
schemaVersion: current.schemaVersion === 4 ? 4 : 3,
|
|
2081
2910
|
legacyCoderSettlementTransfer: {
|
|
2082
2911
|
...transfer,
|
|
2083
2912
|
updatedAt
|
|
@@ -2138,10 +2967,10 @@ async function claimDelegationIngestion(directory, correlationId, options) {
|
|
|
2138
2967
|
}
|
|
2139
2968
|
const disposition = current.status === "ingestion_error" || current.ingestion?.state === "claimed" ? "retry" : "claimed";
|
|
2140
2969
|
const attempt = (current.ingestion?.attempt ?? 0) + 1;
|
|
2141
|
-
const claimToken =
|
|
2970
|
+
const claimToken = createHash3("sha256").update(JSON.stringify([correlationId, options.claimantId, attempt, now])).digest("hex");
|
|
2142
2971
|
const next = {
|
|
2143
2972
|
...current,
|
|
2144
|
-
schemaVersion: 3,
|
|
2973
|
+
schemaVersion: current.schemaVersion === 4 ? 4 : 3,
|
|
2145
2974
|
ingestion: {
|
|
2146
2975
|
state: "claimed",
|
|
2147
2976
|
attempt,
|
|
@@ -2182,7 +3011,7 @@ async function recordDelegationIngestionResult(directory, correlationId, claimTo
|
|
|
2182
3011
|
const updatedAt = options.now ?? Date.now();
|
|
2183
3012
|
const next = {
|
|
2184
3013
|
...current,
|
|
2185
|
-
schemaVersion: 3,
|
|
3014
|
+
schemaVersion: current.schemaVersion === 4 ? 4 : 3,
|
|
2186
3015
|
status: success ? "consumed" : "ingestion_error",
|
|
2187
3016
|
ingestion: {
|
|
2188
3017
|
state: success ? "consumed" : "retryable",
|
|
@@ -2231,7 +3060,7 @@ async function putPendingBackgroundAdvisory(directory, correlationId, input) {
|
|
|
2231
3060
|
}
|
|
2232
3061
|
const next = {
|
|
2233
3062
|
...current,
|
|
2234
|
-
schemaVersion: 3,
|
|
3063
|
+
schemaVersion: current.schemaVersion === 4 ? 4 : 3,
|
|
2235
3064
|
advisoryInbox: parsed.data,
|
|
2236
3065
|
updatedAt: createdAt
|
|
2237
3066
|
};
|
|
@@ -2272,7 +3101,7 @@ async function replacePendingBackgroundAdvisory(directory, correlationId, input)
|
|
|
2272
3101
|
}
|
|
2273
3102
|
const next = {
|
|
2274
3103
|
...current,
|
|
2275
|
-
schemaVersion: 3,
|
|
3104
|
+
schemaVersion: current.schemaVersion === 4 ? 4 : 3,
|
|
2276
3105
|
advisoryInbox: parsed.data,
|
|
2277
3106
|
updatedAt: createdAt
|
|
2278
3107
|
};
|
|
@@ -2320,7 +3149,7 @@ async function preparePendingBackgroundAdvisories(directory, parentSessionId, op
|
|
|
2320
3149
|
};
|
|
2321
3150
|
const next = {
|
|
2322
3151
|
...current,
|
|
2323
|
-
schemaVersion: 3,
|
|
3152
|
+
schemaVersion: current.schemaVersion === 4 ? 4 : 3,
|
|
2324
3153
|
advisoryInbox: nextAdvisory,
|
|
2325
3154
|
updatedAt: now
|
|
2326
3155
|
};
|
|
@@ -2365,7 +3194,7 @@ async function releaseBackgroundAdvisoryPreparation(directory, parentSessionId,
|
|
|
2365
3194
|
const now = Date.now();
|
|
2366
3195
|
const next = {
|
|
2367
3196
|
...current,
|
|
2368
|
-
schemaVersion: 3,
|
|
3197
|
+
schemaVersion: current.schemaVersion === 4 ? 4 : 3,
|
|
2369
3198
|
advisoryInbox: {
|
|
2370
3199
|
...current.advisoryInbox,
|
|
2371
3200
|
preparation: undefined
|
|
@@ -2407,7 +3236,7 @@ async function acknowledgeObservedBackgroundAdvisories(directory, parentSessionI
|
|
|
2407
3236
|
}
|
|
2408
3237
|
const next = {
|
|
2409
3238
|
...current,
|
|
2410
|
-
schemaVersion: 3,
|
|
3239
|
+
schemaVersion: current.schemaVersion === 4 ? 4 : 3,
|
|
2411
3240
|
advisoryInbox: {
|
|
2412
3241
|
...advisory,
|
|
2413
3242
|
state: "delivered",
|
|
@@ -2487,7 +3316,7 @@ async function sweepStaleDelegations(directory, timeoutMs, options = {}) {
|
|
|
2487
3316
|
}
|
|
2488
3317
|
}
|
|
2489
3318
|
function fallbackRelativePath(correlationId) {
|
|
2490
|
-
const digest =
|
|
3319
|
+
const digest = createHash3("sha256").update(correlationId).digest("hex");
|
|
2491
3320
|
return path2.join(BACKGROUND_DELEGATION_FALLBACK_DIR, `${digest}.json`);
|
|
2492
3321
|
}
|
|
2493
3322
|
function fallbackPath(directory, correlationId) {
|
|
@@ -2745,7 +3574,7 @@ function reservationStorePath(directory) {
|
|
|
2745
3574
|
}
|
|
2746
3575
|
function buildBackgroundCoderReservationId(input) {
|
|
2747
3576
|
const ownerIdentity = input.planTaskId === null ? ["call", input.parentSessionId, input.callID] : ["task", input.parentSessionId, input.planTaskId];
|
|
2748
|
-
return `bgcr1:${
|
|
3577
|
+
return `bgcr1:${createHash3("sha256").update(JSON.stringify(ownerIdentity)).digest("hex")}`;
|
|
2749
3578
|
}
|
|
2750
3579
|
function scanBackgroundCoderReservationsForAdmission(directory) {
|
|
2751
3580
|
let absolutePath;
|
|
@@ -3105,7 +3934,7 @@ async function reconcileLegacyCoderSettlements(directory, maxRecords, onReconcil
|
|
|
3105
3934
|
const candidates = readDelegations(directory).filter((record) => record.normalizedAgent === "coder" && Boolean(record.legacyCoderSettlementTransfer) && Boolean(record.terminalResult)).slice(0, maxRecords);
|
|
3106
3935
|
if (candidates.length === 0)
|
|
3107
3936
|
return 0;
|
|
3108
|
-
const { transferCoderSettlementToBackground } = await import("./coder-settlement-
|
|
3937
|
+
const { transferCoderSettlementToBackground } = await import("./coder-settlement-gzar5ypz.js");
|
|
3109
3938
|
let transferred = 0;
|
|
3110
3939
|
for (const record of candidates) {
|
|
3111
3940
|
try {
|
|
@@ -3462,4 +4291,4 @@ async function maintainBackgroundDelegations(directory, options = {}) {
|
|
|
3462
4291
|
return emitObservation("ok");
|
|
3463
4292
|
}
|
|
3464
4293
|
|
|
3465
|
-
export { MAX_RECOVERY_LEDGER_BYTES, readDelegationHealthArtifact, collectDelegationLedgerHealth, MAX_PR_REVIEW_COLLECTION_RECEIPT_ITEM_IDS, BACKGROUND_DELEGATIONS_FILE, BACKGROUND_DELEGATION_FALLBACK_DIR, BACKGROUND_CODER_RESERVATIONS_FILE, BACKGROUND_DELEGATIONS_CHECKPOINT_FILE, BACKGROUND_DELEGATIONS_MANIFEST_FILE, MAX_LIVE_BACKGROUND_FALLBACKS, MAX_LIVE_BACKGROUND_CODER_RESERVATIONS, MAX_BACKGROUND_OBSERVED_FILES, MAX_BACKGROUND_ADVISORY_CHARS, LEGACY_CODER_SETTLEMENT_PENDING_ADVISORY_MARKER, DELEGATION_COMPACTION_LOW_WATER_BYTES, DELEGATION_COMPACTION_HIGH_WATER_BYTES, MAX_CHECKPOINT_BYTES, MAX_CHECKPOINT_RECORDS, TOMBSTONE_MIN_AGE_MS, BACKGROUND_INGESTION_LEASE_MS, BACKGROUND_CODER_RESERVATION_LEASE_MS, BACKGROUND_CODER_RESERVATION_LEASE_MAX_MS, BACKGROUND_CODER_RESERVATION_LEASE_MIN_MS, DEFAULT_STALE_DELEGATION_TIMEOUT_MS, DEFAULT_SWEEPABLE_DELEGATION_STATUSES, _checkpointInternals, isUnsettledWorktreeOwner, compactBackgroundDelegations, readDelegations, scanDelegationsForRecovery, findByCorrelationId, recordPendingDelegationDetailed, recordPendingDelegation, buildPromptSnapshot, appendDelegationTransition, buildBackgroundCompletionEventId, claimTerminalResult, claimCoderSettlement, normalizeBackgroundObservedFiles, updateCoderSettlement, registerLegacyCoderSettlementReconciler, _internals, markLegacyCoderSettlementTransferPending, clearLegacyCoderSettlementTransferPending, claimDelegationIngestion, recordDelegationIngestionResult, putPendingBackgroundAdvisory, replacePendingBackgroundAdvisory, preparePendingBackgroundAdvisories, acknowledgeObservedBackgroundAdvisories, releasePreparedBackgroundAdvisories, findByBatchId, findOpenAsyncLaneBatches, sweepStaleDelegations, readDelegationFallback, listDelegationFallbacks, scanDelegationFallbacksForRecovery, writeDelegationFallback, removeDelegationFallback, findDelegationForCompletion, promoteDelegationFallback, buildBackgroundCoderReservationId, scanBackgroundCoderReservationsForAdmission, reserveBackgroundCoderSlot, bindBackgroundCoderReservation, releaseBackgroundCoderReservation, maintainBackgroundDelegations };
|
|
4294
|
+
export { PR_REVIEW_BASE_DIMENSION_IDS, PR_REVIEW_RISK_IMPACTS, PR_REVIEW_RISK_TAGS, prReviewLegacyTranscriptCompatibilityEnabled, PrReviewResultReceiptSchema, PR_REVIEW_FINDINGS_MAX_BYTES, PR_REVIEW_HANDOFF_MAX_BYTES, PR_REVIEW_DISCARDED_EXAMPLE_ITEM_ID, PrReviewRunIdSchema, prReviewFindingRequiresCritic, parsePrReviewRiskTagsField, PrReviewReviewerVerdictFieldsSchema, PrReviewCriticVerdictFieldsSchema, parsePrReviewVerdictRow, MAX_RECOVERY_LEDGER_BYTES, readDelegationHealthArtifact, collectDelegationLedgerHealth, MAX_PR_REVIEW_COLLECTION_RECEIPT_ITEM_IDS, BACKGROUND_DELEGATIONS_FILE, BACKGROUND_DELEGATION_FALLBACK_DIR, BACKGROUND_CODER_RESERVATIONS_FILE, BACKGROUND_DELEGATIONS_CHECKPOINT_FILE, BACKGROUND_DELEGATIONS_MANIFEST_FILE, MAX_LIVE_BACKGROUND_FALLBACKS, MAX_LIVE_BACKGROUND_CODER_RESERVATIONS, MAX_BACKGROUND_OBSERVED_FILES, MAX_BACKGROUND_ADVISORY_CHARS, LEGACY_CODER_SETTLEMENT_PENDING_ADVISORY_MARKER, DELEGATION_COMPACTION_LOW_WATER_BYTES, DELEGATION_COMPACTION_HIGH_WATER_BYTES, MAX_CHECKPOINT_BYTES, MAX_CHECKPOINT_RECORDS, TOMBSTONE_MIN_AGE_MS, BACKGROUND_INGESTION_LEASE_MS, BACKGROUND_CODER_RESERVATION_LEASE_MS, BACKGROUND_CODER_RESERVATION_LEASE_MAX_MS, BACKGROUND_CODER_RESERVATION_LEASE_MIN_MS, DEFAULT_STALE_DELEGATION_TIMEOUT_MS, DEFAULT_SWEEPABLE_DELEGATION_STATUSES, _checkpointInternals, isUnsettledWorktreeOwner, compactBackgroundDelegations, readDelegations, scanDelegationsForRecovery, findByCorrelationId, recordPendingDelegationDetailed, recordPendingDelegation, buildPromptSnapshot, appendDelegationTransition, publishPrReviewResultReceipt, buildBackgroundCompletionEventId, claimTerminalResult, claimCoderSettlement, normalizeBackgroundObservedFiles, updateCoderSettlement, registerLegacyCoderSettlementReconciler, _internals, markLegacyCoderSettlementTransferPending, clearLegacyCoderSettlementTransferPending, claimDelegationIngestion, recordDelegationIngestionResult, putPendingBackgroundAdvisory, replacePendingBackgroundAdvisory, preparePendingBackgroundAdvisories, acknowledgeObservedBackgroundAdvisories, releasePreparedBackgroundAdvisories, findByBatchId, findOpenAsyncLaneBatches, sweepStaleDelegations, readDelegationFallback, listDelegationFallbacks, scanDelegationFallbacksForRecovery, writeDelegationFallback, removeDelegationFallback, findDelegationForCompletion, promoteDelegationFallback, buildBackgroundCoderReservationId, scanBackgroundCoderReservationsForAdmission, reserveBackgroundCoderSlot, bindBackgroundCoderReservation, releaseBackgroundCoderReservation, maintainBackgroundDelegations };
|