@akagilnc/pi-workflow-roles 0.1.1893 → 0.1.1941
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/dist/evidence-child-executor.js +12 -6
- package/dist/package-contracts/reviewer-output.js +16 -0
- package/dist/public-cli/main.js +447 -173
- package/dist/reviewer-construction.js +46 -6
- package/dist/reviewer-dispatch.js +64 -1
- package/dist/reviewer-execution-ledger.js +2 -1
- package/dist/reviewer-pinned-git.js +33 -0
- package/package.json +1 -1
- package/src/evidence-child-executor.ts +13 -6
- package/src/factory-board.ts +60 -3
- package/src/package-contracts/reviewer-output.ts +19 -0
- package/src/public-cli/cli.ts +96 -39
- package/src/public-cli/coder-run.ts +11 -4
- package/src/public-cli/collector-run.ts +7 -3
- package/src/public-cli/fixer-run.ts +11 -4
- package/src/public-cli/invocation.ts +183 -102
- package/src/public-cli/judge-run.ts +11 -4
- package/src/public-cli/merger-run.ts +11 -4
- package/src/public-cli/reviewer-run.ts +23 -4
- package/src/public-cli/run-lifecycle.ts +97 -1
- package/src/public-cli/settlement.ts +8 -0
- package/src/reviewer-construction.ts +64 -7
- package/src/reviewer-dispatch.ts +81 -2
- package/src/reviewer-execution-ledger.ts +2 -1
- package/src/reviewer-pinned-git.ts +43 -0
- package/src/reviewer-role.ts +143 -132
- package/src/reviewer-settlement.ts +4 -0
- package/src/role-runtime.ts +186 -3
- package/src/ticket-frontmatter.ts +94 -0
- package/src/ticket-trajectory.ts +145 -5
|
@@ -211,8 +211,9 @@ async function dispatchAdmittedCollector(input: {
|
|
|
211
211
|
PI_CODING_AGENT_DIR: env.agentDir,
|
|
212
212
|
AK_ROLE_RUN_DIR: admitted.runDirectory,
|
|
213
213
|
};
|
|
214
|
-
|
|
215
|
-
|
|
214
|
+
const correlationId = admitted.correlationId ?? env.correlationId;
|
|
215
|
+
if (correlationId !== undefined && correlationId.trim() !== "") {
|
|
216
|
+
childEnv.AK_CORRELATION_ID = correlationId;
|
|
216
217
|
}
|
|
217
218
|
|
|
218
219
|
let result: ExplicitInternalPiResult;
|
|
@@ -368,7 +369,10 @@ export async function runPublicCollector(
|
|
|
368
369
|
|
|
369
370
|
return await dispatchAdmittedCollector({
|
|
370
371
|
admitted,
|
|
371
|
-
env
|
|
372
|
+
env: {
|
|
373
|
+
...env,
|
|
374
|
+
...(admitted.correlationId === undefined ? {} : { correlationId: admitted.correlationId }),
|
|
375
|
+
},
|
|
372
376
|
io,
|
|
373
377
|
extraArgs,
|
|
374
378
|
lease,
|
|
@@ -312,8 +312,9 @@ async function dispatchAdmittedFixer(input: {
|
|
|
312
312
|
PI_CODING_AGENT_DIR: env.agentDir,
|
|
313
313
|
AK_ROLE_RUN_DIR: admitted.runDirectory,
|
|
314
314
|
};
|
|
315
|
-
|
|
316
|
-
|
|
315
|
+
const correlationId = admitted.correlationId ?? env.correlationId;
|
|
316
|
+
if (correlationId !== undefined && correlationId.trim() !== "") {
|
|
317
|
+
childEnv.AK_CORRELATION_ID = correlationId;
|
|
317
318
|
}
|
|
318
319
|
|
|
319
320
|
let result: ExplicitInternalPiResult;
|
|
@@ -507,7 +508,10 @@ export async function runPublicFixer(
|
|
|
507
508
|
|
|
508
509
|
return await dispatchAdmittedFixer({
|
|
509
510
|
admitted,
|
|
510
|
-
env
|
|
511
|
+
env: {
|
|
512
|
+
...env,
|
|
513
|
+
...(admitted.correlationId === undefined ? {} : { correlationId: admitted.correlationId }),
|
|
514
|
+
},
|
|
511
515
|
io,
|
|
512
516
|
extraArgs,
|
|
513
517
|
lease,
|
|
@@ -593,7 +597,10 @@ export async function runPublicFixerResume(
|
|
|
593
597
|
|
|
594
598
|
return await dispatchAdmittedFixer({
|
|
595
599
|
admitted,
|
|
596
|
-
env
|
|
600
|
+
env: {
|
|
601
|
+
...env,
|
|
602
|
+
...(admitted.correlationId === undefined ? {} : { correlationId: admitted.correlationId }),
|
|
603
|
+
},
|
|
597
604
|
io,
|
|
598
605
|
extraArgs,
|
|
599
606
|
lease,
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
} from "../activation-ledger-topology.ts";
|
|
21
21
|
import { resolveBookKeyFromGit } from "../activation-ledger-git.ts";
|
|
22
22
|
import { roleRunSessionCoordinates } from "../sitian-role-run-coordinates.ts";
|
|
23
|
+
import { resolveTicketNumberFromAttachmentBodies } from "../ticket-frontmatter.ts";
|
|
23
24
|
import {
|
|
24
25
|
loadDoctorCase,
|
|
25
26
|
} from "../doctor-evidence.ts";
|
|
@@ -73,6 +74,16 @@ export type AdmittedRoleInvocationBase = {
|
|
|
73
74
|
/** Exact Pi session file principal (bound at admission; reopened on resume). */
|
|
74
75
|
readonly sessionFile: string;
|
|
75
76
|
readonly admittedRequestPath: string;
|
|
77
|
+
/**
|
|
78
|
+
* Optional opaque invocation correlation restored from a prior admitted page
|
|
79
|
+
* (ADR 0049 host channel). Admission does not mint ticket-binding ids.
|
|
80
|
+
*/
|
|
81
|
+
readonly correlationId?: string;
|
|
82
|
+
/**
|
|
83
|
+
* Typed ticket face from frozen attachment frontmatter (`ticketNumber`).
|
|
84
|
+
* Absent when no attachment carries a valid contract field (unbound).
|
|
85
|
+
*/
|
|
86
|
+
readonly ticketNumber?: number;
|
|
76
87
|
};
|
|
77
88
|
|
|
78
89
|
export type AdmittedJudgeInvocation = AdmittedRoleInvocationBase & {
|
|
@@ -123,6 +134,11 @@ export type AdmittedReviewerInvocation = AdmittedRoleInvocationBase & {
|
|
|
123
134
|
readonly role: "reviewer";
|
|
124
135
|
/** Required fixed base revision for the pinned review target (ADR 0037). */
|
|
125
136
|
readonly baseRevision: string;
|
|
137
|
+
/**
|
|
138
|
+
* Optional durable authority references/URLs frozen at admission.
|
|
139
|
+
* Spec evidence-child material only — never Standards, never invocation prose promotion.
|
|
140
|
+
*/
|
|
141
|
+
readonly authorityRefs: readonly string[];
|
|
126
142
|
};
|
|
127
143
|
|
|
128
144
|
/** Mechanical envelope derived from the active ordinary two-parent merge. */
|
|
@@ -153,7 +169,7 @@ export type AdmittedRoleInvocation =
|
|
|
153
169
|
|
|
154
170
|
type RoleInvocationLedgerSource = Pick<
|
|
155
171
|
AdmittedRoleInvocationBase,
|
|
156
|
-
"runId" | "bookKey" | "projectRoot" | "runDirectory" | "sessionDirectory" | "sessionFile"
|
|
172
|
+
"runId" | "bookKey" | "projectRoot" | "runDirectory" | "sessionDirectory" | "sessionFile" | "correlationId" | "ticketNumber"
|
|
157
173
|
>;
|
|
158
174
|
|
|
159
175
|
/**
|
|
@@ -173,6 +189,8 @@ async function writeRoleInvocationLedger(
|
|
|
173
189
|
runDirectory: source.runDirectory,
|
|
174
190
|
sessionDirectory: source.sessionDirectory,
|
|
175
191
|
sessionFile: source.sessionFile,
|
|
192
|
+
...(source.correlationId === undefined ? {} : { correlationId: source.correlationId }),
|
|
193
|
+
...(source.ticketNumber === undefined ? {} : { ticketNumber: source.ticketNumber }),
|
|
176
194
|
};
|
|
177
195
|
await writeFile(
|
|
178
196
|
join(source.runDirectory, "invocation.json"),
|
|
@@ -305,6 +323,8 @@ export type ParseReviewerArgvResult = {
|
|
|
305
323
|
attachmentPaths: string[];
|
|
306
324
|
/** Required fixed base revision for the pinned review target. */
|
|
307
325
|
baseRevision: string;
|
|
326
|
+
/** Repeatable durable authority references/URLs (exact order preserved). */
|
|
327
|
+
authorityRefs: string[];
|
|
308
328
|
project?: string;
|
|
309
329
|
};
|
|
310
330
|
|
|
@@ -340,6 +360,25 @@ function requireOptionPath(
|
|
|
340
360
|
return value;
|
|
341
361
|
}
|
|
342
362
|
|
|
363
|
+
/**
|
|
364
|
+
* Public --authority-ref admission grammar (refs-only).
|
|
365
|
+
* Unique owner for fresh argv and durable resume restore — no string-only parallel.
|
|
366
|
+
* Accepts durable reference tokens as-is; rejects blank and inline Spec prose
|
|
367
|
+
* (whitespace-bearing sentences). Does not fetch, normalize, or judge content.
|
|
368
|
+
*/
|
|
369
|
+
export function requireAuthorityRef(value: string | undefined): string {
|
|
370
|
+
if (value === undefined || value.trim() === "") {
|
|
371
|
+
throw new CliUsageError("--authority-ref requires a nonempty durable reference");
|
|
372
|
+
}
|
|
373
|
+
// Spec prose sentences contain whitespace; durable public refs are single tokens.
|
|
374
|
+
if (/\s/.test(value)) {
|
|
375
|
+
throw new CliUsageError(
|
|
376
|
+
"--authority-ref requires a durable reference, not inline Spec prose",
|
|
377
|
+
);
|
|
378
|
+
}
|
|
379
|
+
return value;
|
|
380
|
+
}
|
|
381
|
+
|
|
343
382
|
/**
|
|
344
383
|
* Parse Judge-specific argv after the `judge` token.
|
|
345
384
|
* Rejects any public burden selector/hint and unknown flags.
|
|
@@ -525,7 +564,7 @@ async function freezeRegularFileAttachment(
|
|
|
525
564
|
sourcePath: string,
|
|
526
565
|
destinationDir: string,
|
|
527
566
|
index: number,
|
|
528
|
-
): Promise<FrozenAttachment> {
|
|
567
|
+
): Promise<{ attachment: FrozenAttachment; body: Buffer }> {
|
|
529
568
|
const absolute = isAbsolute(sourcePath) ? sourcePath : resolve(sourcePath);
|
|
530
569
|
let st;
|
|
531
570
|
try {
|
|
@@ -546,14 +585,49 @@ async function freezeRegularFileAttachment(
|
|
|
546
585
|
const frozenPath = join(destinationDir, name);
|
|
547
586
|
await writeFile(frozenPath, bytes);
|
|
548
587
|
return {
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
588
|
+
attachment: {
|
|
589
|
+
provenancePath: absolute,
|
|
590
|
+
frozenPath,
|
|
591
|
+
byteLength: bytes.byteLength,
|
|
592
|
+
sha256: sha256Hex(bytes),
|
|
593
|
+
mediaKind: "regular-file",
|
|
594
|
+
},
|
|
595
|
+
body: bytes,
|
|
554
596
|
};
|
|
555
597
|
}
|
|
556
598
|
|
|
599
|
+
/** Freeze attachments and resolve typed ticketNumber from frozen bodies (bind-if-present). */
|
|
600
|
+
async function freezeAttachmentsWithTicketNumber(
|
|
601
|
+
attachmentPaths: readonly string[],
|
|
602
|
+
attachmentsDirectory: string,
|
|
603
|
+
): Promise<{
|
|
604
|
+
readonly attachments: FrozenAttachment[];
|
|
605
|
+
readonly ticketNumber?: number;
|
|
606
|
+
}> {
|
|
607
|
+
const attachments: FrozenAttachment[] = [];
|
|
608
|
+
const bodies: Buffer[] = [];
|
|
609
|
+
for (let i = 0; i < attachmentPaths.length; i += 1) {
|
|
610
|
+
const frozen = await freezeRegularFileAttachment(
|
|
611
|
+
attachmentPaths[i]!,
|
|
612
|
+
attachmentsDirectory,
|
|
613
|
+
i,
|
|
614
|
+
);
|
|
615
|
+
attachments.push(frozen.attachment);
|
|
616
|
+
bodies.push(frozen.body);
|
|
617
|
+
}
|
|
618
|
+
const ticketNumber = resolveTicketNumberFromAttachmentBodies(bodies);
|
|
619
|
+
return {
|
|
620
|
+
attachments,
|
|
621
|
+
...(ticketNumber === undefined ? {} : { ticketNumber }),
|
|
622
|
+
};
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
function ticketAdmissionFields(
|
|
626
|
+
ticketNumber: number | undefined,
|
|
627
|
+
): { ticketNumber?: number } {
|
|
628
|
+
return ticketNumber === undefined ? {} : { ticketNumber };
|
|
629
|
+
}
|
|
630
|
+
|
|
557
631
|
export type AdmitJudgeInvocationOptions = {
|
|
558
632
|
home: string;
|
|
559
633
|
cwd: string;
|
|
@@ -583,16 +657,11 @@ export async function admitJudgeInvocation(
|
|
|
583
657
|
ensureRealDirectoryTree(ledgerHome, sessionDirectory);
|
|
584
658
|
ensureRealDirectoryTree(ledgerHome, attachmentsDirectory);
|
|
585
659
|
|
|
586
|
-
const attachments
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
attachmentsDirectory,
|
|
592
|
-
i,
|
|
593
|
-
),
|
|
594
|
-
);
|
|
595
|
-
}
|
|
660
|
+
const { attachments, ticketNumber } = await freezeAttachmentsWithTicketNumber(
|
|
661
|
+
options.attachmentPaths,
|
|
662
|
+
attachmentsDirectory,
|
|
663
|
+
);
|
|
664
|
+
const ticketFields = ticketAdmissionFields(ticketNumber);
|
|
596
665
|
|
|
597
666
|
const instruction = options.instruction;
|
|
598
667
|
const instructionEmpty = instruction.trim() === "";
|
|
@@ -604,6 +673,7 @@ export async function admitJudgeInvocation(
|
|
|
604
673
|
runDirectory,
|
|
605
674
|
sessionDirectory,
|
|
606
675
|
sessionFile,
|
|
676
|
+
...ticketFields,
|
|
607
677
|
instruction,
|
|
608
678
|
instructionEmpty,
|
|
609
679
|
attachments: attachments.map((a) => ({
|
|
@@ -630,6 +700,7 @@ export async function admitJudgeInvocation(
|
|
|
630
700
|
sessionDirectory,
|
|
631
701
|
sessionFile,
|
|
632
702
|
admittedRequestPath,
|
|
703
|
+
...ticketFields,
|
|
633
704
|
};
|
|
634
705
|
}
|
|
635
706
|
|
|
@@ -721,16 +792,11 @@ export async function admitCoderInvocation(
|
|
|
721
792
|
ensureRealDirectoryTree(ledgerHome, sessionDirectory);
|
|
722
793
|
ensureRealDirectoryTree(ledgerHome, attachmentsDirectory);
|
|
723
794
|
|
|
724
|
-
const attachments
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
attachmentsDirectory,
|
|
730
|
-
i,
|
|
731
|
-
),
|
|
732
|
-
);
|
|
733
|
-
}
|
|
795
|
+
const { attachments, ticketNumber } = await freezeAttachmentsWithTicketNumber(
|
|
796
|
+
options.attachmentPaths,
|
|
797
|
+
attachmentsDirectory,
|
|
798
|
+
);
|
|
799
|
+
const ticketFields = ticketAdmissionFields(ticketNumber);
|
|
734
800
|
|
|
735
801
|
const taskPath = join(runDirectory, "task.md");
|
|
736
802
|
await writeFile(taskPath, instruction, "utf8");
|
|
@@ -744,6 +810,7 @@ export async function admitCoderInvocation(
|
|
|
744
810
|
runDirectory,
|
|
745
811
|
sessionDirectory,
|
|
746
812
|
sessionFile,
|
|
813
|
+
...ticketFields,
|
|
747
814
|
instruction,
|
|
748
815
|
instructionEmpty: false,
|
|
749
816
|
taskPath,
|
|
@@ -773,6 +840,7 @@ export async function admitCoderInvocation(
|
|
|
773
840
|
sessionFile,
|
|
774
841
|
admittedRequestPath,
|
|
775
842
|
taskPath,
|
|
843
|
+
...ticketFields,
|
|
776
844
|
};
|
|
777
845
|
}
|
|
778
846
|
|
|
@@ -828,34 +896,15 @@ export async function admitFixerInvocation(
|
|
|
828
896
|
throw new CliUsageError("fixer phase must be plan or apply");
|
|
829
897
|
}
|
|
830
898
|
|
|
831
|
-
|
|
832
|
-
const runId = (options.createRunId ?? uuidv7)();
|
|
833
|
-
const { ledgerHome, bookKey, runDirectory, sessionDirectory, sessionFile } =
|
|
834
|
-
roleRunSessionCoordinates({ cwd: projectRoot, runId, role: "fixer", home: options.home });
|
|
835
|
-
const attachmentsDirectory = join(runDirectory, "attachments");
|
|
836
|
-
ensureRealDirectoryTree(ledgerHome, sessionDirectory);
|
|
837
|
-
ensureRealDirectoryTree(ledgerHome, attachmentsDirectory);
|
|
838
|
-
|
|
839
|
-
const attachments: FrozenAttachment[] = [];
|
|
840
|
-
for (let i = 0; i < options.attachmentPaths.length; i += 1) {
|
|
841
|
-
attachments.push(
|
|
842
|
-
await freezeRegularFileAttachment(
|
|
843
|
-
options.attachmentPaths[i]!,
|
|
844
|
-
attachmentsDirectory,
|
|
845
|
-
i,
|
|
846
|
-
),
|
|
847
|
-
);
|
|
848
|
-
}
|
|
849
|
-
|
|
899
|
+
// Validate/read prerequisites before freezing request materials.
|
|
850
900
|
let prerequisites: readonly FixerPrerequisite[] = Object.freeze([]);
|
|
851
|
-
let
|
|
901
|
+
let prerequisitesSource: string | undefined;
|
|
852
902
|
if (options.prerequisitesPath !== undefined) {
|
|
853
903
|
const absolutePrereq = isAbsolute(options.prerequisitesPath)
|
|
854
904
|
? options.prerequisitesPath
|
|
855
905
|
: resolve(options.prerequisitesPath);
|
|
856
|
-
let source: string;
|
|
857
906
|
try {
|
|
858
|
-
|
|
907
|
+
prerequisitesSource = await readFile(absolutePrereq, "utf8");
|
|
859
908
|
} catch (error) {
|
|
860
909
|
throw new CliUsageError(
|
|
861
910
|
`fixer prerequisites path is unreadable: ${options.prerequisitesPath}`,
|
|
@@ -863,13 +912,31 @@ export async function admitFixerInvocation(
|
|
|
863
912
|
);
|
|
864
913
|
}
|
|
865
914
|
try {
|
|
866
|
-
prerequisites = parseFixerPrerequisites(
|
|
915
|
+
prerequisites = parseFixerPrerequisites(prerequisitesSource);
|
|
867
916
|
} catch (error) {
|
|
868
917
|
if (error instanceof FixerPacketValidationError) {
|
|
869
918
|
throw new CliUsageError(error.message, { cause: error });
|
|
870
919
|
}
|
|
871
920
|
throw error;
|
|
872
921
|
}
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
const projectRoot = resolve(options.project ?? options.cwd);
|
|
925
|
+
const runId = (options.createRunId ?? uuidv7)();
|
|
926
|
+
const { ledgerHome, bookKey, runDirectory, sessionDirectory, sessionFile } =
|
|
927
|
+
roleRunSessionCoordinates({ cwd: projectRoot, runId, role: "fixer", home: options.home });
|
|
928
|
+
const attachmentsDirectory = join(runDirectory, "attachments");
|
|
929
|
+
ensureRealDirectoryTree(ledgerHome, sessionDirectory);
|
|
930
|
+
ensureRealDirectoryTree(ledgerHome, attachmentsDirectory);
|
|
931
|
+
|
|
932
|
+
const { attachments, ticketNumber } = await freezeAttachmentsWithTicketNumber(
|
|
933
|
+
options.attachmentPaths,
|
|
934
|
+
attachmentsDirectory,
|
|
935
|
+
);
|
|
936
|
+
const ticketFields = ticketAdmissionFields(ticketNumber);
|
|
937
|
+
|
|
938
|
+
let prerequisitesPath: string | undefined;
|
|
939
|
+
if (prerequisitesSource !== undefined) {
|
|
873
940
|
prerequisitesPath = join(runDirectory, "prerequisites.json");
|
|
874
941
|
await writeFile(
|
|
875
942
|
prerequisitesPath,
|
|
@@ -890,6 +957,7 @@ export async function admitFixerInvocation(
|
|
|
890
957
|
runDirectory,
|
|
891
958
|
sessionDirectory,
|
|
892
959
|
sessionFile,
|
|
960
|
+
...ticketFields,
|
|
893
961
|
instruction,
|
|
894
962
|
instructionEmpty: false,
|
|
895
963
|
packetPath,
|
|
@@ -926,6 +994,7 @@ export async function admitFixerInvocation(
|
|
|
926
994
|
packetPath,
|
|
927
995
|
...(prerequisitesPath === undefined ? {} : { prerequisitesPath }),
|
|
928
996
|
prerequisites,
|
|
997
|
+
...ticketFields,
|
|
929
998
|
};
|
|
930
999
|
}
|
|
931
1000
|
|
|
@@ -1103,6 +1172,19 @@ export async function admitCollectorInvocation(
|
|
|
1103
1172
|
repository = resolveGitHubRemoteRepository(projectRoot);
|
|
1104
1173
|
}
|
|
1105
1174
|
|
|
1175
|
+
// Validate optional request-manifest before freezing request materials.
|
|
1176
|
+
let manifest = emptyCollectorManifest();
|
|
1177
|
+
let manifestCanonicalJson: string | undefined;
|
|
1178
|
+
if (options.requestManifestPath !== undefined) {
|
|
1179
|
+
try {
|
|
1180
|
+
manifest = await loadCollectorManifest(options.requestManifestPath);
|
|
1181
|
+
manifestCanonicalJson = manifest.canonicalJson;
|
|
1182
|
+
} catch (error) {
|
|
1183
|
+
throw new CliUsageError(error instanceof Error ? error.message : String(error), { cause: error });
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
const manifestDigest = manifest.digest;
|
|
1187
|
+
|
|
1106
1188
|
const runId = (options.createRunId ?? uuidv7)();
|
|
1107
1189
|
const { ledgerHome, bookKey, runDirectory, sessionDirectory, sessionFile } =
|
|
1108
1190
|
roleRunSessionCoordinates({ cwd: projectRoot, runId, role: "collector", home: options.home });
|
|
@@ -1110,30 +1192,17 @@ export async function admitCollectorInvocation(
|
|
|
1110
1192
|
ensureRealDirectoryTree(ledgerHome, sessionDirectory);
|
|
1111
1193
|
ensureRealDirectoryTree(ledgerHome, attachmentsDirectory);
|
|
1112
1194
|
|
|
1113
|
-
const attachments
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
attachmentPaths[i]!,
|
|
1119
|
-
attachmentsDirectory,
|
|
1120
|
-
i,
|
|
1121
|
-
),
|
|
1122
|
-
);
|
|
1123
|
-
}
|
|
1195
|
+
const { attachments, ticketNumber } = await freezeAttachmentsWithTicketNumber(
|
|
1196
|
+
options.attachmentPaths ?? [],
|
|
1197
|
+
attachmentsDirectory,
|
|
1198
|
+
);
|
|
1199
|
+
const ticketFields = ticketAdmissionFields(ticketNumber);
|
|
1124
1200
|
|
|
1125
|
-
let manifest = emptyCollectorManifest();
|
|
1126
1201
|
let requestManifestPath: string | undefined;
|
|
1127
|
-
if (
|
|
1128
|
-
try {
|
|
1129
|
-
manifest = await loadCollectorManifest(options.requestManifestPath);
|
|
1130
|
-
} catch (error) {
|
|
1131
|
-
throw new CliUsageError(error instanceof Error ? error.message : String(error), { cause: error });
|
|
1132
|
-
}
|
|
1202
|
+
if (manifestCanonicalJson !== undefined) {
|
|
1133
1203
|
requestManifestPath = join(runDirectory, "request-manifest.json");
|
|
1134
|
-
await writeFile(requestManifestPath,
|
|
1204
|
+
await writeFile(requestManifestPath, manifestCanonicalJson, "utf8");
|
|
1135
1205
|
}
|
|
1136
|
-
const manifestDigest = manifest.digest;
|
|
1137
1206
|
|
|
1138
1207
|
const instruction = options.instruction ?? "";
|
|
1139
1208
|
const instructionEmpty = instruction.trim() === "";
|
|
@@ -1145,6 +1214,7 @@ export async function admitCollectorInvocation(
|
|
|
1145
1214
|
runDirectory,
|
|
1146
1215
|
sessionDirectory,
|
|
1147
1216
|
sessionFile,
|
|
1217
|
+
...ticketFields,
|
|
1148
1218
|
instruction,
|
|
1149
1219
|
instructionEmpty,
|
|
1150
1220
|
prNumber,
|
|
@@ -1184,6 +1254,7 @@ export async function admitCollectorInvocation(
|
|
|
1184
1254
|
repository,
|
|
1185
1255
|
...(requestManifestPath === undefined ? {} : { requestManifestPath }),
|
|
1186
1256
|
manifestDigest,
|
|
1257
|
+
...ticketFields,
|
|
1187
1258
|
};
|
|
1188
1259
|
}
|
|
1189
1260
|
|
|
@@ -1462,17 +1533,11 @@ export async function admitDoctorInvocation(
|
|
|
1462
1533
|
ensureRealDirectoryTree(ledgerHome, sessionDirectory);
|
|
1463
1534
|
ensureRealDirectoryTree(ledgerHome, attachmentsDirectory);
|
|
1464
1535
|
|
|
1465
|
-
const attachments
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
attachmentPaths[i]!,
|
|
1471
|
-
attachmentsDirectory,
|
|
1472
|
-
i,
|
|
1473
|
-
),
|
|
1474
|
-
);
|
|
1475
|
-
}
|
|
1536
|
+
const { attachments, ticketNumber } = await freezeAttachmentsWithTicketNumber(
|
|
1537
|
+
options.attachmentPaths ?? [],
|
|
1538
|
+
attachmentsDirectory,
|
|
1539
|
+
);
|
|
1540
|
+
const ticketFields = ticketAdmissionFields(ticketNumber);
|
|
1476
1541
|
|
|
1477
1542
|
const instruction = options.instruction ?? "";
|
|
1478
1543
|
const instructionEmpty = instruction.trim() === "";
|
|
@@ -1484,6 +1549,7 @@ export async function admitDoctorInvocation(
|
|
|
1484
1549
|
runDirectory,
|
|
1485
1550
|
sessionDirectory,
|
|
1486
1551
|
sessionFile,
|
|
1552
|
+
...ticketFields,
|
|
1487
1553
|
instruction,
|
|
1488
1554
|
instructionEmpty,
|
|
1489
1555
|
issueNumber: options.issueNumber,
|
|
@@ -1520,6 +1586,7 @@ export async function admitDoctorInvocation(
|
|
|
1520
1586
|
issueNumber: options.issueNumber,
|
|
1521
1587
|
caseRunsPath,
|
|
1522
1588
|
caseIdentity,
|
|
1589
|
+
...ticketFields,
|
|
1523
1590
|
};
|
|
1524
1591
|
}
|
|
1525
1592
|
|
|
@@ -1540,13 +1607,15 @@ export function buildDoctorTransportPrompt(
|
|
|
1540
1607
|
|
|
1541
1608
|
/**
|
|
1542
1609
|
* Parse Reviewer-specific argv after the `reviewer` token.
|
|
1543
|
-
* Public flags: --project
|
|
1610
|
+
* Public flags: --project, required --base, optional repeatable --authority-ref.
|
|
1544
1611
|
* Reviewer gathers its own evidence; users submit neither attachments nor capability packets.
|
|
1612
|
+
* Caller instruction remains scope/procedure provenance — not Spec authority.
|
|
1545
1613
|
*/
|
|
1546
1614
|
export function parseReviewerArgv(
|
|
1547
1615
|
args: readonly string[],
|
|
1548
1616
|
): ParseReviewerArgvResult {
|
|
1549
1617
|
const attachmentPaths: string[] = [];
|
|
1618
|
+
const authorityRefs: string[] = [];
|
|
1550
1619
|
let project: string | undefined;
|
|
1551
1620
|
let baseRevision: string | undefined;
|
|
1552
1621
|
const positional: string[] = [];
|
|
@@ -1574,6 +1643,14 @@ export function parseReviewerArgv(
|
|
|
1574
1643
|
baseRevision = requireOptionPath("--base", token.slice("--base=".length));
|
|
1575
1644
|
continue;
|
|
1576
1645
|
}
|
|
1646
|
+
if (token === "--authority-ref") {
|
|
1647
|
+
authorityRefs.push(requireAuthorityRef(tokens.shift()));
|
|
1648
|
+
continue;
|
|
1649
|
+
}
|
|
1650
|
+
if (token.startsWith("--authority-ref=")) {
|
|
1651
|
+
authorityRefs.push(requireAuthorityRef(token.slice("--authority-ref=".length)));
|
|
1652
|
+
continue;
|
|
1653
|
+
}
|
|
1577
1654
|
if (token.startsWith("-") && token !== "-") {
|
|
1578
1655
|
throw new CliUsageError(`unknown reviewer option: ${token}`);
|
|
1579
1656
|
}
|
|
@@ -1587,6 +1664,7 @@ export function parseReviewerArgv(
|
|
|
1587
1664
|
instruction: positional.join(" "),
|
|
1588
1665
|
attachmentPaths,
|
|
1589
1666
|
baseRevision,
|
|
1667
|
+
authorityRefs,
|
|
1590
1668
|
...(project === undefined ? {} : { project }),
|
|
1591
1669
|
};
|
|
1592
1670
|
}
|
|
@@ -1598,6 +1676,8 @@ export type AdmitReviewerInvocationOptions = {
|
|
|
1598
1676
|
instruction: string;
|
|
1599
1677
|
attachmentPaths: readonly string[];
|
|
1600
1678
|
baseRevision: string;
|
|
1679
|
+
/** Optional durable authority references/URLs; frozen unchanged at admission. */
|
|
1680
|
+
authorityRefs?: readonly string[];
|
|
1601
1681
|
project?: string;
|
|
1602
1682
|
createRunId?: () => string;
|
|
1603
1683
|
};
|
|
@@ -1605,6 +1685,7 @@ export type AdmitReviewerInvocationOptions = {
|
|
|
1605
1685
|
/**
|
|
1606
1686
|
* Admit a Reviewer Role run on the fixed base only.
|
|
1607
1687
|
* Caller instruction is optional provenance; Reviewer acquires issue/authority independently.
|
|
1688
|
+
* Optional authorityRefs are frozen as durable references only — not Spec prose.
|
|
1608
1689
|
*/
|
|
1609
1690
|
export async function admitReviewerInvocation(
|
|
1610
1691
|
options: AdmitReviewerInvocationOptions,
|
|
@@ -1615,6 +1696,9 @@ export async function admitReviewerInvocation(
|
|
|
1615
1696
|
if (options.baseRevision.trim() === "") {
|
|
1616
1697
|
throw new CliUsageError("--base requires a nonempty revision");
|
|
1617
1698
|
}
|
|
1699
|
+
const authorityRefs = Object.freeze(
|
|
1700
|
+
(options.authorityRefs ?? []).map((ref) => requireAuthorityRef(ref)),
|
|
1701
|
+
);
|
|
1618
1702
|
|
|
1619
1703
|
const projectRoot = resolve(options.project ?? options.cwd);
|
|
1620
1704
|
const runId = (options.createRunId ?? uuidv7)();
|
|
@@ -1625,16 +1709,11 @@ export async function admitReviewerInvocation(
|
|
|
1625
1709
|
ensureRealDirectoryTree(ledgerHome, attachmentsDirectory);
|
|
1626
1710
|
|
|
1627
1711
|
// Public parse already rejects attachments; keep freeze loop for structural symmetry.
|
|
1628
|
-
const attachments
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
attachmentsDirectory,
|
|
1634
|
-
i,
|
|
1635
|
-
),
|
|
1636
|
-
);
|
|
1637
|
-
}
|
|
1712
|
+
const { attachments, ticketNumber } = await freezeAttachmentsWithTicketNumber(
|
|
1713
|
+
options.attachmentPaths,
|
|
1714
|
+
attachmentsDirectory,
|
|
1715
|
+
);
|
|
1716
|
+
const ticketFields = ticketAdmissionFields(ticketNumber);
|
|
1638
1717
|
|
|
1639
1718
|
const instruction = options.instruction;
|
|
1640
1719
|
const instructionEmpty = instruction.trim() === "";
|
|
@@ -1646,9 +1725,11 @@ export async function admitReviewerInvocation(
|
|
|
1646
1725
|
runDirectory,
|
|
1647
1726
|
sessionDirectory,
|
|
1648
1727
|
sessionFile,
|
|
1728
|
+
...ticketFields,
|
|
1649
1729
|
instruction,
|
|
1650
1730
|
instructionEmpty,
|
|
1651
1731
|
baseRevision: options.baseRevision,
|
|
1732
|
+
authorityRefs: [...authorityRefs],
|
|
1652
1733
|
attachments: attachments.map((a) => ({
|
|
1653
1734
|
provenancePath: a.provenancePath,
|
|
1654
1735
|
frozenPath: a.frozenPath,
|
|
@@ -1678,6 +1759,8 @@ export async function admitReviewerInvocation(
|
|
|
1678
1759
|
sessionFile,
|
|
1679
1760
|
admittedRequestPath,
|
|
1680
1761
|
baseRevision: options.baseRevision,
|
|
1762
|
+
authorityRefs,
|
|
1763
|
+
...ticketFields,
|
|
1681
1764
|
};
|
|
1682
1765
|
}
|
|
1683
1766
|
|
|
@@ -1845,16 +1928,11 @@ export async function admitMergerInvocation(
|
|
|
1845
1928
|
ensureRealDirectoryTree(ledgerHome, sessionDirectory);
|
|
1846
1929
|
ensureRealDirectoryTree(ledgerHome, attachmentsDirectory);
|
|
1847
1930
|
|
|
1848
|
-
const attachments
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
attachmentsDirectory,
|
|
1854
|
-
i,
|
|
1855
|
-
),
|
|
1856
|
-
);
|
|
1857
|
-
}
|
|
1931
|
+
const { attachments, ticketNumber } = await freezeAttachmentsWithTicketNumber(
|
|
1932
|
+
options.attachmentPaths,
|
|
1933
|
+
attachmentsDirectory,
|
|
1934
|
+
);
|
|
1935
|
+
const ticketFields = ticketAdmissionFields(ticketNumber);
|
|
1858
1936
|
|
|
1859
1937
|
// Intent materials seed primary-source investigation; the method owns the work.
|
|
1860
1938
|
const targetIntent = mergerMaterialFromUtf8(
|
|
@@ -1866,6 +1944,7 @@ export async function admitMergerInvocation(
|
|
|
1866
1944
|
const taskMaterial = mergerMaterialFromUtf8(instruction);
|
|
1867
1945
|
const authorityMaterial = mergerMaterialFromUtf8(instruction);
|
|
1868
1946
|
|
|
1947
|
+
// Validate merger envelope before placing admitted identity.
|
|
1869
1948
|
const mergerInput = validateMergerInput({
|
|
1870
1949
|
version: 1,
|
|
1871
1950
|
attemptId: runId,
|
|
@@ -1898,6 +1977,7 @@ export async function admitMergerInvocation(
|
|
|
1898
1977
|
runDirectory,
|
|
1899
1978
|
sessionDirectory,
|
|
1900
1979
|
sessionFile,
|
|
1980
|
+
...ticketFields,
|
|
1901
1981
|
instruction,
|
|
1902
1982
|
instructionEmpty: false,
|
|
1903
1983
|
mergerInputPath,
|
|
@@ -1938,6 +2018,7 @@ export async function admitMergerInvocation(
|
|
|
1938
2018
|
admittedRequestPath,
|
|
1939
2019
|
mergerInputPath,
|
|
1940
2020
|
derived: admitted.derived,
|
|
2021
|
+
...ticketFields,
|
|
1941
2022
|
};
|
|
1942
2023
|
}
|
|
1943
2024
|
|
|
@@ -289,8 +289,9 @@ async function dispatchAdmittedJudge(input: {
|
|
|
289
289
|
// and role-runtime can record typed provider HTTP observations.
|
|
290
290
|
AK_ROLE_RUN_DIR: admitted.runDirectory,
|
|
291
291
|
};
|
|
292
|
-
|
|
293
|
-
|
|
292
|
+
const correlationId = admitted.correlationId ?? env.correlationId;
|
|
293
|
+
if (correlationId !== undefined && correlationId.trim() !== "") {
|
|
294
|
+
childEnv.AK_CORRELATION_ID = correlationId;
|
|
294
295
|
}
|
|
295
296
|
|
|
296
297
|
let result: ExplicitInternalPiResult;
|
|
@@ -450,7 +451,10 @@ export async function runPublicJudge(
|
|
|
450
451
|
|
|
451
452
|
return await dispatchAdmittedJudge({
|
|
452
453
|
admitted,
|
|
453
|
-
env
|
|
454
|
+
env: {
|
|
455
|
+
...env,
|
|
456
|
+
...(admitted.correlationId === undefined ? {} : { correlationId: admitted.correlationId }),
|
|
457
|
+
},
|
|
454
458
|
io,
|
|
455
459
|
extraArgs,
|
|
456
460
|
lease,
|
|
@@ -520,7 +524,10 @@ export async function runPublicResume(
|
|
|
520
524
|
|
|
521
525
|
return await dispatchAdmittedJudge({
|
|
522
526
|
admitted,
|
|
523
|
-
env
|
|
527
|
+
env: {
|
|
528
|
+
...env,
|
|
529
|
+
...(admitted.correlationId === undefined ? {} : { correlationId: admitted.correlationId }),
|
|
530
|
+
},
|
|
524
531
|
io,
|
|
525
532
|
extraArgs,
|
|
526
533
|
lease,
|