@akagilnc/pi-workflow-roles 0.1.4673 → 0.1.4698
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/acp-host/production-host.js +496 -518
- package/dist/compliance-transport.js +6 -2
- package/dist/gatekeeper-role.js +6 -7
- package/dist/headless-host/production-host.js +492 -514
- package/dist/migrate-book-topology.js +8 -0
- package/dist/public-cli/countersign-run.js +63 -18
- package/dist/public-cli/main.js +488 -513
- package/dist/public-cli/settlement.js +316 -247
- package/dist/public-cli/terminal.js +36 -9
- package/dist/run-terminal-artifacts.js +71 -32
- package/package.json +1 -1
- package/souls/audit-law.md +7 -2
- package/souls/countersign.md +1 -1
- package/souls/gleaner-left.md +1 -1
- package/souls/notary.md +1 -1
- package/souls/quality-law.md +9 -0
- package/souls/reviewer.md +1 -1
- package/src/compliance-transport.ts +8 -2
- package/src/gatekeeper-role.ts +6 -6
- package/src/public-cli/countersign-run.ts +75 -26
- package/src/public-cli/secretariat-run.ts +2 -3
- package/src/public-cli/settlement.ts +380 -355
- package/src/public-cli/terminal.ts +48 -13
- package/src/role-runtime.ts +9 -11
- package/src/run-terminal-artifacts.ts +81 -28
- package/src/secretariat-role.ts +9 -4
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Controlled failures and audit human decisions settle here without washing causes.
|
|
5
5
|
*/
|
|
6
6
|
import { randomUUID } from "node:crypto";
|
|
7
|
-
import { appendFile, lstat,
|
|
7
|
+
import { appendFile, lstat, readFile, readdir, rm, unlink, writeFile } from "node:fs/promises";
|
|
8
8
|
import { dirname, join } from "node:path";
|
|
9
9
|
import { readAnalystGateCyclesFromAuditorRoles, } from "../analyst-gate-cycles-read.js";
|
|
10
10
|
import { readSitianRecords, resolveSitianRecordPath, sitianReport } from "../sitian-facade.js";
|
|
@@ -41,6 +41,7 @@ import { observePackagedMethodSkillInvocation, } from "../package-resources/meth
|
|
|
41
41
|
import { classifyPackagedRoleTerminalResult, findLatestDurablePackagedRoleTerminal, hasNavigatorInfrastructureFailureBase, isAcceptedPackagedRoleTerminalResult, isReceiptSettlementBindingClear, NAVIGATOR_INVOCATION_ENTRY, parseInvocationMarkerIdentity, } from "../navigator-invocation-identity.js";
|
|
42
42
|
import { NO_RECEIPT_LIFECYCLE_ENTRY_TYPE, RECEIPT_DELIVERY_TURN_LIMIT, noReceiptLifecycleFacts, parseNoReceiptLifecycleFacts, } from "../receipt-delivery-policy.js";
|
|
43
43
|
import { roleRunArtifactsDirectory } from "../role-run-placement.js";
|
|
44
|
+
import { listSeamOwnedUniqueErrorFacePaths, RUN_TERMINAL_ARTIFACT_FILES, RUN_TERMINAL_ERROR_FALLBACK_RELATIVE_PATHS, } from "../run-terminal-artifacts.js";
|
|
44
45
|
import { ensureRunArtifactsDir, homeFromRunDirectory, } from "./invocation.js";
|
|
45
46
|
/** Ledger reads use the run's machine home — not ambient process HOME (child write vs parent settle). */
|
|
46
47
|
function sealedLedgerHome(admitted) {
|
|
@@ -107,13 +108,20 @@ export function withSubmissions(terminal, submissions) {
|
|
|
107
108
|
if (submissions.length === 0)
|
|
108
109
|
return terminal;
|
|
109
110
|
const roleOutcome = terminal.roleOutcome;
|
|
110
|
-
// #
|
|
111
|
-
//
|
|
111
|
+
// #881 / #836: full run history always lands on terminal.submissions.
|
|
112
|
+
// #879: accepted/audit_escalation may still fill a missing this-court
|
|
113
|
+
// payloads face from that history. #953: failure must not — prior receipts
|
|
114
|
+
// stay on the historical carrier only, never as the current failure's
|
|
115
|
+
// ordinary payloads/receipt face.
|
|
116
|
+
if (roleOutcome.kind === "failure") {
|
|
117
|
+
return { ...terminal, submissions };
|
|
118
|
+
}
|
|
112
119
|
const withPayloads = roleOutcome.kind === "accepted" || roleOutcome.kind === "audit_escalation"
|
|
113
|
-
? {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
120
|
+
? {
|
|
121
|
+
...roleOutcome,
|
|
122
|
+
payloads: coalesceSubmissionRows(roleOutcome.payloads, submissions),
|
|
123
|
+
}
|
|
124
|
+
: roleOutcome;
|
|
117
125
|
return { ...terminal, roleOutcome: withPayloads, submissions };
|
|
118
126
|
}
|
|
119
127
|
/** Attach full ledger submissions onto any settled terminal (#836). */
|
|
@@ -127,6 +135,7 @@ export async function attachRecordedSubmissions(admitted, terminal, scope) {
|
|
|
127
135
|
/**
|
|
128
136
|
* Host ended with no recorded submission — lawful no_receipt (exit 0).
|
|
129
137
|
* Does not invent an output failure for an empty ledger.
|
|
138
|
+
* #953: empty public terminal face — clear every reader-adoptable prior face.
|
|
130
139
|
*/
|
|
131
140
|
export async function settleHostEndedNoReceipt(admitted, authority, scope) {
|
|
132
141
|
const facts = noReceiptLifecycleFacts({
|
|
@@ -137,6 +146,7 @@ export async function settleHostEndedNoReceipt(admitted, authority, scope) {
|
|
|
137
146
|
attemptPointer: `current:${admitted.runDirectory}`,
|
|
138
147
|
});
|
|
139
148
|
const coordinates = coordinatesFromAdmitted(authority, admitted);
|
|
149
|
+
await clearOppositeTerminalArtifactFace(admitted.runDirectory);
|
|
140
150
|
return withOptionalGateProjection({
|
|
141
151
|
roleOutcome: {
|
|
142
152
|
kind: "no_receipt",
|
|
@@ -157,7 +167,7 @@ async function closedLedgerOutcome(admitted, role, scope) {
|
|
|
157
167
|
function coordinatesFromAdmitted(authority, admitted) {
|
|
158
168
|
return authority.decode(admitted.principal);
|
|
159
169
|
}
|
|
160
|
-
import { exitCodeForTerminalOutcome, formatTerminalResult, isLawfulTypedTerminalOutcome, adviceNavigatorFact, } from "./terminal.js";
|
|
170
|
+
import { coalesceSubmissionRows, exitCodeForTerminalOutcome, formatTerminalResult, isLawfulTypedTerminalOutcome, adviceNavigatorFact, } from "./terminal.js";
|
|
161
171
|
export { exitCodeForTerminalOutcome, formatTerminalResult, isLawfulTypedTerminalOutcome, };
|
|
162
172
|
/**
|
|
163
173
|
* Host stderr as recorded — full bytes, no flood filter, no char clip (#836).
|
|
@@ -470,6 +480,13 @@ function isMissingPathError(error) {
|
|
|
470
480
|
"code" in error &&
|
|
471
481
|
error.code === "ENOENT");
|
|
472
482
|
}
|
|
483
|
+
/** Face clear only: path not enterable as a face (ENOENT or file mid-path). */
|
|
484
|
+
function isAbsentFacePathError(error) {
|
|
485
|
+
return (error instanceof Error &&
|
|
486
|
+
"code" in error &&
|
|
487
|
+
(error.code === "ENOENT" ||
|
|
488
|
+
error.code === "ENOTDIR"));
|
|
489
|
+
}
|
|
473
490
|
/**
|
|
474
491
|
* Preserve session-read failure identity as a typed session cause.
|
|
475
492
|
* SyntaxError keeps its name so durable settlement does not wash malformed JSONL
|
|
@@ -1644,72 +1661,131 @@ async function extractNavigatorFactFromAdmittedSession(sessionFile) {
|
|
|
1644
1661
|
};
|
|
1645
1662
|
}
|
|
1646
1663
|
}
|
|
1647
|
-
|
|
1664
|
+
/**
|
|
1665
|
+
* Remove one face path (file or directory collision plant).
|
|
1666
|
+
* Only missing target is silent — other errno stay loud (失败诚实).
|
|
1667
|
+
* recursive: publication may have occupied a face name as a directory (EISDIR plant).
|
|
1668
|
+
*/
|
|
1669
|
+
async function removeFaceIfPresent(path) {
|
|
1670
|
+
try {
|
|
1671
|
+
await rm(path, { recursive: true, force: true });
|
|
1672
|
+
}
|
|
1673
|
+
catch (error) {
|
|
1674
|
+
// force:true already ignores ENOENT; ENOTDIR = face path not enterable
|
|
1675
|
+
// (artifacts-as-file mid-path) — same absent-face semantics as the reader.
|
|
1676
|
+
// Other errno stay loud (失败诚实).
|
|
1677
|
+
if (isAbsentFacePathError(error))
|
|
1678
|
+
return;
|
|
1679
|
+
throw error;
|
|
1680
|
+
}
|
|
1681
|
+
}
|
|
1682
|
+
/**
|
|
1683
|
+
* #953: artifact face reflects the current terminal only.
|
|
1684
|
+
* Reader contract owns the full adoptable set (conventional trio + fixed
|
|
1685
|
+
* fallbacks + seam-owned unique). Clear every seam-owned face before the
|
|
1686
|
+
* new current publishes — including the conventional name about to be
|
|
1687
|
+
* rewritten. Retaining that name left directory collision plants in place
|
|
1688
|
+
* (supported publish input); writer then fell back while the reader stopped
|
|
1689
|
+
* at EISDIR on the stale conventional path and never adopted the fallback.
|
|
1690
|
+
* report / error / empty share one method (no per-branch face list).
|
|
1691
|
+
* empty publishes nothing; does not create a no_receipt-shaped public artifact.
|
|
1692
|
+
* Non-terminal materials stay. Face names may be directory collision plants —
|
|
1693
|
+
* remove recursively. Unique ownership is listSeamOwnedUniqueErrorFacePaths:
|
|
1694
|
+
* parent runs/ faces clear only when body.runId binds; unparseable runId → none.
|
|
1695
|
+
* Path absence (ENOENT/ENOTDIR) is silent; other delete failures stay loud.
|
|
1696
|
+
*/
|
|
1697
|
+
async function clearOppositeTerminalArtifactFace(runDirectory) {
|
|
1698
|
+
const artifactsDir = roleRunArtifactsDirectory(runDirectory);
|
|
1699
|
+
for (const file of RUN_TERMINAL_ARTIFACT_FILES) {
|
|
1700
|
+
await removeFaceIfPresent(join(artifactsDir, file));
|
|
1701
|
+
}
|
|
1702
|
+
// Fixed fallbacks + unique clear too; subsequent publish writes the new
|
|
1703
|
+
// durable path after this clear (conventional first when writable).
|
|
1704
|
+
for (const relative of RUN_TERMINAL_ERROR_FALLBACK_RELATIVE_PATHS) {
|
|
1705
|
+
await removeFaceIfPresent(join(runDirectory, relative));
|
|
1706
|
+
}
|
|
1707
|
+
for (const path of await listSeamOwnedUniqueErrorFacePaths(runDirectory)) {
|
|
1708
|
+
await removeFaceIfPresent(path);
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1711
|
+
async function ensureTerminalArtifactFace(runDirectory) {
|
|
1712
|
+
const artifactsDir = await ensureRunArtifactsDir(runDirectory);
|
|
1713
|
+
await clearOppositeTerminalArtifactFace(runDirectory);
|
|
1714
|
+
return artifactsDir;
|
|
1715
|
+
}
|
|
1716
|
+
function acceptedArtifactAttachmentRefs(attachments) {
|
|
1717
|
+
return attachments.map((a) => ({
|
|
1718
|
+
provenancePath: a.provenancePath,
|
|
1719
|
+
frozenPath: a.frozenPath,
|
|
1720
|
+
sha256: a.sha256,
|
|
1721
|
+
byteLength: a.byteLength,
|
|
1722
|
+
}));
|
|
1723
|
+
}
|
|
1724
|
+
/**
|
|
1725
|
+
* Sole success-terminal artifact publisher (#953): append attempt history,
|
|
1726
|
+
* refresh the public terminal face, write report/evidence, return refs.
|
|
1727
|
+
* Seat-specific structured fields stay in callers; do not fork this flow.
|
|
1728
|
+
*/
|
|
1729
|
+
async function publishAcceptedTerminalArtifacts(admitted, roleOutcome, coordinates, bodies) {
|
|
1648
1730
|
// #419: history first — report/evidence stay last-write-wins views only
|
|
1649
1731
|
// because every attempt's complete result has already been appended.
|
|
1650
|
-
await appendRunAttemptHistory({
|
|
1651
|
-
|
|
1652
|
-
const reportPath = join(artifactsDir, "report.json");
|
|
1653
|
-
const evidencePath = join(artifactsDir, "evidence.json");
|
|
1654
|
-
await writeFile(reportPath, `${JSON.stringify({
|
|
1655
|
-
role: "judge",
|
|
1656
|
-
runId: admitted.runId,
|
|
1657
|
-
outcome: roleOutcome,
|
|
1658
|
-
}, null, 2)}\n`, "utf8");
|
|
1659
|
-
await writeFile(evidencePath, `${JSON.stringify({
|
|
1732
|
+
await appendRunAttemptHistory({
|
|
1733
|
+
role: admitted.role,
|
|
1660
1734
|
runId: admitted.runId,
|
|
1661
|
-
sessionDirectory: coordinates.sessionDirectory,
|
|
1662
1735
|
sessionFile: coordinates.sessionFile,
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
})),
|
|
1670
|
-
}, null, 2)}\n`, "utf8");
|
|
1736
|
+
}, roleOutcome);
|
|
1737
|
+
const artifactsDir = await ensureTerminalArtifactFace(admitted.runDirectory);
|
|
1738
|
+
const reportPath = join(artifactsDir, "report.json");
|
|
1739
|
+
const evidencePath = join(artifactsDir, "evidence.json");
|
|
1740
|
+
await writeFile(reportPath, `${JSON.stringify(bodies.report, null, 2)}\n`, "utf8");
|
|
1741
|
+
await writeFile(evidencePath, `${JSON.stringify(bodies.evidence, null, 2)}\n`, "utf8");
|
|
1671
1742
|
return [
|
|
1672
1743
|
{ kind: "report", path: reportPath },
|
|
1673
1744
|
{ kind: "evidence", path: evidencePath },
|
|
1674
1745
|
];
|
|
1675
1746
|
}
|
|
1747
|
+
export async function publishJudgeArtifacts(admitted, roleOutcome, coordinates) {
|
|
1748
|
+
return publishAcceptedTerminalArtifacts(admitted, roleOutcome, coordinates, {
|
|
1749
|
+
report: {
|
|
1750
|
+
role: "judge",
|
|
1751
|
+
runId: admitted.runId,
|
|
1752
|
+
outcome: roleOutcome,
|
|
1753
|
+
},
|
|
1754
|
+
evidence: {
|
|
1755
|
+
runId: admitted.runId,
|
|
1756
|
+
sessionDirectory: coordinates.sessionDirectory,
|
|
1757
|
+
sessionFile: coordinates.sessionFile,
|
|
1758
|
+
admittedRequestPath: admitted.admittedRequestPath,
|
|
1759
|
+
attachments: acceptedArtifactAttachmentRefs(admitted.attachments),
|
|
1760
|
+
},
|
|
1761
|
+
});
|
|
1762
|
+
}
|
|
1676
1763
|
/**
|
|
1677
1764
|
* Publish lawful Coder success Artifacts on the shared #106 success interface.
|
|
1678
1765
|
* Evidence records package method provenance without ambient home Skill paths.
|
|
1679
1766
|
*/
|
|
1680
1767
|
export async function publishCoderArtifacts(admitted, roleOutcome, coordinates, options = {}) {
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
sha256: a.sha256,
|
|
1703
|
-
byteLength: a.byteLength,
|
|
1704
|
-
})),
|
|
1705
|
-
...(options.methodProvenance === undefined
|
|
1706
|
-
? {}
|
|
1707
|
-
: { methodProvenance: options.methodProvenance }),
|
|
1708
|
-
}, null, 2)}\n`, "utf8");
|
|
1709
|
-
return [
|
|
1710
|
-
{ kind: "report", path: reportPath },
|
|
1711
|
-
{ kind: "evidence", path: evidencePath },
|
|
1712
|
-
];
|
|
1768
|
+
return publishAcceptedTerminalArtifacts(admitted, roleOutcome, coordinates, {
|
|
1769
|
+
report: {
|
|
1770
|
+
role: "coder",
|
|
1771
|
+
runId: admitted.runId,
|
|
1772
|
+
phase: admitted.phase,
|
|
1773
|
+
outcome: roleOutcome,
|
|
1774
|
+
},
|
|
1775
|
+
evidence: {
|
|
1776
|
+
runId: admitted.runId,
|
|
1777
|
+
role: "coder",
|
|
1778
|
+
phase: admitted.phase,
|
|
1779
|
+
sessionDirectory: coordinates.sessionDirectory,
|
|
1780
|
+
sessionFile: coordinates.sessionFile,
|
|
1781
|
+
admittedRequestPath: admitted.admittedRequestPath,
|
|
1782
|
+
taskPath: admitted.taskPath,
|
|
1783
|
+
attachments: acceptedArtifactAttachmentRefs(admitted.attachments),
|
|
1784
|
+
...(options.methodProvenance === undefined
|
|
1785
|
+
? {}
|
|
1786
|
+
: { methodProvenance: options.methodProvenance }),
|
|
1787
|
+
},
|
|
1788
|
+
});
|
|
1713
1789
|
}
|
|
1714
1790
|
/**
|
|
1715
1791
|
* Read session entries for lawful settlement. Missing path → undefined (absence).
|
|
@@ -1861,43 +1937,32 @@ export function extractFixerMethodInvocations(entries, options) {
|
|
|
1861
1937
|
* Evidence records package diagnosis provenance and optional observed invocation.
|
|
1862
1938
|
*/
|
|
1863
1939
|
export async function publishFixerArtifacts(admitted, roleOutcome, coordinates, options) {
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
:
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
byteLength: a.byteLength,
|
|
1891
|
-
})),
|
|
1892
|
-
methodProvenance: options.methodProvenance,
|
|
1893
|
-
// Optional diagnosis: availability is package-bound; invocation only when observed.
|
|
1894
|
-
methodInvocationObserved: (options.methodInvocations ?? []).length > 0,
|
|
1895
|
-
methodInvocations: options.methodInvocations ?? [],
|
|
1896
|
-
}, null, 2)}\n`, "utf8");
|
|
1897
|
-
return [
|
|
1898
|
-
{ kind: "report", path: reportPath },
|
|
1899
|
-
{ kind: "evidence", path: evidencePath },
|
|
1900
|
-
];
|
|
1940
|
+
return publishAcceptedTerminalArtifacts(admitted, roleOutcome, coordinates, {
|
|
1941
|
+
report: {
|
|
1942
|
+
role: "fixer",
|
|
1943
|
+
runId: admitted.runId,
|
|
1944
|
+
phase: admitted.phase,
|
|
1945
|
+
outcome: roleOutcome,
|
|
1946
|
+
},
|
|
1947
|
+
evidence: {
|
|
1948
|
+
runId: admitted.runId,
|
|
1949
|
+
role: "fixer",
|
|
1950
|
+
phase: admitted.phase,
|
|
1951
|
+
sessionDirectory: coordinates.sessionDirectory,
|
|
1952
|
+
sessionFile: coordinates.sessionFile,
|
|
1953
|
+
admittedRequestPath: admitted.admittedRequestPath,
|
|
1954
|
+
packetPath: admitted.packetPath,
|
|
1955
|
+
...(admitted.prerequisitesPath === undefined
|
|
1956
|
+
? {}
|
|
1957
|
+
: { prerequisitesPath: admitted.prerequisitesPath }),
|
|
1958
|
+
prerequisites: admitted.prerequisites,
|
|
1959
|
+
attachments: acceptedArtifactAttachmentRefs(admitted.attachments),
|
|
1960
|
+
methodProvenance: options.methodProvenance,
|
|
1961
|
+
// Optional diagnosis: availability is package-bound; invocation only when observed.
|
|
1962
|
+
methodInvocationObserved: (options.methodInvocations ?? []).length > 0,
|
|
1963
|
+
methodInvocations: options.methodInvocations ?? [],
|
|
1964
|
+
},
|
|
1965
|
+
});
|
|
1901
1966
|
}
|
|
1902
1967
|
async function settleLawfulFixerTerminalResult(admitted, authority, options, scope) {
|
|
1903
1968
|
const ledgerOutcome = await closedLedgerOutcome(admitted, "fixer", scope);
|
|
@@ -1934,35 +1999,24 @@ export async function settleFixerTerminalResult(admitted, authority, options, sc
|
|
|
1934
1999
|
return settled;
|
|
1935
2000
|
}
|
|
1936
2001
|
export async function publishCollectorArtifacts(admitted, roleOutcome, coordinates) {
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
attachments: admitted.attachments.map((a) => ({
|
|
1956
|
-
provenancePath: a.provenancePath,
|
|
1957
|
-
frozenPath: a.frozenPath,
|
|
1958
|
-
sha256: a.sha256,
|
|
1959
|
-
byteLength: a.byteLength,
|
|
1960
|
-
})),
|
|
1961
|
-
}, null, 2)}\n`, "utf8");
|
|
1962
|
-
return [
|
|
1963
|
-
{ kind: "report", path: reportPath },
|
|
1964
|
-
{ kind: "evidence", path: evidencePath },
|
|
1965
|
-
];
|
|
2002
|
+
return publishAcceptedTerminalArtifacts(admitted, roleOutcome, coordinates, {
|
|
2003
|
+
report: {
|
|
2004
|
+
role: "collector",
|
|
2005
|
+
runId: admitted.runId,
|
|
2006
|
+
outcome: roleOutcome,
|
|
2007
|
+
},
|
|
2008
|
+
evidence: {
|
|
2009
|
+
runId: admitted.runId,
|
|
2010
|
+
role: "collector",
|
|
2011
|
+
...(admitted.prNumber === undefined ? {} : { prNumber: admitted.prNumber }),
|
|
2012
|
+
repository: admitted.repository.canonical,
|
|
2013
|
+
manifestDigest: admitted.manifestDigest,
|
|
2014
|
+
sessionDirectory: coordinates.sessionDirectory,
|
|
2015
|
+
sessionFile: coordinates.sessionFile,
|
|
2016
|
+
admittedRequestPath: admitted.admittedRequestPath,
|
|
2017
|
+
attachments: acceptedArtifactAttachmentRefs(admitted.attachments),
|
|
2018
|
+
},
|
|
2019
|
+
});
|
|
1966
2020
|
}
|
|
1967
2021
|
async function settleLawfulCollectorTerminalResult(admitted, authority, scope) {
|
|
1968
2022
|
const coordinates = coordinatesFromAdmitted(authority, admitted);
|
|
@@ -2047,37 +2101,28 @@ function extractDoctorCandidateAuditNoReceiptFact(entries) {
|
|
|
2047
2101
|
return undefined;
|
|
2048
2102
|
}
|
|
2049
2103
|
export async function publishDoctorArtifacts(admitted, roleOutcome, coordinates, options = {}) {
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
frozenPath: a.frozenPath,
|
|
2073
|
-
sha256: a.sha256,
|
|
2074
|
-
byteLength: a.byteLength,
|
|
2075
|
-
})),
|
|
2076
|
-
}, null, 2)}\n`, "utf8");
|
|
2077
|
-
return [
|
|
2078
|
-
{ kind: "report", path: reportPath },
|
|
2079
|
-
{ kind: "evidence", path: evidencePath },
|
|
2080
|
-
];
|
|
2104
|
+
return publishAcceptedTerminalArtifacts(admitted, roleOutcome, coordinates, {
|
|
2105
|
+
report: {
|
|
2106
|
+
role: "doctor",
|
|
2107
|
+
runId: admitted.runId,
|
|
2108
|
+
outcome: roleOutcome,
|
|
2109
|
+
...(options.cost === undefined ? {} : { cost: options.cost }),
|
|
2110
|
+
...(options.auditNoReceipt === undefined
|
|
2111
|
+
? {}
|
|
2112
|
+
: { auditNoReceipt: options.auditNoReceipt }),
|
|
2113
|
+
},
|
|
2114
|
+
evidence: {
|
|
2115
|
+
runId: admitted.runId,
|
|
2116
|
+
role: "doctor",
|
|
2117
|
+
issueNumber: admitted.issueNumber,
|
|
2118
|
+
caseRunsPath: admitted.caseRunsPath,
|
|
2119
|
+
caseIdentity: admitted.caseIdentity,
|
|
2120
|
+
sessionDirectory: coordinates.sessionDirectory,
|
|
2121
|
+
sessionFile: coordinates.sessionFile,
|
|
2122
|
+
admittedRequestPath: admitted.admittedRequestPath,
|
|
2123
|
+
attachments: acceptedArtifactAttachmentRefs(admitted.attachments),
|
|
2124
|
+
},
|
|
2125
|
+
});
|
|
2081
2126
|
}
|
|
2082
2127
|
async function settleLawfulDoctorTerminalResult(admitted, authority, scope) {
|
|
2083
2128
|
const sealed = await sealedLedgerOutcome(admitted, "doctor", scope);
|
|
@@ -2132,6 +2177,25 @@ function currentAttemptStartIndex(entries) {
|
|
|
2132
2177
|
}
|
|
2133
2178
|
return 0;
|
|
2134
2179
|
}
|
|
2180
|
+
/**
|
|
2181
|
+
* Filed-seat success face via the sole accepted publisher (#953).
|
|
2182
|
+
*/
|
|
2183
|
+
async function publishSeatAcceptedArtifacts(admitted, roleOutcome, coordinates) {
|
|
2184
|
+
return publishAcceptedTerminalArtifacts(admitted, roleOutcome, coordinates, {
|
|
2185
|
+
report: {
|
|
2186
|
+
role: admitted.role,
|
|
2187
|
+
runId: admitted.runId,
|
|
2188
|
+
outcome: roleOutcome,
|
|
2189
|
+
},
|
|
2190
|
+
evidence: {
|
|
2191
|
+
runId: admitted.runId,
|
|
2192
|
+
sessionDirectory: coordinates.sessionDirectory,
|
|
2193
|
+
sessionFile: coordinates.sessionFile,
|
|
2194
|
+
admittedRequestPath: admitted.admittedRequestPath,
|
|
2195
|
+
attachments: acceptedArtifactAttachmentRefs(admitted.attachments),
|
|
2196
|
+
},
|
|
2197
|
+
});
|
|
2198
|
+
}
|
|
2135
2199
|
async function settleLawfulSeatAcceptedTerminalResult(admitted, authority, spec, scope) {
|
|
2136
2200
|
const coordinates = coordinatesFromAdmitted(authority, admitted);
|
|
2137
2201
|
const { sessionDirectory, sessionFile } = coordinates;
|
|
@@ -2169,10 +2233,11 @@ async function settleLawfulSeatAcceptedTerminalResult(admitted, authority, spec,
|
|
|
2169
2233
|
const roleOutcome = await closedLedgerOutcome(admitted, spec.role, scope);
|
|
2170
2234
|
if (roleOutcome !== undefined && (thisAttemptHasSeatSuccess || residual === undefined)) {
|
|
2171
2235
|
const navigator = extractNavigatorFact(entries);
|
|
2236
|
+
const artifacts = await publishSeatAcceptedArtifacts(admitted, roleOutcome, coordinates);
|
|
2172
2237
|
return withSubmissions(await withOptionalGateProjection({
|
|
2173
2238
|
roleOutcome,
|
|
2174
2239
|
navigator,
|
|
2175
|
-
artifacts
|
|
2240
|
+
artifacts,
|
|
2176
2241
|
runId: admitted.runId,
|
|
2177
2242
|
}, sessionDirectory, detourGateContext(admitted, scope)), submissions);
|
|
2178
2243
|
}
|
|
@@ -2433,42 +2498,31 @@ export function extractReviewerMethodInvocations(entries, options) {
|
|
|
2433
2498
|
* observation without ambient home Skill paths.
|
|
2434
2499
|
*/
|
|
2435
2500
|
export async function publishReviewerArtifacts(admitted, roleOutcome, coordinates, options) {
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
byteLength: a.byteLength,
|
|
2462
|
-
})),
|
|
2463
|
-
methodProvenance: options.methodProvenance,
|
|
2464
|
-
// Forced package method: availability is package-bound; expansion only when observed.
|
|
2465
|
-
methodInvocationObserved: (options.methodInvocations ?? []).length > 0,
|
|
2466
|
-
methodInvocations: options.methodInvocations ?? [],
|
|
2467
|
-
}, null, 2)}\n`, "utf8");
|
|
2468
|
-
return [
|
|
2469
|
-
{ kind: "report", path: reportPath },
|
|
2470
|
-
{ kind: "evidence", path: evidencePath },
|
|
2471
|
-
];
|
|
2501
|
+
return publishAcceptedTerminalArtifacts(admitted, roleOutcome, coordinates, {
|
|
2502
|
+
report: {
|
|
2503
|
+
role: "reviewer",
|
|
2504
|
+
runId: admitted.runId,
|
|
2505
|
+
outcome: roleOutcome,
|
|
2506
|
+
},
|
|
2507
|
+
evidence: {
|
|
2508
|
+
runId: admitted.runId,
|
|
2509
|
+
role: "reviewer",
|
|
2510
|
+
sessionDirectory: coordinates.sessionDirectory,
|
|
2511
|
+
sessionFile: coordinates.sessionFile,
|
|
2512
|
+
admittedRequestPath: admitted.admittedRequestPath,
|
|
2513
|
+
baseRevision: admitted.baseRevision,
|
|
2514
|
+
lens: admitted.lens,
|
|
2515
|
+
authorityRefs: [...admitted.authorityRefs],
|
|
2516
|
+
...(admitted.instructionEmpty
|
|
2517
|
+
? {}
|
|
2518
|
+
: { callerProvenance: admitted.instruction }),
|
|
2519
|
+
attachments: acceptedArtifactAttachmentRefs(admitted.attachments),
|
|
2520
|
+
methodProvenance: options.methodProvenance,
|
|
2521
|
+
// Forced package method: availability is package-bound; expansion only when observed.
|
|
2522
|
+
methodInvocationObserved: (options.methodInvocations ?? []).length > 0,
|
|
2523
|
+
methodInvocations: options.methodInvocations ?? [],
|
|
2524
|
+
},
|
|
2525
|
+
});
|
|
2472
2526
|
}
|
|
2473
2527
|
async function settleLawfulReviewerTerminalResult(admitted, authority, options, scope) {
|
|
2474
2528
|
const sealed = await sealedLedgerOutcome(admitted, "reviewer", scope);
|
|
@@ -2538,37 +2592,26 @@ export function extractMergerMethodInvocations(entries, options) {
|
|
|
2538
2592
|
* adapter-derived mechanical envelope facts without ambient home Skill paths.
|
|
2539
2593
|
*/
|
|
2540
2594
|
export async function publishMergerArtifacts(admitted, roleOutcome, coordinates, options) {
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
sha256: a.sha256,
|
|
2562
|
-
byteLength: a.byteLength,
|
|
2563
|
-
})),
|
|
2564
|
-
methodProvenance: options.methodProvenance,
|
|
2565
|
-
methodInvocationObserved: (options.methodInvocations ?? []).length > 0,
|
|
2566
|
-
methodInvocations: options.methodInvocations ?? [],
|
|
2567
|
-
}, null, 2)}\n`, "utf8");
|
|
2568
|
-
return [
|
|
2569
|
-
{ kind: "report", path: reportPath },
|
|
2570
|
-
{ kind: "evidence", path: evidencePath },
|
|
2571
|
-
];
|
|
2595
|
+
return publishAcceptedTerminalArtifacts(admitted, roleOutcome, coordinates, {
|
|
2596
|
+
report: {
|
|
2597
|
+
role: "merger",
|
|
2598
|
+
runId: admitted.runId,
|
|
2599
|
+
outcome: roleOutcome,
|
|
2600
|
+
},
|
|
2601
|
+
evidence: {
|
|
2602
|
+
runId: admitted.runId,
|
|
2603
|
+
role: "merger",
|
|
2604
|
+
sessionDirectory: coordinates.sessionDirectory,
|
|
2605
|
+
sessionFile: coordinates.sessionFile,
|
|
2606
|
+
admittedRequestPath: admitted.admittedRequestPath,
|
|
2607
|
+
mergerInputPath: admitted.mergerInputPath,
|
|
2608
|
+
derived: admitted.derived,
|
|
2609
|
+
attachments: acceptedArtifactAttachmentRefs(admitted.attachments),
|
|
2610
|
+
methodProvenance: options.methodProvenance,
|
|
2611
|
+
methodInvocationObserved: (options.methodInvocations ?? []).length > 0,
|
|
2612
|
+
methodInvocations: options.methodInvocations ?? [],
|
|
2613
|
+
},
|
|
2614
|
+
});
|
|
2572
2615
|
}
|
|
2573
2616
|
async function settleLawfulMergerTerminalResult(admitted, authority, options, scope) {
|
|
2574
2617
|
const coordinates = coordinatesFromAdmitted(authority, admitted);
|
|
@@ -2710,6 +2753,17 @@ export async function publishFailureArtifacts(admitted, failure, authority) {
|
|
|
2710
2753
|
const { sessionDirectory, sessionFile } = coordinatesFromAdmitted(authority, admitted);
|
|
2711
2754
|
const { baseDir, attempt: baseAttempt } = await resolveFailureArtifactsBase(admitted.runDirectory);
|
|
2712
2755
|
const priorIssues = baseAttempt === undefined ? [] : [baseAttempt];
|
|
2756
|
+
// #953: failure face must not leave a prior success report as the durable view.
|
|
2757
|
+
// Clear failure must not strand the original controlled failure outside
|
|
2758
|
+
// settlement — same as history failure below, it rides publicationIssues
|
|
2759
|
+
// and unique fallback still places the durable error (locked artifacts/ +
|
|
2760
|
+
// prior face must not abort publishFailureArtifacts).
|
|
2761
|
+
try {
|
|
2762
|
+
await clearOppositeTerminalArtifactFace(admitted.runDirectory);
|
|
2763
|
+
}
|
|
2764
|
+
catch (error) {
|
|
2765
|
+
priorIssues.push(publicationAttemptFromError(roleRunArtifactsDirectory(admitted.runDirectory), error));
|
|
2766
|
+
}
|
|
2713
2767
|
// #419: each attempt's complete failure result joins the appended history
|
|
2714
2768
|
// before any fixed-name artifact view is rewritten. History failure must not
|
|
2715
2769
|
// strand the original controlled failure outside settlement — it rides
|
|
@@ -2803,32 +2857,47 @@ export async function settleFailureTerminalResult(admitted, failure, authority,
|
|
|
2803
2857
|
const lifecycleEntry = entries.slice(attemptStart).reverse().find((entry) => entry.customType === NO_RECEIPT_LIFECYCLE_ENTRY_TYPE || entry.message?.customType === NO_RECEIPT_LIFECYCLE_ENTRY_TYPE);
|
|
2804
2858
|
const raw = lifecycleEntry?.data ?? lifecycleEntry?.message?.details;
|
|
2805
2859
|
if (raw !== undefined) {
|
|
2860
|
+
// Catch only covers lifecycle-byte parse. Clear / navigator / gate I/O
|
|
2861
|
+
// after a valid parse must keep their real failure identity (#953).
|
|
2862
|
+
let facts;
|
|
2806
2863
|
try {
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2864
|
+
facts = parseNoReceiptLifecycleFacts(raw);
|
|
2865
|
+
}
|
|
2866
|
+
catch {
|
|
2867
|
+
/* malformed lifecycle bytes remain the existing nonzero output failure */
|
|
2868
|
+
}
|
|
2869
|
+
if (facts !== undefined &&
|
|
2870
|
+
facts.runPointer === admitted.runDirectory &&
|
|
2871
|
+
facts.attemptPointer === `current:${admitted.runDirectory}`) {
|
|
2872
|
+
let decisiveFacts = facts;
|
|
2873
|
+
// #676 D1/J3: project durable bind-target rejection onto public no_receipt facts.
|
|
2874
|
+
if (admitted.role === "collector") {
|
|
2875
|
+
const bindRejection = extractCollectorTargetBindRejection(entries.slice(attemptStart));
|
|
2876
|
+
if (bindRejection !== undefined) {
|
|
2877
|
+
decisiveFacts = {
|
|
2878
|
+
...facts,
|
|
2879
|
+
targetBindRejected: true,
|
|
2880
|
+
targetBindDiagnostic: bindRejection.diagnostic,
|
|
2881
|
+
...(bindRejection.code === undefined ? {} : { targetBindCode: bindRejection.code }),
|
|
2882
|
+
};
|
|
2821
2883
|
}
|
|
2822
|
-
// #478: no_receipt is still a public Terminal — project accepted gate facts.
|
|
2823
|
-
return withOptionalGateProjection({
|
|
2824
|
-
roleOutcome: { kind: "no_receipt", role: admitted.role, status: "no-accepted-receipt", ...facts, decisiveFacts },
|
|
2825
|
-
navigator: await extractNavigatorFactFromAdmittedSession(sessionFile),
|
|
2826
|
-
artifacts: [],
|
|
2827
|
-
runId: admitted.runId,
|
|
2828
|
-
}, sessionDirectory, detourGateContext(admitted, options));
|
|
2829
2884
|
}
|
|
2885
|
+
// #478: no_receipt is still a public Terminal — project accepted gate facts.
|
|
2886
|
+
// #953: empty public terminal face — clear every reader-adoptable prior face.
|
|
2887
|
+
await clearOppositeTerminalArtifactFace(admitted.runDirectory);
|
|
2888
|
+
return withOptionalGateProjection({
|
|
2889
|
+
roleOutcome: {
|
|
2890
|
+
kind: "no_receipt",
|
|
2891
|
+
role: admitted.role,
|
|
2892
|
+
status: "no-accepted-receipt",
|
|
2893
|
+
...facts,
|
|
2894
|
+
decisiveFacts,
|
|
2895
|
+
},
|
|
2896
|
+
navigator: await extractNavigatorFactFromAdmittedSession(sessionFile),
|
|
2897
|
+
artifacts: [],
|
|
2898
|
+
runId: admitted.runId,
|
|
2899
|
+
}, sessionDirectory, detourGateContext(admitted, options));
|
|
2830
2900
|
}
|
|
2831
|
-
catch { /* malformed lifecycle bytes remain the existing nonzero output failure */ }
|
|
2832
2901
|
}
|
|
2833
2902
|
}
|
|
2834
2903
|
}
|