opencode-swarm 7.159.3 → 7.160.1
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-review/SKILL.md +28 -29
- package/.opencode/skills/swarm-pr-review/references/prompt-templates.md +21 -5
- package/dist/background/delegation-health.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/cli/{coder-settlement-50p7dsya.js → coder-settlement-678ccmnf.js} +11 -10
- package/dist/cli/{config-doctor-a7drgs33.js → config-doctor-fr8dfrt2.js} +3 -3
- package/dist/cli/{core-madqgdsc.js → core-4j1hbhey.js} +2 -2
- package/dist/cli/{curation-policy-ray8h55z.js → curation-policy-47przjwg.js} +6 -6
- package/dist/cli/{curator-3sz7refy.js → curator-85d97240.js} +33 -32
- package/dist/cli/curator-llm-factory-s9s4s0q3.js +67 -0
- package/dist/cli/{evidence-summary-service-cwyjkdsa.js → evidence-summary-service-9dyt2kzh.js} +15 -14
- package/dist/cli/{gate-evidence-95k5ap1z.js → gate-evidence-a6paafg8.js} +7 -7
- package/dist/cli/guardrail-explain-4a2xdtew.js +68 -0
- package/dist/cli/{guardrail-log-nerqk9qb.js → guardrail-log-27nkntrx.js} +9 -6
- package/dist/cli/{guardrail-reset-chbc0mep.js → guardrail-reset-xn7k3hn8.js} +33 -32
- package/dist/cli/{hive-promoter-4rtxhw7n.js → hive-promoter-k57j3kp6.js} +33 -32
- package/dist/cli/{index-515nwvdp.js → index-497a3hhj.js} +19 -10
- package/dist/cli/{index-h96xp4t0.js → index-61c3d769.js} +875 -37
- package/dist/cli/{index-ve0xj03m.js → index-7ezv5j23.js} +4 -4
- package/dist/cli/{index-0zerbq1v.js → index-7h2armwf.js} +23 -14
- package/dist/cli/{index-ebxmfr4j.js → index-7npz9n4s.js} +5 -4
- package/dist/cli/{index-m9m3emns.js → index-7v0ex0jt.js} +2 -2
- package/dist/cli/{index-ebz97mks.js → index-8c9qzpy7.js} +1 -0
- package/dist/cli/{index-5hfqc3h3.js → index-98jmggma.js} +24 -7
- package/dist/cli/{index-8fyebh3w.js → index-awjx0wgk.js} +1 -1
- package/dist/cli/{index-av3gnekk.js → index-b5adxpy6.js} +1 -1
- package/dist/cli/{index-t3wk7q51.js → index-bqxffayb.js} +1 -1
- package/dist/cli/{index-yt75r1er.js → index-c9zp4xwc.js} +13 -2
- package/dist/cli/{index-9qw4sbg1.js → index-dh5q6z7y.js} +7 -7
- package/dist/cli/{index-prknc0xn.js → index-dke4wzkn.js} +108 -44
- package/dist/cli/{index-nvz4mp5w.js → index-dq93ar40.js} +6 -6
- package/dist/cli/{index-zswy6xgb.js → index-drqvph47.js} +7 -7
- package/dist/cli/{index-sn6mtxxc.js → index-e1ygmd4q.js} +35 -34
- package/dist/cli/{index-6jp5yxye.js → index-f72612zc.js} +16 -2
- package/dist/cli/{index-y2d381ce.js → index-gjx53y3c.js} +1 -1
- package/dist/cli/{index-xs32znyz.js → index-j3ss86kf.js} +1 -1
- package/dist/cli/{index-p3ym3y8b.js → index-jszabr0r.js} +4 -4
- package/dist/cli/{index-wwpe4am7.js → index-m1cw9fsh.js} +8 -8
- package/dist/cli/{index-8zw60wya.js → index-m84z3aa8.js} +13 -4
- package/dist/cli/index-mmr96pwr.js +785 -0
- package/dist/cli/{index-gk6gpe7r.js → index-nk498mx6.js} +2 -2
- package/dist/cli/{index-2jzmg2km.js → index-nnzdayvk.js} +6 -6
- package/dist/cli/{index-fnxmg8sz.js → index-ny0g8fdg.js} +5 -5
- package/dist/cli/{index-40t6s98s.js → index-pkz91fwm.js} +3 -3
- package/dist/cli/{index-bxpqq9th.js → index-pqjcyj0p.js} +3 -3
- package/dist/cli/{index-nhhek8yw.js → index-prv20xq6.js} +1 -1
- package/dist/cli/{index-mqfs5f8a.js → index-qc53dfzh.js} +2 -2
- package/dist/cli/{index-xqjhbfbx.js → index-v8dsmee1.js} +4 -4
- package/dist/cli/{index-qxpfmryw.js → index-wccdm7jv.js} +5 -5
- package/dist/cli/{index-rq4jcw64.js → index-z0bxbb9g.js} +4 -4
- package/dist/cli/{index-txwx9p21.js → index-zdv914xa.js} +585 -471
- package/dist/cli/{index-2fq4a3vk.js → index-znf683sm.js} +1 -1
- package/dist/cli/{index-v3ybemb1.js → index-zpzvpybn.js} +2 -2
- package/dist/cli/index.js +33 -32
- package/dist/cli/{knowledge-escalator-f80n84ch.js → knowledge-escalator-3q2x34cg.js} +14 -13
- package/dist/cli/{knowledge-events-1d7v2krw.js → knowledge-events-5y34w84b.js} +12 -11
- package/dist/cli/{knowledge-link-vm4caewt.js → knowledge-link-xezm8hr3.js} +5 -5
- package/dist/cli/{knowledge-store-66yxeet7.js → knowledge-store-fqv89q5k.js} +6 -6
- package/dist/cli/{knowledge-validator-p0xcx7jx.js → knowledge-validator-fsdx14tk.js} +8 -8
- package/dist/cli/{model-preflight-w85ecyxh.js → model-preflight-yqqchzjn.js} +1 -1
- package/dist/cli/{pending-delegations-vad1z71d.js → pending-delegations-6ae7wy5q.js} +7 -3
- package/dist/cli/{pr-review-reentry-authorization-kn3nny7h.js → pr-review-reentry-authorization-986tk381.js} +35 -33
- package/dist/cli/{pr-subscriptions-482gzvt6.js → pr-subscriptions-asjevc5p.js} +5 -4
- package/dist/cli/{runner-sn7a6zd0.js → runner-wsdcy2d6.js} +6 -6
- package/dist/cli/{scan-cursor-2v7995nb.js → scan-cursor-shn926r6.js} +7 -7
- package/dist/cli/{schema-dy8fqycb.js → schema-98tdb9h0.js} +4 -2
- package/dist/cli/{scope-persistence-baty62vx.js → scope-persistence-cn34xnwr.js} +10 -9
- package/dist/cli/{skill-generator-nwrvtqbz.js → skill-generator-kck7087c.js} +16 -15
- package/dist/cli/{telemetry-3rh94wv3.js → telemetry-gpr9s3sm.js} +3 -1
- package/dist/cli/{worktree-collision-ownership-cy24p5mr.js → worktree-collision-ownership-6b3kshcv.js} +6 -5
- package/dist/cli/{worktree-isolation-8jbx0s8d.js → worktree-isolation-he01qhss.js} +33 -32
- package/dist/config/constants.d.ts +8 -0
- package/dist/config/context-window.d.ts +11 -4
- package/dist/config/evidence-schema.d.ts +9 -6
- package/dist/config/schema.d.ts +8 -0
- package/dist/context-map/telemetry.d.ts +1 -1
- package/dist/health/learning-health.d.ts +356 -0
- package/dist/hooks/context-budget.d.ts +10 -1
- package/dist/hooks/curator.d.ts +2 -0
- package/dist/hooks/final-context-accounting.d.ts +2 -0
- package/dist/hooks/model-limits.d.ts +56 -25
- package/dist/hooks/pr-workflow-gate.d.ts +25 -1
- package/dist/hooks/skill-usage-pending.d.ts +1 -1
- package/dist/index.js +623 -609
- package/dist/observability/catalog.d.ts +2 -2
- package/dist/observability/ids.d.ts +17 -0
- package/dist/prm/trajectory-store.d.ts +1 -1
- package/dist/services/diagnose-service.d.ts +7 -0
- package/dist/services/status-service.d.ts +18 -0
- package/dist/telemetry.d.ts +52 -1
- package/dist/tools/context-status.d.ts +15 -1
- 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/repo-graph/ontology.d.ts +6 -0
- package/dist/tools/repo-graph/pack-query.d.ts +36 -0
- package/dist/tools/repo-graph/types.d.ts +198 -1
- package/dist/tools/repo-graph.d.ts +5 -3
- 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/tool-metadata.d.ts +8 -0
- package/opencode-swarm.schema.json +4 -0
- package/package.json +1 -1
- package/dist/cli/curator-llm-factory-pyp5kmra.js +0 -66
- package/dist/cli/guardrail-explain-a13kbmrt.js +0 -67
|
@@ -8,15 +8,19 @@ import {
|
|
|
8
8
|
import {
|
|
9
9
|
bunWrite
|
|
10
10
|
} from "./index-r3mvsbtq.js";
|
|
11
|
+
import {
|
|
12
|
+
observeDelegationLedgerPressure
|
|
13
|
+
} from "./index-mmr96pwr.js";
|
|
11
14
|
import {
|
|
12
15
|
EvidenceLockTimeoutError,
|
|
13
16
|
withEvidenceLock
|
|
14
|
-
} from "./index-
|
|
17
|
+
} from "./index-b5adxpy6.js";
|
|
15
18
|
import {
|
|
16
19
|
exports_external,
|
|
17
20
|
init_zod
|
|
18
21
|
} from "./index-bpmtbmy9.js";
|
|
19
22
|
import {
|
|
23
|
+
criticalWarn,
|
|
20
24
|
init_logger,
|
|
21
25
|
warn
|
|
22
26
|
} from "./index-zgwm4ryv.js";
|
|
@@ -26,7 +30,7 @@ import {
|
|
|
26
30
|
|
|
27
31
|
// src/background/pending-delegations.ts
|
|
28
32
|
init_zod();
|
|
29
|
-
import { createHash as
|
|
33
|
+
import { createHash as createHash3 } from "crypto";
|
|
30
34
|
import * as fs2 from "fs";
|
|
31
35
|
import * as path2 from "path";
|
|
32
36
|
import { isDeepStrictEqual } from "util";
|
|
@@ -269,6 +273,12 @@ function collectDelegationLedgerHealth(directory, options) {
|
|
|
269
273
|
const limitBytes = options.ledgerLimitBytes;
|
|
270
274
|
const pressurePct = Math.min(100, Math.round(ledgerBytes / limitBytes * 1000) / 10);
|
|
271
275
|
const band = ledgerBytes > limitBytes ? "fail-closed" : ledgerBytes > options.highWaterBytes ? "compact-overdue" : ledgerBytes > options.lowWaterBytes ? "nominal" : "ok";
|
|
276
|
+
observeDelegationLedgerPressure({
|
|
277
|
+
directory,
|
|
278
|
+
pressurePct: pressurePct / 100,
|
|
279
|
+
band,
|
|
280
|
+
uncertain: artifact?.lastUncertainty != null
|
|
281
|
+
});
|
|
272
282
|
return {
|
|
273
283
|
schemaVersion: 1,
|
|
274
284
|
updatedAt: artifact?.updatedAt ?? 0,
|
|
@@ -383,6 +393,638 @@ function parsePrReviewCollectionReceiptFooter(binding, result) {
|
|
|
383
393
|
const payload = parsed.data;
|
|
384
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;
|
|
385
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
|
+
}
|
|
386
1028
|
// src/background/pending-delegations.ts
|
|
387
1029
|
var BACKGROUND_DELEGATIONS_FILE = "background-delegations.jsonl";
|
|
388
1030
|
var BACKGROUND_DELEGATION_FALLBACK_DIR = "background-delegation-fallback";
|
|
@@ -396,6 +1038,8 @@ var MAX_BACKGROUND_ADVISORY_CHARS = 4000;
|
|
|
396
1038
|
var LEGACY_CODER_SETTLEMENT_PENDING_ADVISORY_MARKER = "legacy coder settlement transfer is pending";
|
|
397
1039
|
var MAX_BACKGROUND_DELEGATION_GENERATION = 1e6;
|
|
398
1040
|
var MAX_RECOVERY_FALLBACK_BYTES = 1024 * 1024;
|
|
1041
|
+
var MAX_TRACKED_LENIENT_LEDGER_SIGNALS = 32;
|
|
1042
|
+
var LENIENT_LEDGER_SIGNAL_SOURCE = "lenient-read";
|
|
399
1043
|
var DELEGATION_COMPACTION_LOW_WATER_BYTES = 256 * 1024;
|
|
400
1044
|
var DELEGATION_COMPACTION_HIGH_WATER_BYTES = 1024 * 1024;
|
|
401
1045
|
var MAX_CHECKPOINT_BYTES = 2 * 1024 * 1024;
|
|
@@ -448,6 +1092,7 @@ var ResultSchema = exports_external.object({
|
|
|
448
1092
|
outputArtifactError: exports_external.string().optional(),
|
|
449
1093
|
transcriptIncomplete: exports_external.boolean().optional(),
|
|
450
1094
|
messageCount: exports_external.number().optional(),
|
|
1095
|
+
prReviewResultReceipt: PrReviewResultReceiptSchema.optional(),
|
|
451
1096
|
workflowLaneFailureClass: exports_external.enum(["contract", "resource", "deadline"]).optional(),
|
|
452
1097
|
terminalErrorClass: exports_external.object({
|
|
453
1098
|
kind: exports_external.enum(["provider", "aborted", "output_length", "unknown"]),
|
|
@@ -643,7 +1288,12 @@ var PromptSchema = exports_external.object({
|
|
|
643
1288
|
digest: exports_external.string()
|
|
644
1289
|
}).strict();
|
|
645
1290
|
var RecordSchema = exports_external.object({
|
|
646
|
-
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
|
+
]),
|
|
647
1297
|
correlationId: exports_external.string().min(1),
|
|
648
1298
|
jobId: exports_external.string().nullable(),
|
|
649
1299
|
subagentSessionId: exports_external.string().min(1),
|
|
@@ -670,6 +1320,7 @@ var RecordSchema = exports_external.object({
|
|
|
670
1320
|
mode: exports_external.string().optional(),
|
|
671
1321
|
workflowLane: exports_external.string().optional(),
|
|
672
1322
|
ownedWorkflowLanes: exports_external.array(exports_external.string().min(1).max(120)).min(1).max(11).optional(),
|
|
1323
|
+
prReviewLegacyTranscriptCompatibility: exports_external.boolean().optional(),
|
|
673
1324
|
promptHash: exports_external.string().optional(),
|
|
674
1325
|
workspace: WorkspaceSchema.optional(),
|
|
675
1326
|
taskChangeContext: TaskChangeContextSchema.optional(),
|
|
@@ -852,7 +1503,7 @@ function readDelegationCheckpoint(directory) {
|
|
|
852
1503
|
return { kind: "ok", checkpoint: parsed.data, bytes };
|
|
853
1504
|
}
|
|
854
1505
|
function sha256Hex(data) {
|
|
855
|
-
return
|
|
1506
|
+
return createHash3("sha256").update(data).digest("hex");
|
|
856
1507
|
}
|
|
857
1508
|
function checkpointPayloadChecksum(checkpoint) {
|
|
858
1509
|
return sha256Hex(JSON.stringify([
|
|
@@ -870,6 +1521,8 @@ function checkpointPayloadChecksum(checkpoint) {
|
|
|
870
1521
|
}
|
|
871
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";
|
|
872
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 = [];
|
|
873
1526
|
function loadFoldedState(directory, options) {
|
|
874
1527
|
const manifestRead = readDelegationManifest(directory);
|
|
875
1528
|
if (manifestRead.kind === "invalid") {
|
|
@@ -959,9 +1612,13 @@ function loadFoldedState(directory, options) {
|
|
|
959
1612
|
for (const summary of checkpoint.closed) {
|
|
960
1613
|
records.set(summary.correlationId, summary);
|
|
961
1614
|
}
|
|
962
|
-
const
|
|
1615
|
+
const lenientSkips = emptyLenientLedgerSkipCounts();
|
|
1616
|
+
const foldError = foldLedgerTail(records, tail, options.strict, checkpoint, lenientSkips);
|
|
963
1617
|
if (foldError)
|
|
964
1618
|
return { status: "uncertain", reason: foldError };
|
|
1619
|
+
if (!options.strict) {
|
|
1620
|
+
recordLenientLedgerSkips(directory, mode, lenientSkips);
|
|
1621
|
+
}
|
|
965
1622
|
return {
|
|
966
1623
|
status: "ok",
|
|
967
1624
|
mode,
|
|
@@ -996,7 +1653,7 @@ function readBoundedRecentLedgerWindow(directory, size) {
|
|
|
996
1653
|
const firstNewline = window.indexOf(10);
|
|
997
1654
|
return firstNewline === -1 ? Buffer.alloc(0) : window.subarray(firstNewline + 1);
|
|
998
1655
|
}
|
|
999
|
-
function foldLedgerTail(records, tail, strict, checkpoint) {
|
|
1656
|
+
function foldLedgerTail(records, tail, strict, checkpoint, lenientSkips) {
|
|
1000
1657
|
let lineNumber = 0;
|
|
1001
1658
|
for (const line of tail.toString("utf-8").split(`
|
|
1002
1659
|
`)) {
|
|
@@ -1011,6 +1668,8 @@ function foldLedgerTail(records, tail, strict, checkpoint) {
|
|
|
1011
1668
|
if (strict) {
|
|
1012
1669
|
return `background delegation ledger has malformed JSON at line ${lineNumber}`;
|
|
1013
1670
|
}
|
|
1671
|
+
if (lenientSkips)
|
|
1672
|
+
lenientSkips.malformedJson += 1;
|
|
1014
1673
|
continue;
|
|
1015
1674
|
}
|
|
1016
1675
|
const parsed = RecordSchema.safeParse(parsedJson);
|
|
@@ -1018,6 +1677,8 @@ function foldLedgerTail(records, tail, strict, checkpoint) {
|
|
|
1018
1677
|
if (strict) {
|
|
1019
1678
|
return `background delegation ledger has an invalid record at line ${lineNumber}`;
|
|
1020
1679
|
}
|
|
1680
|
+
if (lenientSkips)
|
|
1681
|
+
lenientSkips.invalidRecord += 1;
|
|
1021
1682
|
continue;
|
|
1022
1683
|
}
|
|
1023
1684
|
const existing = checkpoint ? records.get(parsed.data.correlationId) : undefined;
|
|
@@ -1046,7 +1707,9 @@ function loadLegacyLedger(directory, strict) {
|
|
|
1046
1707
|
};
|
|
1047
1708
|
}
|
|
1048
1709
|
const records2 = new Map;
|
|
1049
|
-
const
|
|
1710
|
+
const lenientSkips = emptyLenientLedgerSkipCounts();
|
|
1711
|
+
const foldError2 = foldLedgerTail(records2, Buffer.from(raw2, "utf-8"), false, undefined, lenientSkips);
|
|
1712
|
+
recordLenientLedgerSkips(directory, "legacy-ledger", lenientSkips);
|
|
1050
1713
|
return {
|
|
1051
1714
|
status: "ok",
|
|
1052
1715
|
mode: "legacy",
|
|
@@ -1136,6 +1799,48 @@ function recordLedgerUncertainty(directory, reason, source, repairHint) {
|
|
|
1136
1799
|
});
|
|
1137
1800
|
} catch {}
|
|
1138
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
|
+
}
|
|
1139
1844
|
function isUnsettledWorktreeOwner(record) {
|
|
1140
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"));
|
|
1141
1846
|
}
|
|
@@ -1166,7 +1871,7 @@ function buildClosedSummary(record) {
|
|
|
1166
1871
|
if (summary.terminalResult) {
|
|
1167
1872
|
summary.terminalResult = {
|
|
1168
1873
|
...summary.terminalResult,
|
|
1169
|
-
result:
|
|
1874
|
+
result: dropTerminalResultBody(summary.terminalResult.result)
|
|
1170
1875
|
};
|
|
1171
1876
|
}
|
|
1172
1877
|
const parsed = RecordSchema.safeParse(summary);
|
|
@@ -1188,6 +1893,10 @@ function dropResultBody(result) {
|
|
|
1188
1893
|
} = result;
|
|
1189
1894
|
return rest;
|
|
1190
1895
|
}
|
|
1896
|
+
function dropTerminalResultBody(result) {
|
|
1897
|
+
const { prReviewResultReceipt: _receipt, ...rest } = dropResultBody(result);
|
|
1898
|
+
return rest;
|
|
1899
|
+
}
|
|
1191
1900
|
function dropRetainedPrReviewReceipt(record) {
|
|
1192
1901
|
const compact = (result) => {
|
|
1193
1902
|
const payload = parsePrReviewCollectionReceiptFooter(record, result);
|
|
@@ -1213,7 +1922,7 @@ function dropRetainedPrReviewReceipt(record) {
|
|
|
1213
1922
|
...record.terminalResult ? {
|
|
1214
1923
|
terminalResult: {
|
|
1215
1924
|
...record.terminalResult,
|
|
1216
|
-
result:
|
|
1925
|
+
result: dropTerminalResultBody(record.terminalResult.result)
|
|
1217
1926
|
}
|
|
1218
1927
|
} : {}
|
|
1219
1928
|
};
|
|
@@ -1578,6 +2287,9 @@ function buildPendingRecord(input, now) {
|
|
|
1578
2287
|
...input.mode ? { mode: input.mode } : {},
|
|
1579
2288
|
...input.workflowLane ? { workflowLane: input.workflowLane } : {},
|
|
1580
2289
|
...input.ownedWorkflowLanes?.length ? { ownedWorkflowLanes: [...input.ownedWorkflowLanes] } : {},
|
|
2290
|
+
...input.prReviewLegacyTranscriptCompatibility !== undefined ? {
|
|
2291
|
+
prReviewLegacyTranscriptCompatibility: input.prReviewLegacyTranscriptCompatibility
|
|
2292
|
+
} : {},
|
|
1581
2293
|
...input.promptHash ? { promptHash: input.promptHash } : {},
|
|
1582
2294
|
...input.workspace ? { workspace: input.workspace } : {},
|
|
1583
2295
|
...input.taskChangeContext ? { taskChangeContext: input.taskChangeContext } : {},
|
|
@@ -1670,7 +2382,7 @@ function buildPromptSnapshot(text, maxChars) {
|
|
|
1670
2382
|
text: bounded,
|
|
1671
2383
|
chars: text.length,
|
|
1672
2384
|
truncated,
|
|
1673
|
-
digest:
|
|
2385
|
+
digest: createHash3("sha256").update(text).digest("hex")
|
|
1674
2386
|
};
|
|
1675
2387
|
}
|
|
1676
2388
|
async function appendDelegationTransition(directory, correlationId, transition) {
|
|
@@ -1694,7 +2406,7 @@ async function appendDelegationTransition(directory, correlationId, transition)
|
|
|
1694
2406
|
}
|
|
1695
2407
|
next = {
|
|
1696
2408
|
...current,
|
|
1697
|
-
schemaVersion: current.schemaVersion === 1 ? 2 : current.schemaVersion,
|
|
2409
|
+
schemaVersion: transition.result?.prReviewResultReceipt ? 4 : current.schemaVersion === 1 ? 2 : current.schemaVersion,
|
|
1698
2410
|
status: transition.status,
|
|
1699
2411
|
updatedAt: now,
|
|
1700
2412
|
...transition.completedAt !== undefined ? { completedAt: transition.completedAt } : transition.status === "completed" || transition.status === "error" ? { completedAt: now } : {},
|
|
@@ -1709,6 +2421,87 @@ async function appendDelegationTransition(directory, correlationId, transition)
|
|
|
1709
2421
|
return null;
|
|
1710
2422
|
}
|
|
1711
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
|
+
}
|
|
1712
2505
|
function buildBackgroundCompletionEventId(input) {
|
|
1713
2506
|
const canonical = JSON.stringify([
|
|
1714
2507
|
input.correlationId,
|
|
@@ -1716,16 +2509,59 @@ function buildBackgroundCompletionEventId(input) {
|
|
|
1716
2509
|
input.status,
|
|
1717
2510
|
input.resultDigest
|
|
1718
2511
|
]);
|
|
1719
|
-
return `bgc1:${
|
|
2512
|
+
return `bgc1:${createHash3("sha256").update(canonical).digest("hex")}`;
|
|
1720
2513
|
}
|
|
1721
2514
|
function sameJson(left, right) {
|
|
1722
2515
|
return JSON.stringify(left) === JSON.stringify(right);
|
|
1723
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
|
+
}
|
|
1724
2538
|
function sameTerminalEvent(left, right) {
|
|
1725
2539
|
return left.eventId === right.eventId && left.status === right.status && sameRetainedResult(left.result, right.result);
|
|
1726
2540
|
}
|
|
1727
2541
|
function sameRetainedResult(left, right) {
|
|
1728
|
-
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 };
|
|
1729
2565
|
}
|
|
1730
2566
|
function settlementProvenanceFor(record) {
|
|
1731
2567
|
const baseline = record.taskChangeContext?.baseline;
|
|
@@ -1764,9 +2600,11 @@ async function claimTerminalResult(directory, correlationId, terminalResult) {
|
|
|
1764
2600
|
const current = findRecordForWrite(records, correlationId);
|
|
1765
2601
|
if (!current)
|
|
1766
2602
|
return;
|
|
2603
|
+
const normalizedResult = mergeRecordedPrReviewResultReceipt(current, parsedTerminal.data.result);
|
|
2604
|
+
const normalizedTerminal = normalizedResult === parsedTerminal.data.result ? parsedTerminal.data : { ...parsedTerminal.data, result: normalizedResult };
|
|
1767
2605
|
if (current.terminalResult) {
|
|
1768
|
-
if (!sameTerminalEvent(current.terminalResult,
|
|
1769
|
-
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`);
|
|
1770
2608
|
incrementLateTerminalCount(directory);
|
|
1771
2609
|
return;
|
|
1772
2610
|
}
|
|
@@ -1787,18 +2625,18 @@ async function claimTerminalResult(directory, correlationId, terminalResult) {
|
|
|
1787
2625
|
state: "pending",
|
|
1788
2626
|
provenance,
|
|
1789
2627
|
observedFiles: null,
|
|
1790
|
-
updatedAt:
|
|
2628
|
+
updatedAt: normalizedTerminal.recordedAt
|
|
1791
2629
|
};
|
|
1792
2630
|
}
|
|
1793
2631
|
}
|
|
1794
|
-
const foldUpdatedAt = Math.max(
|
|
2632
|
+
const foldUpdatedAt = Math.max(normalizedTerminal.recordedAt, current.updatedAt);
|
|
1795
2633
|
const next = {
|
|
1796
2634
|
...current,
|
|
1797
|
-
schemaVersion: 3,
|
|
1798
|
-
status:
|
|
1799
|
-
terminalResult:
|
|
1800
|
-
result:
|
|
1801
|
-
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,
|
|
1802
2640
|
updatedAt: foldUpdatedAt,
|
|
1803
2641
|
...coderSettlement ? { coderSettlement } : {}
|
|
1804
2642
|
};
|
|
@@ -1876,7 +2714,7 @@ async function claimCoderSettlement(directory, correlationId, operationId, input
|
|
|
1876
2714
|
};
|
|
1877
2715
|
const next = {
|
|
1878
2716
|
...current,
|
|
1879
|
-
schemaVersion: 3,
|
|
2717
|
+
schemaVersion: current.schemaVersion === 4 ? 4 : 3,
|
|
1880
2718
|
coderSettlement: settlement,
|
|
1881
2719
|
updatedAt: settlement.updatedAt
|
|
1882
2720
|
};
|
|
@@ -1984,7 +2822,7 @@ async function updateCoderSettlement(directory, correlationId, input) {
|
|
|
1984
2822
|
};
|
|
1985
2823
|
const next = {
|
|
1986
2824
|
...current,
|
|
1987
|
-
schemaVersion: 3,
|
|
2825
|
+
schemaVersion: current.schemaVersion === 4 ? 4 : 3,
|
|
1988
2826
|
coderSettlement: settlement,
|
|
1989
2827
|
updatedAt
|
|
1990
2828
|
};
|
|
@@ -2068,7 +2906,7 @@ async function updateLegacyCoderSettlementTransfer(directory, correlationId, tra
|
|
|
2068
2906
|
const updatedAt = Date.now();
|
|
2069
2907
|
const next = transfer ? {
|
|
2070
2908
|
...current,
|
|
2071
|
-
schemaVersion: 3,
|
|
2909
|
+
schemaVersion: current.schemaVersion === 4 ? 4 : 3,
|
|
2072
2910
|
legacyCoderSettlementTransfer: {
|
|
2073
2911
|
...transfer,
|
|
2074
2912
|
updatedAt
|
|
@@ -2129,10 +2967,10 @@ async function claimDelegationIngestion(directory, correlationId, options) {
|
|
|
2129
2967
|
}
|
|
2130
2968
|
const disposition = current.status === "ingestion_error" || current.ingestion?.state === "claimed" ? "retry" : "claimed";
|
|
2131
2969
|
const attempt = (current.ingestion?.attempt ?? 0) + 1;
|
|
2132
|
-
const claimToken =
|
|
2970
|
+
const claimToken = createHash3("sha256").update(JSON.stringify([correlationId, options.claimantId, attempt, now])).digest("hex");
|
|
2133
2971
|
const next = {
|
|
2134
2972
|
...current,
|
|
2135
|
-
schemaVersion: 3,
|
|
2973
|
+
schemaVersion: current.schemaVersion === 4 ? 4 : 3,
|
|
2136
2974
|
ingestion: {
|
|
2137
2975
|
state: "claimed",
|
|
2138
2976
|
attempt,
|
|
@@ -2173,7 +3011,7 @@ async function recordDelegationIngestionResult(directory, correlationId, claimTo
|
|
|
2173
3011
|
const updatedAt = options.now ?? Date.now();
|
|
2174
3012
|
const next = {
|
|
2175
3013
|
...current,
|
|
2176
|
-
schemaVersion: 3,
|
|
3014
|
+
schemaVersion: current.schemaVersion === 4 ? 4 : 3,
|
|
2177
3015
|
status: success ? "consumed" : "ingestion_error",
|
|
2178
3016
|
ingestion: {
|
|
2179
3017
|
state: success ? "consumed" : "retryable",
|
|
@@ -2222,7 +3060,7 @@ async function putPendingBackgroundAdvisory(directory, correlationId, input) {
|
|
|
2222
3060
|
}
|
|
2223
3061
|
const next = {
|
|
2224
3062
|
...current,
|
|
2225
|
-
schemaVersion: 3,
|
|
3063
|
+
schemaVersion: current.schemaVersion === 4 ? 4 : 3,
|
|
2226
3064
|
advisoryInbox: parsed.data,
|
|
2227
3065
|
updatedAt: createdAt
|
|
2228
3066
|
};
|
|
@@ -2263,7 +3101,7 @@ async function replacePendingBackgroundAdvisory(directory, correlationId, input)
|
|
|
2263
3101
|
}
|
|
2264
3102
|
const next = {
|
|
2265
3103
|
...current,
|
|
2266
|
-
schemaVersion: 3,
|
|
3104
|
+
schemaVersion: current.schemaVersion === 4 ? 4 : 3,
|
|
2267
3105
|
advisoryInbox: parsed.data,
|
|
2268
3106
|
updatedAt: createdAt
|
|
2269
3107
|
};
|
|
@@ -2311,7 +3149,7 @@ async function preparePendingBackgroundAdvisories(directory, parentSessionId, op
|
|
|
2311
3149
|
};
|
|
2312
3150
|
const next = {
|
|
2313
3151
|
...current,
|
|
2314
|
-
schemaVersion: 3,
|
|
3152
|
+
schemaVersion: current.schemaVersion === 4 ? 4 : 3,
|
|
2315
3153
|
advisoryInbox: nextAdvisory,
|
|
2316
3154
|
updatedAt: now
|
|
2317
3155
|
};
|
|
@@ -2356,7 +3194,7 @@ async function releaseBackgroundAdvisoryPreparation(directory, parentSessionId,
|
|
|
2356
3194
|
const now = Date.now();
|
|
2357
3195
|
const next = {
|
|
2358
3196
|
...current,
|
|
2359
|
-
schemaVersion: 3,
|
|
3197
|
+
schemaVersion: current.schemaVersion === 4 ? 4 : 3,
|
|
2360
3198
|
advisoryInbox: {
|
|
2361
3199
|
...current.advisoryInbox,
|
|
2362
3200
|
preparation: undefined
|
|
@@ -2398,7 +3236,7 @@ async function acknowledgeObservedBackgroundAdvisories(directory, parentSessionI
|
|
|
2398
3236
|
}
|
|
2399
3237
|
const next = {
|
|
2400
3238
|
...current,
|
|
2401
|
-
schemaVersion: 3,
|
|
3239
|
+
schemaVersion: current.schemaVersion === 4 ? 4 : 3,
|
|
2402
3240
|
advisoryInbox: {
|
|
2403
3241
|
...advisory,
|
|
2404
3242
|
state: "delivered",
|
|
@@ -2478,7 +3316,7 @@ async function sweepStaleDelegations(directory, timeoutMs, options = {}) {
|
|
|
2478
3316
|
}
|
|
2479
3317
|
}
|
|
2480
3318
|
function fallbackRelativePath(correlationId) {
|
|
2481
|
-
const digest =
|
|
3319
|
+
const digest = createHash3("sha256").update(correlationId).digest("hex");
|
|
2482
3320
|
return path2.join(BACKGROUND_DELEGATION_FALLBACK_DIR, `${digest}.json`);
|
|
2483
3321
|
}
|
|
2484
3322
|
function fallbackPath(directory, correlationId) {
|
|
@@ -2736,7 +3574,7 @@ function reservationStorePath(directory) {
|
|
|
2736
3574
|
}
|
|
2737
3575
|
function buildBackgroundCoderReservationId(input) {
|
|
2738
3576
|
const ownerIdentity = input.planTaskId === null ? ["call", input.parentSessionId, input.callID] : ["task", input.parentSessionId, input.planTaskId];
|
|
2739
|
-
return `bgcr1:${
|
|
3577
|
+
return `bgcr1:${createHash3("sha256").update(JSON.stringify(ownerIdentity)).digest("hex")}`;
|
|
2740
3578
|
}
|
|
2741
3579
|
function scanBackgroundCoderReservationsForAdmission(directory) {
|
|
2742
3580
|
let absolutePath;
|
|
@@ -3096,7 +3934,7 @@ async function reconcileLegacyCoderSettlements(directory, maxRecords, onReconcil
|
|
|
3096
3934
|
const candidates = readDelegations(directory).filter((record) => record.normalizedAgent === "coder" && Boolean(record.legacyCoderSettlementTransfer) && Boolean(record.terminalResult)).slice(0, maxRecords);
|
|
3097
3935
|
if (candidates.length === 0)
|
|
3098
3936
|
return 0;
|
|
3099
|
-
const { transferCoderSettlementToBackground } = await import("./coder-settlement-
|
|
3937
|
+
const { transferCoderSettlementToBackground } = await import("./coder-settlement-678ccmnf.js");
|
|
3100
3938
|
let transferred = 0;
|
|
3101
3939
|
for (const record of candidates) {
|
|
3102
3940
|
try {
|
|
@@ -3453,4 +4291,4 @@ async function maintainBackgroundDelegations(directory, options = {}) {
|
|
|
3453
4291
|
return emitObservation("ok");
|
|
3454
4292
|
}
|
|
3455
4293
|
|
|
3456
|
-
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 };
|