@akagilnc/pi-workflow-roles 0.1.3932 → 0.1.3975

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. package/CLAUDE.md +1 -1
  2. package/dist/acp-host/production-host.js +2389 -6018
  3. package/dist/analyst-gate-cycles-read.js +15 -19
  4. package/dist/audit-escalation.js +16 -46
  5. package/dist/auditor-dossier-tool.js +7 -62
  6. package/dist/collector-identity.js +0 -157
  7. package/dist/collector-ledger.js +2 -42
  8. package/dist/compliance-transport.js +40 -14
  9. package/dist/diarist-contracts.js +2 -40
  10. package/dist/doctor-contracts.js +39 -108
  11. package/dist/doctor-evidence.js +1 -5
  12. package/dist/engine-detour-tool.js +1 -1
  13. package/dist/gatekeeper-role.js +49 -38
  14. package/dist/headless-host/production-host.js +4814 -8450
  15. package/dist/host-contracts.js +0 -5
  16. package/dist/merger-contracts.js +4 -6
  17. package/dist/navigator-attendance.js +30 -52
  18. package/dist/navigator-invocation-identity.js +0 -1
  19. package/dist/navigator-public-session.js +2 -1
  20. package/dist/notary-contracts.js +4 -10
  21. package/dist/package-contracts/auditor-output.js +5 -23
  22. package/dist/package-contracts/fixer-output.js +25 -49
  23. package/dist/package-contracts/gatekeeper-output.js +3 -13
  24. package/dist/package-contracts/navigator-output.js +4 -7
  25. package/dist/package-contracts/reviewer-output.js +1 -95
  26. package/dist/package-contracts/terminating-tools.js +33 -144
  27. package/dist/package-contracts/worker-output.js +1 -3
  28. package/dist/public-cli/auto-resume.js +30 -68
  29. package/dist/public-cli/case-dossier-delivery.js +5 -17
  30. package/dist/public-cli/diarist-run.js +9 -4
  31. package/dist/public-cli/inspector-run.js +2 -8
  32. package/dist/public-cli/instruction-seat-run.js +3 -7
  33. package/dist/public-cli/invocation.js +5 -2
  34. package/dist/public-cli/main.js +6068 -6964
  35. package/dist/public-cli/notary-run.js +1 -8
  36. package/dist/public-cli/post-admission.js +314 -113
  37. package/dist/public-cli/run-lifecycle.js +14 -38
  38. package/dist/public-cli/settlement.js +209 -390
  39. package/dist/public-cli/terminal.js +51 -45
  40. package/dist/public-role-summons.js +1 -12
  41. package/dist/reviewer-dispatch.js +12 -258
  42. package/dist/submission-correctable-error.js +0 -12
  43. package/dist/submission-errors.js +6 -1
  44. package/dist/submission-ledger.js +125 -168
  45. package/dist/ticket-provenance-contracts.js +2 -49
  46. package/dist/ticket-provenance.js +82 -31
  47. package/extensions/role-runtime.ts +1 -6
  48. package/package.json +1 -1
  49. package/resources/836-deleted-machine-instruction-inventory.md +18 -0
  50. package/src/acp-host/role-turn-host.ts +8 -3
  51. package/src/analyst-gate-cycles-read.ts +17 -29
  52. package/src/audit-escalation.ts +20 -50
  53. package/src/auditor-dossier-tool.ts +5 -103
  54. package/src/canonical-skill-binding.ts +3 -2
  55. package/src/collector-identity.ts +0 -179
  56. package/src/collector-ledger.ts +3 -46
  57. package/src/collector-role.ts +32 -61
  58. package/src/collector-tool-schemas.ts +20 -14
  59. package/src/compliance-transport.ts +55 -17
  60. package/src/countersign-role.ts +17 -8
  61. package/src/diarist-contracts.ts +3 -36
  62. package/src/diarist-role.ts +13 -7
  63. package/src/diarist.ts +4 -16
  64. package/src/doctor-contracts.ts +73 -94
  65. package/src/doctor-evidence.ts +1 -1
  66. package/src/doctor-role.ts +3 -3
  67. package/src/engine-detour-tool.ts +4 -1
  68. package/src/external-host-turn-loop.ts +9 -3
  69. package/src/gatekeeper-pass-envelope.ts +7 -12
  70. package/src/gatekeeper-role.ts +56 -50
  71. package/src/gleaner-left-role.ts +4 -2
  72. package/src/headless-host/role-turn-host.ts +4 -5
  73. package/src/host-contracts.ts +3 -8
  74. package/src/judge-role.ts +19 -13
  75. package/src/merger-contracts.ts +10 -6
  76. package/src/merger-role.ts +1 -5
  77. package/src/navigator-attendance.ts +37 -74
  78. package/src/navigator-invocation-identity.ts +0 -6
  79. package/src/navigator-public-session.ts +2 -1
  80. package/src/notary-contracts.ts +7 -10
  81. package/src/package-contracts/auditor-output.ts +4 -21
  82. package/src/package-contracts/fixer-output.ts +34 -52
  83. package/src/package-contracts/gatekeeper-output.ts +5 -22
  84. package/src/package-contracts/navigator-output.ts +7 -7
  85. package/src/package-contracts/reviewer-output.ts +2 -150
  86. package/src/package-contracts/terminating-tools.ts +32 -147
  87. package/src/package-contracts/worker-output.ts +0 -1
  88. package/src/pi/adapter.ts +3 -8
  89. package/src/public-cli/auto-resume.ts +41 -94
  90. package/src/public-cli/case-dossier-delivery.ts +5 -15
  91. package/src/public-cli/countersign-run.ts +14 -6
  92. package/src/public-cli/diarist-run.ts +11 -9
  93. package/src/public-cli/inspector-run.ts +2 -18
  94. package/src/public-cli/instruction-seat-run.ts +3 -17
  95. package/src/public-cli/invocation.ts +5 -2
  96. package/src/public-cli/merger-run.ts +1 -1
  97. package/src/public-cli/notary-run.ts +1 -18
  98. package/src/public-cli/post-admission.ts +385 -115
  99. package/src/public-cli/run-lifecycle.ts +13 -44
  100. package/src/public-cli/settlement.ts +314 -562
  101. package/src/public-cli/terminal.ts +66 -72
  102. package/src/public-role-summons.ts +5 -30
  103. package/src/reviewer-dispatch.ts +29 -331
  104. package/src/reviewer-role.ts +16 -83
  105. package/src/role-envelope.ts +16 -24
  106. package/src/role-runtime-dependencies.ts +1 -6
  107. package/src/role-runtime.ts +65 -201
  108. package/src/submission-correctable-error.ts +0 -14
  109. package/src/submission-errors.ts +6 -1
  110. package/src/submission-ledger.ts +187 -187
  111. package/src/ticket-provenance-contracts.ts +4 -60
  112. package/src/ticket-provenance.ts +98 -32
  113. package/src/worker-role.ts +35 -36
  114. package/dist/activation-ledger-session.js +0 -105
  115. package/dist/activation-ledger.js +0 -139
  116. package/dist/activation-trace.js +0 -33
  117. package/dist/atomic-write.js +0 -23
  118. package/dist/auditor-role.js +0 -12
  119. package/dist/canonical-skill-binding.js +0 -61
  120. package/dist/collector-handbook.js +0 -142
  121. package/dist/collector-receipt.js +0 -107
  122. package/dist/collector-role.js +0 -566
  123. package/dist/collector-tool-schemas.js +0 -107
  124. package/dist/countersign-role.js +0 -28
  125. package/dist/diarist-role.js +0 -44
  126. package/dist/diarist.js +0 -66
  127. package/dist/doctor-role.js +0 -75
  128. package/dist/fixer-bash-seatbelt.js +0 -13
  129. package/dist/gatekeeper-pass-envelope.js +0 -77
  130. package/dist/gleaner-left-role.js +0 -26
  131. package/dist/inspector-role.js +0 -29
  132. package/dist/judge-role.js +0 -104
  133. package/dist/merger-role.js +0 -55
  134. package/dist/navigator-role.js +0 -12
  135. package/dist/notary-role.js +0 -134
  136. package/dist/oauth-keepalive.js +0 -158
  137. package/dist/pi/adapter.js +0 -223
  138. package/dist/reviewer-agent.js +0 -122
  139. package/dist/reviewer-child-executor.js +0 -194
  140. package/dist/reviewer-construction.js +0 -103
  141. package/dist/reviewer-execution-ledger.js +0 -166
  142. package/dist/reviewer-failure-diagnostic.js +0 -17
  143. package/dist/reviewer-role.js +0 -159
  144. package/dist/reviewer-scope-prompt.js +0 -21
  145. package/dist/reviewer-settlement.js +0 -66
  146. package/dist/reviewer-workspace.js +0 -132
  147. package/dist/role-runtime.js +0 -1604
  148. package/dist/stderr-jsonl.js +0 -26
  149. package/dist/tool-execution-observation.js +0 -141
  150. package/dist/worker-role.js +0 -345
  151. package/dist/worker-submission-gates.js +0 -305
  152. package/src/collector-receipt.ts +0 -140
  153. package/src/diagnostic-tail.ts +0 -18
  154. package/src/reviewer-agent.ts +0 -135
  155. package/src/reviewer-child-executor.ts +0 -252
  156. package/src/reviewer-construction.ts +0 -195
  157. package/src/reviewer-execution-ledger.ts +0 -212
  158. package/src/reviewer-failure-diagnostic.ts +0 -18
  159. package/src/reviewer-scope-prompt.ts +0 -24
  160. package/src/reviewer-settlement.ts +0 -74
  161. package/src/reviewer-workspace.ts +0 -105
  162. package/src/shape-unreadable-failure.ts +0 -49
@@ -1,23 +0,0 @@
1
- /**
2
- * Same-directory temp + rename atomic file replace.
3
- * Shared primitive for ledger-adjacent typed pages (analyst metrics, etc.).
4
- * Does not open/truncate an existing destination inode, so hard-linked twins
5
- * keep prior bytes until the directory entry is swapped.
6
- * Parent directory must already exist — callers that write under the package
7
- * ledger home own confinement via ensureRealDirectoryTree (ADR 0038).
8
- */
9
- import { randomUUID } from "node:crypto";
10
- import { rename, rm, writeFile } from "node:fs/promises";
11
- import { dirname, join } from "node:path";
12
- export async function writeFileAtomically(destination, contents) {
13
- const parent = dirname(destination);
14
- const temporary = join(parent, `.atomic-write-${randomUUID()}.tmp`);
15
- try {
16
- await writeFile(temporary, contents);
17
- await rename(temporary, destination);
18
- }
19
- catch (error) {
20
- await rm(temporary, { force: true }).catch(() => undefined);
21
- throw error;
22
- }
23
- }
@@ -1,12 +0,0 @@
1
- /**
2
- * Public Auditor (审刑院) role — filed-officer envelope (#675).
3
- */
4
- import { AUDITOR_ACCEPTED_TEXT, AUDITOR_OUTPUT_TOOL_NAME, auditorOutputSchema, } from "./package-contracts/auditor-output.js";
5
- export { AUDITOR_ACCEPTED_TEXT, AUDITOR_OUTPUT_TOOL_NAME };
6
- export const AUDITOR_TOOL_SPEC = {
7
- name: AUDITOR_OUTPUT_TOOL_NAME,
8
- label: "审刑院输出",
9
- description: "审刑院终局回执,状态为 pass、bounce 或 escalate。",
10
- promptSnippet: "审刑院终局回执",
11
- parameters: auditorOutputSchema,
12
- };
@@ -1,61 +0,0 @@
1
- import { readFile, realpath } from "node:fs/promises";
2
- import { homedir } from "node:os";
3
- import { dirname, resolve } from "node:path";
4
- import { stripFrontmatter } from "@earendil-works/pi-coding-agent";
5
- export function captureCanonicalSkillExpansion(name, snapshot, configuredPath, evidence, originalRequest) {
6
- const matchedPath = evidence?.location === configuredPath
7
- ? configuredPath
8
- : evidence?.location === snapshot.path
9
- ? snapshot.path
10
- : undefined;
11
- const expectedContent = matchedPath === undefined
12
- ? undefined
13
- : `References are relative to ${dirname(matchedPath)}.\n\n${snapshot.body}`;
14
- if (evidence?.name !== name
15
- || matchedPath === undefined
16
- || evidence.content !== expectedContent
17
- || evidence.userMessage !== originalRequest) {
18
- return undefined;
19
- }
20
- return Object.freeze({ ...evidence, name });
21
- }
22
- export class CanonicalSkillUnavailableError extends Error {
23
- skillName;
24
- code = "canonical-skill-unavailable";
25
- constructor(skillName, path, cause) {
26
- super(`Canonical ${skillName} Skill is unavailable at ${path}`, { cause });
27
- this.skillName = skillName;
28
- this.name = "CanonicalSkillUnavailableError";
29
- }
30
- }
31
- export async function loadCanonicalSkillBinding(name) {
32
- const configuredPath = resolve(homedir(), `.agents/skills/${name}/SKILL.md`);
33
- let path;
34
- let raw;
35
- try {
36
- path = await realpath(configuredPath);
37
- raw = await readFile(path, "utf8");
38
- }
39
- catch (error) {
40
- throw new CanonicalSkillUnavailableError(name, configuredPath, error);
41
- }
42
- const body = stripFrontmatter(raw).trim();
43
- if (body.length === 0) {
44
- throw new Error(`Canonical ${name} Skill is empty at ${path}`);
45
- }
46
- const snapshot = Object.freeze({
47
- raw,
48
- path,
49
- baseDir: dirname(path),
50
- body,
51
- snapshotIdentity: Object.freeze({ text: raw }),
52
- });
53
- const binding = {
54
- name,
55
- snapshot,
56
- captureExpansion(evidence, originalRequest) {
57
- return captureCanonicalSkillExpansion(name, snapshot, configuredPath, evidence, originalRequest);
58
- },
59
- };
60
- return Object.freeze(binding);
61
- }
@@ -1,142 +0,0 @@
1
- /**
2
- * Collector bot handbook — opaque working memory under the book topology.
3
- * Runtime stores and delivers UTF-8 text only; never parses free text into
4
- * code state rules (parent #673 D3 / #677).
5
- *
6
- * Placement reuses the machine ledger home (ADR 0048) when the admitted
7
- * session already sits under books/<bookKey>/ — no parallel persistence frame.
8
- */
9
- import { readFile } from "node:fs/promises";
10
- import { join, sep } from "node:path";
11
- import { writeFileAtomically } from "./atomic-write.js";
12
- import { activationBookDirectory, assertLedgerFileInsideHome, ensureRealDirectoryTree, resolveActivationLedgerHomeForPath, } from "./activation-ledger-topology.js";
13
- import { COLLECTOR_HANDBOOK_MAX_BYTES } from "./collector-tool-schemas.js";
14
- /**
15
- * Derive handbook root from an admitted session/run path under
16
- * `.ak-roles/books/<bookKey>/...`. Fails closed when topology is absent.
17
- */
18
- export function resolveCollectorHandbookRoot(sessionPath) {
19
- if (typeof sessionPath !== "string" || sessionPath.trim().length === 0) {
20
- throw new Error("通进司手册要求非空 session 路径,且位于 books/<bookKey>/");
21
- }
22
- // Platform path segments only — never rewrite non-separator characters (POSIX `\\` is literal).
23
- const segments = sessionPath.split(sep);
24
- let bookKey;
25
- for (let i = 0; i + 3 < segments.length; i += 1) {
26
- if (segments[i] === ".ak-roles" && segments[i + 1] === "books") {
27
- const candidate = segments[i + 2];
28
- // Require a following segment so bookKey is a true path component under books/.
29
- if (candidate.length > 0) {
30
- bookKey = candidate;
31
- break;
32
- }
33
- }
34
- }
35
- if (bookKey === undefined) {
36
- throw new Error(`通进司手册要求 session 位于 books/<bookKey>/;收到 ${sessionPath}`);
37
- }
38
- if (bookKey === "." || bookKey === "..") {
39
- throw new Error(`通进司手册拒绝不安全 bookKey ${JSON.stringify(bookKey)}`);
40
- }
41
- const ledgerHome = resolveActivationLedgerHomeForPath(sessionPath);
42
- const root = join(activationBookDirectory(ledgerHome, bookKey), "collector-handbook");
43
- return { ledgerHome, bookKey, root };
44
- }
45
- /** Flat repo file name under handbook/repos/ — avoids nested owner/repo dirs. */
46
- function collectorHandbookRepoFileName(repositoryCanonical) {
47
- if (!/^[a-z0-9][a-z0-9._-]*\/[a-z0-9][a-z0-9._-]*$/.test(repositoryCanonical)) {
48
- throw new Error(`通进司手册仓库文件要求规范 owner/repo,收到 ${JSON.stringify(repositoryCanonical)}`);
49
- }
50
- return `${repositoryCanonical.replaceAll("/", "__")}.md`;
51
- }
52
- export function createCollectorHandbookStore(input) {
53
- const generalPath = join(input.handbookRoot, "general.md");
54
- const repoDir = join(input.handbookRoot, "repos");
55
- const repoPath = join(repoDir, collectorHandbookRepoFileName(input.repositoryCanonical));
56
- /**
57
- * ADR 0038: confine at the real read seam. Parent dirs must be physical under
58
- * ledger home; the leaf must not be a pre-existing symlink (even in-home).
59
- */
60
- /** Sole UTF-8 budget seam — write and read share COLLECTOR_HANDBOOK_MAX_BYTES. */
61
- const assertHandbookBudget = (body, label) => {
62
- const byteLength = Buffer.byteLength(body, "utf8");
63
- if (byteLength > COLLECTOR_HANDBOOK_MAX_BYTES) {
64
- throw new Error(`通进司手册${label} UTF-8 至多 ${COLLECTOR_HANDBOOK_MAX_BYTES} 字节,收到 ${byteLength}`);
65
- }
66
- return byteLength;
67
- };
68
- const readOptional = async (path, parentDir) => {
69
- ensureRealDirectoryTree(input.ledgerHome, parentDir);
70
- assertLedgerFileInsideHome(path, input.ledgerHome);
71
- try {
72
- const body = await readFile(path, "utf8");
73
- assertHandbookBudget(body, "正文");
74
- return body;
75
- }
76
- catch (error) {
77
- if (isNotFound(error))
78
- return undefined;
79
- throw error;
80
- }
81
- };
82
- return {
83
- root: input.handbookRoot,
84
- repositoryCanonical: input.repositoryCanonical,
85
- async read() {
86
- const bookGeneral = await readOptional(generalPath, input.handbookRoot);
87
- const bookRepo = await readOptional(repoPath, repoDir);
88
- if (bookGeneral !== undefined) {
89
- return {
90
- general: bookGeneral,
91
- repo: bookRepo ?? "",
92
- generalSource: "book",
93
- repoSource: bookRepo === undefined ? "empty" : "book",
94
- generalPath,
95
- repoPath,
96
- };
97
- }
98
- const seed = input.seedGeneral;
99
- if (typeof seed === "string" && seed.length > 0) {
100
- assertHandbookBudget(seed, "正文");
101
- return {
102
- general: seed,
103
- repo: bookRepo ?? "",
104
- generalSource: "seed",
105
- repoSource: bookRepo === undefined ? "empty" : "book",
106
- generalPath,
107
- repoPath,
108
- };
109
- }
110
- return {
111
- general: "",
112
- repo: bookRepo ?? "",
113
- generalSource: "empty",
114
- repoSource: bookRepo === undefined ? "empty" : "book",
115
- generalPath,
116
- repoPath,
117
- };
118
- },
119
- async write(scope, body) {
120
- // body string shape = collectorHandbookWriteArgsSchema; byte budget is business (UTF-8).
121
- const byteLength = assertHandbookBudget(body, "正文");
122
- ensureRealDirectoryTree(input.ledgerHome, input.handbookRoot);
123
- const path = scope === "general" ? generalPath : repoPath;
124
- if (scope === "repo") {
125
- ensureRealDirectoryTree(input.ledgerHome, repoDir);
126
- }
127
- assertLedgerFileInsideHome(path, input.ledgerHome);
128
- await writeFileAtomically(path, body);
129
- return {
130
- scope,
131
- path,
132
- byteLength,
133
- };
134
- },
135
- };
136
- }
137
- function isNotFound(error) {
138
- return typeof error === "object"
139
- && error !== null
140
- && "code" in error
141
- && error.code === "ENOENT";
142
- }
@@ -1,107 +0,0 @@
1
- import { COLLECTOR_HOST } from "./collector-config.js";
2
- import { enrichCollectorFindings, extractCollectorEvidenceIdentityGroups, extractCollectorUnfinishedReasons, } from "./collector-identity.js";
3
- import { validateAcceptedCollectorReceipt, } from "./package-contracts/collector-output.js";
4
- export { validateAcceptedCollectorReceipt };
5
- function fail(message) { throw new Error(message); }
6
- /** Runtime output assembles findings pointers from the model submission into the typed receipt. */
7
- export function buildCollectorReceipt(ledger, candidateRaw, clock) {
8
- ledger.assertNotFatal();
9
- if (ledger.unresolvedTransportFailure)
10
- fail("Collector cannot output while a transport failure is unrecovered");
11
- if (ledger.latestCompleteSnapshotId === undefined)
12
- fail("Collector output requires a complete final snapshot");
13
- if (ledger.activationTime === undefined || ledger.deadlineTime === undefined)
14
- fail("Collector output requires activation timeline");
15
- if (ledger.config.prNumber === undefined) {
16
- fail("Collector output requires a bound PR target; call ak_collector_bind_target first or pass --pr");
17
- }
18
- if (clock !== undefined)
19
- ledger.assertOutputObservationLaw(clock);
20
- else if (ledger.observedGeneration !== ledger.mutationGeneration ||
21
- (ledger.finalObservationRequired && !ledger.finalObservationCompleted)) {
22
- fail("Collector output requires a complete observe after the latest request/wait mutation");
23
- }
24
- const finalSnapshot = ledger.getSnapshot(ledger.latestCompleteSnapshotId);
25
- if (finalSnapshot === undefined || !finalSnapshot.complete)
26
- fail("Collector final snapshot is incomplete");
27
- // #676 D6: closed/merged still deliver collected materials; status is a fact on the receipt.
28
- const evidenceRecords = [...ledger.allEvidence()];
29
- const snapshots = [...ledger.allSnapshots()];
30
- const evidenceIndex = new Map(evidenceRecords.map((record) => [record.evidenceId, record]));
31
- const snapshotIndex = new Map(snapshots.map((snapshot) => [snapshot.snapshotId, snapshot]));
32
- if (evidenceIndex.size !== evidenceRecords.length)
33
- fail("Collector receipt evidenceId collision");
34
- if (snapshotIndex.size !== snapshots.length)
35
- fail("Collector receipt snapshotId collision");
36
- for (const id of evidenceIndex.keys())
37
- if (snapshotIndex.has(id))
38
- fail(`Collector receipt id "${id}" is ambiguous`);
39
- if (!snapshotIndex.has(finalSnapshot.snapshotId))
40
- fail("Collector receipt lacks final snapshot");
41
- for (const snapshot of snapshots) {
42
- for (const id of snapshot.evidenceIds)
43
- if (!evidenceIndex.has(id))
44
- fail(`Collector snapshot ref "${id}" does not resolve`);
45
- }
46
- const groups = extractCollectorEvidenceIdentityGroups(evidenceRecords, finalSnapshot.headOid);
47
- // #641 chain①: the collector LLM submits findings as pointer refs; the runtime
48
- // enriches each with the machine locator from the same stored record.
49
- const findingsProjection = enrichCollectorFindings({
50
- candidate: candidateRaw,
51
- records: evidenceRecords,
52
- groups,
53
- targetHead: finalSnapshot.headOid,
54
- repository: ledger.config.repository.canonical,
55
- prNumber: ledger.config.prNumber,
56
- });
57
- for (const group of groups) {
58
- for (const material of group.materials) {
59
- if (material.evidenceId === undefined || !evidenceIndex.has(material.evidenceId))
60
- fail("Collector material lacks a receipt-local evidence ref");
61
- }
62
- for (const finding of group.findings) {
63
- if (finding.source.evidenceId === undefined || !evidenceIndex.has(finding.source.evidenceId))
64
- fail("Collector finding lacks a receipt-local evidence ref");
65
- }
66
- }
67
- const unfinished = extractCollectorUnfinishedReasons(candidateRaw);
68
- const submissionProjection = {
69
- findingsSource: findingsProjection.findingsSource,
70
- findingsProjectedCount: findingsProjection.findingsProjectedCount,
71
- findingsUnprojected: findingsProjection.findingsUnprojected,
72
- unfinishedReasonsSource: unfinished.source,
73
- unfinishedReasonsProjectedCount: unfinished.reasons?.length ?? 0,
74
- unfinishedReasonsUnprojected: unfinished.unprojected,
75
- };
76
- return {
77
- host: COLLECTOR_HOST,
78
- repository: ledger.config.repository.canonical,
79
- prNumber: ledger.config.prNumber,
80
- prState: finalSnapshot.prState,
81
- manifestDigest: ledger.config.manifest.digest,
82
- activationTime: ledger.activationTime.toISOString(),
83
- deadlineTime: ledger.deadlineTime.toISOString(),
84
- finalObservationTime: finalSnapshot.completedAt ?? finalSnapshot.observedAt,
85
- finalSnapshotId: finalSnapshot.snapshotId,
86
- targetHead: finalSnapshot.headOid,
87
- groups,
88
- ...(unfinished.reasons === undefined ? {} : { unfinishedReasons: unfinished.reasons }),
89
- submissionProjection,
90
- requestAttempts: [...ledger.requestAttempts()],
91
- snapshots,
92
- evidenceRecords: evidenceRecords.map(toReceiptEvidenceRecord),
93
- };
94
- }
95
- function toReceiptEvidenceRecord(record) {
96
- return {
97
- evidenceId: record.evidenceId,
98
- kind: record.kind,
99
- versionId: record.versionId,
100
- contentDigest: record.contentDigest,
101
- firstObservedAt: record.firstObservedAt,
102
- ...(record.githubId === undefined ? {} : { githubId: record.githubId }),
103
- ...(record.authorLogin === undefined ? {} : { authorLogin: record.authorLogin }),
104
- ...(record.htmlUrl === undefined ? {} : { htmlUrl: record.htmlUrl }),
105
- ...(record.authoritativeTime === undefined ? {} : { authoritativeTime: record.authoritativeTime }),
106
- };
107
- }