@akagilnc/pi-workflow-roles 0.1.3572 → 0.1.3621
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 +20239 -10556
- package/dist/analyst-gate-cycles-read.js +387 -0
- package/dist/archivist-record-entry.js +22 -1
- package/dist/audit-escalation.js +6 -0
- package/dist/auditor-soul.js +74 -0
- package/dist/collector-config.js +86 -0
- package/dist/collector-evidence.js +316 -0
- package/dist/collector-github.js +527 -0
- package/dist/collector-ledger.js +853 -0
- package/dist/collector-tool-schemas.js +33 -0
- package/dist/compliance-transport.js +104 -52
- package/dist/diarist-mechanical.js +411 -0
- package/dist/diarist-ticket-resolution.js +177 -0
- package/dist/diarist.js +311 -0
- package/dist/doctor-auditor.js +25 -0
- package/dist/doctor-contracts.js +2 -0
- package/dist/doctor-evidence.js +142 -0
- package/dist/gatekeeper-role.js +104 -81
- package/dist/host-transition-prior-native.js +78 -0
- package/dist/institutional-resolution.js +1 -95
- package/dist/judge-auditor.js +26 -0
- package/dist/ledger-session-read.js +227 -0
- package/dist/merger-git-state.js +78 -0
- package/dist/navigator-attendance.js +15 -7
- package/dist/navigator-public-session.js +170 -0
- package/dist/navigator-session-contracts.js +36 -40
- package/dist/notary-source-run.js +122 -0
- package/dist/package-contracts/auditor-output.js +66 -0
- package/dist/package-contracts/evidence-child-output.js +34 -0
- package/dist/package-contracts/judge-output.js +2 -0
- package/dist/package-contracts/terminating-tools.js +25 -2
- package/dist/package-resources/method-skill.js +254 -0
- package/dist/packaged-role-registry.js +36 -0
- package/dist/pi/durable-principal.js +61 -0
- package/dist/pi/in-process-session.js +25 -6
- package/dist/pi/known-failure.js +52 -0
- package/dist/pi/role-turn-host.js +430 -0
- package/dist/public-cli/auto-resume.js +414 -0
- package/dist/public-cli/cli-errors.js +8 -0
- package/dist/public-cli/cli-io.js +1 -0
- package/dist/public-cli/command-renderer.js +5 -0
- package/dist/public-cli/doctor-run.js +84 -0
- package/dist/public-cli/inspector-run.js +136 -0
- package/dist/public-cli/instruction-seat-run.js +256 -0
- package/dist/public-cli/invocation.js +2225 -0
- package/dist/public-cli/judge-run.js +118 -0
- package/dist/public-cli/load-production-acp-host.js +40 -0
- package/dist/public-cli/main.js +1140 -652
- package/dist/public-cli/notary-run.js +161 -0
- package/dist/public-cli/option-definitions.js +1192 -0
- package/dist/public-cli/post-admission.js +667 -0
- package/dist/public-cli/public-run-credentials.js +49 -0
- package/dist/public-cli/registry.js +4 -1
- package/dist/public-cli/reviewer-dispatch-rejection.js +77 -0
- package/dist/public-cli/run-lifecycle.js +1344 -0
- package/dist/public-cli/seat-ticket-binding.js +113 -0
- package/dist/public-cli/settlement.js +3441 -0
- package/dist/public-cli/terminal.js +135 -0
- package/dist/public-cli/turn-request.js +25 -0
- package/dist/public-role-summons.js +301 -0
- package/dist/receipt-delivery-policy.js +10 -0
- package/dist/reviewer-child-executor.js +80 -8
- package/dist/reviewer-execution-ledger.js +2 -1
- package/dist/run-terminal-artifacts.js +195 -0
- package/dist/run-ticket-number.js +40 -0
- package/dist/session-assistant-usage.js +107 -0
- package/dist/shape-unreadable-failure.js +34 -0
- package/dist/submission-errors.js +3 -0
- package/dist/submission-ledger.js +388 -0
- package/dist/ticket-provenance-contracts.js +115 -0
- package/dist/ticket-provenance.js +340 -0
- package/extensions/role-runtime.ts +7 -0
- package/package.json +1 -1
- package/scripts/build-package.mjs +2 -1
- package/souls/doctor-auditor.md +1 -0
- package/souls/evidence-child.md +1 -0
- package/src/acp-host/production-host.ts +3 -0
- package/src/acp-host/role-envelope.ts +2 -2
- package/src/acp-host/role-turn-host.ts +9 -1
- package/src/analyst-gate-cycles-read.ts +37 -2
- package/src/archivist-record-entry.ts +45 -1
- package/src/audit-escalation.ts +17 -0
- package/src/auditor-role.ts +22 -0
- package/src/auditor-soul.ts +42 -0
- package/src/compliance-transport.ts +177 -66
- package/src/doctor-auditor.ts +10 -14
- package/src/doctor-contracts.ts +1 -0
- package/src/doctor-role.ts +2 -2
- package/src/evidence-child-role.ts +22 -0
- package/src/gatekeeper-pass-envelope.ts +109 -0
- package/src/gatekeeper-role.ts +145 -104
- package/src/host-contracts.ts +9 -1
- package/src/institutional-resolution.ts +8 -163
- package/src/judge-auditor.ts +10 -15
- package/src/judge-role.ts +8 -0
- package/src/navigator-attendance.ts +25 -9
- package/src/navigator-public-session.ts +217 -0
- package/src/navigator-session-contracts.ts +61 -54
- package/src/notary-source-run.ts +3 -1
- package/src/package-contracts/auditor-output.ts +82 -0
- package/src/package-contracts/evidence-child-output.ts +51 -0
- package/src/package-contracts/judge-output.ts +1 -0
- package/src/package-contracts/reviewer-output.ts +2 -2
- package/src/package-contracts/terminating-tools.ts +31 -1
- package/src/packaged-role-registry.ts +43 -0
- package/src/pi/adapter.ts +2 -1
- package/src/pi/in-process-session.ts +38 -12
- package/src/pi/role-turn-host.ts +34 -0
- package/src/public-cli/cli.ts +14 -6
- package/src/public-cli/instruction-seat-run.ts +289 -50
- package/src/public-cli/invocation.ts +66 -25
- package/src/public-cli/option-definitions.ts +61 -0
- package/src/public-cli/post-admission.ts +7 -1
- package/src/public-cli/registry.ts +4 -1
- package/src/public-cli/run-lifecycle.ts +22 -3
- package/src/public-cli/settlement.ts +120 -5
- package/src/public-cli/terminal.ts +2 -0
- package/src/public-role-summons.ts +431 -0
- package/src/receipt-delivery-policy.ts +10 -0
- package/src/reviewer-agent.ts +1 -1
- package/src/reviewer-child-executor.ts +114 -12
- package/src/reviewer-execution-ledger.ts +3 -2
- package/src/role-runtime.ts +158 -17
- package/src/session-assistant-usage.ts +119 -0
- package/src/session-opening-materials.ts +1 -1
- package/src/shape-unreadable-failure.ts +49 -0
- package/src/submission-errors.ts +3 -0
- package/dist/evidence-child-executor.js +0 -829
- package/src/evidence-child-executor.ts +0 -1140
|
@@ -10,6 +10,8 @@ import { CorrectableSubmissionError } from "../submission-correctable-error.js";
|
|
|
10
10
|
import { DOCTOR_ACCEPTED_TEXT, DOCTOR_OUTPUT_TOOL_NAME, validateDoctorSubmissionShape, validateRecordedDoctorOutput } from "../doctor-contracts.js";
|
|
11
11
|
import { GATEKEEPER_ACCEPTED_TEXT, GATEKEEPER_OUTPUT_TOOL_NAME, validateRecordedGatekeeperOutput } from "./gatekeeper-output.js";
|
|
12
12
|
import { NAVIGATOR_ACCEPTED_TEXT, NAVIGATOR_OUTPUT_TOOL_NAME, validateRecordedNavigatorOutput } from "./navigator-output.js";
|
|
13
|
+
import { AUDITOR_ACCEPTED_TEXT, AUDITOR_OUTPUT_TOOL_NAME, validateRecordedAuditorOutput } from "./auditor-output.js";
|
|
14
|
+
import { EVIDENCE_CHILD_ACCEPTED_TEXT, EVIDENCE_CHILD_OUTPUT_TOOL_NAME, validateRecordedEvidenceChildOutput } from "./evidence-child-output.js";
|
|
13
15
|
import { MERGER_ACCEPTED_TEXT, MERGER_OUTPUT_TOOL_NAME, validateMergerOutput } from "../merger-contracts.js";
|
|
14
16
|
import { NOTARY_ACCEPTED_TEXT, NOTARY_OUTPUT_TOOL_NAME, validateRecordedNotaryOutput } from "../notary-contracts.js";
|
|
15
17
|
import { COUNTERSIGN_ACCEPTED_TEXT, COUNTERSIGN_OUTPUT_TOOL_NAME, validateRecordedCountersignOutput } from "../countersign-contracts.js";
|
|
@@ -17,7 +19,7 @@ import { GLEANER_LEFT_ACCEPTED_TEXT, GLEANER_LEFT_OUTPUT_TOOL_NAME, validateReco
|
|
|
17
19
|
import { INSPECTOR_ACCEPTED_TEXT, INSPECTOR_OUTPUT_TOOL_NAME, validateRecordedInspectorOutput } from "../inspector-contracts.js";
|
|
18
20
|
import { DIARIST_ACCEPTED_TEXT, DIARIST_OUTPUT_TOOL_NAME, validateRecordedDiaristOutput } from "../diarist-contracts.js";
|
|
19
21
|
import { CODER_ACCEPTED_TEXT, CODER_OUTPUT_TOOL_NAME, FIXER_ACCEPTED_TEXT, FIXER_OUTPUT_TOOL_NAME, validateAcceptedWorkerDetails, } from "./worker-output.js";
|
|
20
|
-
export { CODER_ACCEPTED_TEXT, CODER_OUTPUT_TOOL_NAME, COLLECTOR_ACCEPTED_TEXT, COLLECTOR_OUTPUT_TOOL, FIXER_ACCEPTED_TEXT, FIXER_OUTPUT_TOOL_NAME, JUDGE_ACCEPTED_TEXT, JUDGE_OUTPUT_TOOL_NAME, REVIEWER_ACCEPTED_TEXT, REVIEWER_OUTPUT_TOOL_NAME, MERGER_ACCEPTED_TEXT, MERGER_OUTPUT_TOOL_NAME, validateAcceptedCollectorReceipt, validateAcceptedJudgeDetails, projectReviewerIntentToReceipt, validateReviewerIntent, validateRuntimeReviewerReceipt, validateAcceptedWorkerDetails, validateDoctorSubmissionShape, validateRecordedDoctorOutput, validateMergerOutput, validateRecordedNotaryOutput, validateRecordedCountersignOutput, validateRecordedGleanerLeftOutput, validateRecordedInspectorOutput, validateRecordedGatekeeperOutput, validateRecordedNavigatorOutput, validateRecordedDiaristOutput, };
|
|
22
|
+
export { CODER_ACCEPTED_TEXT, CODER_OUTPUT_TOOL_NAME, COLLECTOR_ACCEPTED_TEXT, COLLECTOR_OUTPUT_TOOL, FIXER_ACCEPTED_TEXT, FIXER_OUTPUT_TOOL_NAME, JUDGE_ACCEPTED_TEXT, JUDGE_OUTPUT_TOOL_NAME, REVIEWER_ACCEPTED_TEXT, REVIEWER_OUTPUT_TOOL_NAME, MERGER_ACCEPTED_TEXT, MERGER_OUTPUT_TOOL_NAME, validateAcceptedCollectorReceipt, validateAcceptedJudgeDetails, projectReviewerIntentToReceipt, validateReviewerIntent, validateRuntimeReviewerReceipt, validateAcceptedWorkerDetails, validateDoctorSubmissionShape, validateRecordedDoctorOutput, validateMergerOutput, validateRecordedNotaryOutput, validateRecordedCountersignOutput, validateRecordedGleanerLeftOutput, validateRecordedInspectorOutput, validateRecordedGatekeeperOutput, validateRecordedNavigatorOutput, validateRecordedAuditorOutput, validateRecordedEvidenceChildOutput, validateRecordedDiaristOutput, };
|
|
21
23
|
export const TERMINATING_TOOL_NAMES = [
|
|
22
24
|
CODER_OUTPUT_TOOL_NAME,
|
|
23
25
|
FIXER_OUTPUT_TOOL_NAME,
|
|
@@ -32,6 +34,8 @@ export const TERMINATING_TOOL_NAMES = [
|
|
|
32
34
|
INSPECTOR_OUTPUT_TOOL_NAME,
|
|
33
35
|
GATEKEEPER_OUTPUT_TOOL_NAME,
|
|
34
36
|
NAVIGATOR_OUTPUT_TOOL_NAME,
|
|
37
|
+
AUDITOR_OUTPUT_TOOL_NAME,
|
|
38
|
+
EVIDENCE_CHILD_OUTPUT_TOOL_NAME,
|
|
35
39
|
DIARIST_OUTPUT_TOOL_NAME,
|
|
36
40
|
];
|
|
37
41
|
export function isTerminatingToolName(name) {
|
|
@@ -65,6 +69,10 @@ export function acceptedTextFor(toolName) {
|
|
|
65
69
|
return GATEKEEPER_ACCEPTED_TEXT;
|
|
66
70
|
case NAVIGATOR_OUTPUT_TOOL_NAME:
|
|
67
71
|
return NAVIGATOR_ACCEPTED_TEXT;
|
|
72
|
+
case AUDITOR_OUTPUT_TOOL_NAME:
|
|
73
|
+
return AUDITOR_ACCEPTED_TEXT;
|
|
74
|
+
case EVIDENCE_CHILD_OUTPUT_TOOL_NAME:
|
|
75
|
+
return EVIDENCE_CHILD_ACCEPTED_TEXT;
|
|
68
76
|
case DIARIST_OUTPUT_TOOL_NAME:
|
|
69
77
|
return DIARIST_ACCEPTED_TEXT;
|
|
70
78
|
}
|
|
@@ -118,14 +126,21 @@ export function validateAcceptedDetails(toolName, details) {
|
|
|
118
126
|
[INSPECTOR_OUTPUT_TOOL_NAME]: ["pass", "bounce"],
|
|
119
127
|
[GATEKEEPER_OUTPUT_TOOL_NAME]: ["dispatch", "pass"],
|
|
120
128
|
[NAVIGATOR_OUTPUT_TOOL_NAME]: ["advice"],
|
|
129
|
+
[AUDITOR_OUTPUT_TOOL_NAME]: ["pass", "revise", "escalate"],
|
|
130
|
+
[EVIDENCE_CHILD_OUTPUT_TOOL_NAME]: [],
|
|
121
131
|
[DIARIST_OUTPUT_TOOL_NAME]: ["completed"],
|
|
122
132
|
};
|
|
123
133
|
const collectorDiscriminator = toolName === COLLECTOR_OUTPUT_TOOL && Array.isArray(candidate?.groups);
|
|
134
|
+
// Evidence-child: any object is a candidate body — no report-field presence gate (#675 / ADR 0055).
|
|
135
|
+
const evidenceChildDiscriminator = toolName === EVIDENCE_CHILD_OUTPUT_TOOL_NAME
|
|
136
|
+
&& candidate !== null
|
|
137
|
+
&& typeof candidate === "object"
|
|
138
|
+
&& !Array.isArray(candidate);
|
|
124
139
|
const baseDiscriminator = discriminator;
|
|
125
140
|
const runtimeBindingMissing = (toolName === DOCTOR_OUTPUT_TOOL_NAME && baseDiscriminator === "completed" && !(candidate?.cost !== null && typeof candidate?.cost === "object")) ||
|
|
126
141
|
(toolName === REVIEWER_OUTPUT_TOOL_NAME && candidate?.version !== 2);
|
|
127
142
|
if (runtimeBindingMissing ||
|
|
128
|
-
(!collectorDiscriminator && (typeof discriminator !== "string" || !lawfulStatuses[toolName].includes(baseDiscriminator)))) {
|
|
143
|
+
(!collectorDiscriminator && !evidenceChildDiscriminator && (typeof discriminator !== "string" || !lawfulStatuses[toolName].includes(baseDiscriminator)))) {
|
|
129
144
|
throw new AcceptedDetailsContractError("terminating receipt has no recognized execution discriminator");
|
|
130
145
|
}
|
|
131
146
|
try {
|
|
@@ -156,6 +171,10 @@ export function validateAcceptedDetails(toolName, details) {
|
|
|
156
171
|
return validateRecordedGatekeeperOutput(details);
|
|
157
172
|
case NAVIGATOR_OUTPUT_TOOL_NAME:
|
|
158
173
|
return validateRecordedNavigatorOutput(details);
|
|
174
|
+
case AUDITOR_OUTPUT_TOOL_NAME:
|
|
175
|
+
return validateRecordedAuditorOutput(details);
|
|
176
|
+
case EVIDENCE_CHILD_OUTPUT_TOOL_NAME:
|
|
177
|
+
return validateRecordedEvidenceChildOutput(details);
|
|
159
178
|
case DIARIST_OUTPUT_TOOL_NAME:
|
|
160
179
|
return validateRecordedDiaristOutput(details);
|
|
161
180
|
}
|
|
@@ -210,6 +229,10 @@ export function acceptedFacts(toolName, details) {
|
|
|
210
229
|
case INSPECTOR_OUTPUT_TOOL_NAME:
|
|
211
230
|
case GATEKEEPER_OUTPUT_TOOL_NAME:
|
|
212
231
|
case NAVIGATOR_OUTPUT_TOOL_NAME:
|
|
232
|
+
case AUDITOR_OUTPUT_TOOL_NAME:
|
|
233
|
+
return { status: details.status };
|
|
234
|
+
case EVIDENCE_CHILD_OUTPUT_TOOL_NAME:
|
|
235
|
+
return { status: "report" };
|
|
213
236
|
case DIARIST_OUTPUT_TOOL_NAME: return { status: details.status };
|
|
214
237
|
case JUDGE_OUTPUT_TOOL_NAME: return { status: details.judgeStatus };
|
|
215
238
|
case COUNTERSIGN_OUTPUT_TOOL_NAME: return { status: details.countersignStatus };
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Package-owned role method Skill seam (ADR 0052 / #109).
|
|
3
|
+
* Forced methods load from the installed package copy — never ambient home discovery.
|
|
4
|
+
*
|
|
5
|
+
* This module is intentionally free of @earendil-works/pi-coding-agent so the
|
|
6
|
+
* public ak-role bin can load provenance/path without bundling peer runtime.
|
|
7
|
+
*/
|
|
8
|
+
import { createHash } from "node:crypto";
|
|
9
|
+
import { readFile, realpath } from "node:fs/promises";
|
|
10
|
+
import { join } from "node:path";
|
|
11
|
+
import { sha256Hex } from "../sha256.js";
|
|
12
|
+
/** Package-side unavailable method Skill (mirrors CanonicalSkillUnavailableError identity). */
|
|
13
|
+
export class PackagedMethodSkillUnavailableError extends Error {
|
|
14
|
+
skillName;
|
|
15
|
+
code = "canonical-skill-unavailable";
|
|
16
|
+
constructor(skillName, path, cause) {
|
|
17
|
+
super(`Canonical ${skillName} Skill is unavailable at ${path}`, { cause });
|
|
18
|
+
this.skillName = skillName;
|
|
19
|
+
this.name = "CanonicalSkillUnavailableError";
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
const METHOD_SKILL_RELATIVE_ROOT = "resources/methods";
|
|
23
|
+
const GIT_COMMIT_RE = /^[0-9a-f]{40}$/;
|
|
24
|
+
const GIT_BLOB_RE = /^[0-9a-f]{40}$/;
|
|
25
|
+
const SHA256_RE = /^[0-9a-f]{64}$/;
|
|
26
|
+
const REQUIRED_COMPANIONS = {
|
|
27
|
+
tdd: ["tests.md", "mocking.md", "agents/openai.yaml"],
|
|
28
|
+
"diagnosing-bugs": ["agents/openai.yaml", "scripts/hitl-loop.template.sh"],
|
|
29
|
+
"code-review": ["agents/openai.yaml"],
|
|
30
|
+
"resolving-merge-conflicts": ["agents/openai.yaml"],
|
|
31
|
+
};
|
|
32
|
+
/** Git blob OID for raw file bytes (sha1 of `blob <size>\\0` + content). */
|
|
33
|
+
export function gitBlobOid(bytes) {
|
|
34
|
+
const body = typeof bytes === "string" ? Buffer.from(bytes, "utf8") : Buffer.from(bytes);
|
|
35
|
+
const header = Buffer.from(`blob ${body.byteLength}\0`, "utf8");
|
|
36
|
+
return createHash("sha1").update(header).update(body).digest("hex");
|
|
37
|
+
}
|
|
38
|
+
/** Minimal frontmatter strip — body after closing `---` fence (or full text). */
|
|
39
|
+
export function stripSkillFrontmatter(content) {
|
|
40
|
+
if (!content.startsWith("---"))
|
|
41
|
+
return content;
|
|
42
|
+
const end = content.indexOf("\n---", 3);
|
|
43
|
+
if (end === -1)
|
|
44
|
+
return content;
|
|
45
|
+
const after = content.slice(end + "\n---".length);
|
|
46
|
+
return after.replace(/^\r?\n/, "");
|
|
47
|
+
}
|
|
48
|
+
export function packagedMethodSkillRelativeDirectory(name) {
|
|
49
|
+
return `${METHOD_SKILL_RELATIVE_ROOT}/${name}`;
|
|
50
|
+
}
|
|
51
|
+
export function resolvePackagedMethodSkillRoot(packageRoot, name) {
|
|
52
|
+
return join(packageRoot, packagedMethodSkillRelativeDirectory(name));
|
|
53
|
+
}
|
|
54
|
+
export function resolvePackagedMethodSkillPath(packageRoot, name) {
|
|
55
|
+
return join(resolvePackagedMethodSkillRoot(packageRoot, name), "SKILL.md");
|
|
56
|
+
}
|
|
57
|
+
function isRecord(value) {
|
|
58
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
59
|
+
}
|
|
60
|
+
function parseProvenance(raw, expectedName) {
|
|
61
|
+
if (!isRecord(raw)) {
|
|
62
|
+
throw new Error(`Packaged method provenance must be an object for ${expectedName}`);
|
|
63
|
+
}
|
|
64
|
+
if (raw.name !== expectedName) {
|
|
65
|
+
throw new Error(`Packaged method provenance name mismatch: expected ${expectedName}, got ${String(raw.name)}`);
|
|
66
|
+
}
|
|
67
|
+
if (raw.kind !== "role-method-skill") {
|
|
68
|
+
throw new Error(`Packaged method provenance kind must be role-method-skill`);
|
|
69
|
+
}
|
|
70
|
+
if (typeof raw.packageAdaptation !== "string" || raw.packageAdaptation.trim() === "") {
|
|
71
|
+
throw new Error(`Packaged method provenance packageAdaptation must be nonblank`);
|
|
72
|
+
}
|
|
73
|
+
if (!isRecord(raw.upstream)) {
|
|
74
|
+
throw new Error(`Packaged method provenance upstream must be an object`);
|
|
75
|
+
}
|
|
76
|
+
const upstream = raw.upstream;
|
|
77
|
+
for (const key of [
|
|
78
|
+
"repository",
|
|
79
|
+
"path",
|
|
80
|
+
"license",
|
|
81
|
+
"copyright",
|
|
82
|
+
"attribution",
|
|
83
|
+
]) {
|
|
84
|
+
if (typeof upstream[key] !== "string" || upstream[key].trim() === "") {
|
|
85
|
+
throw new Error(`Packaged method provenance upstream.${key} must be nonblank`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (typeof upstream.commit !== "string" || !GIT_COMMIT_RE.test(upstream.commit)) {
|
|
89
|
+
throw new Error(`Packaged method provenance upstream.commit must be a 40-char lowercase git object id`);
|
|
90
|
+
}
|
|
91
|
+
const tag = typeof upstream.tag === "string" && upstream.tag.trim() !== ""
|
|
92
|
+
? upstream.tag.trim()
|
|
93
|
+
: undefined;
|
|
94
|
+
const version = typeof upstream.version === "string" && upstream.version.trim() !== ""
|
|
95
|
+
? upstream.version.trim()
|
|
96
|
+
: undefined;
|
|
97
|
+
if (tag === undefined && version === undefined) {
|
|
98
|
+
throw new Error(`Packaged method provenance upstream must include nonblank tag or version`);
|
|
99
|
+
}
|
|
100
|
+
if (!isRecord(raw.files)) {
|
|
101
|
+
throw new Error(`Packaged method provenance files must be an object`);
|
|
102
|
+
}
|
|
103
|
+
const files = {};
|
|
104
|
+
for (const [rel, entry] of Object.entries(raw.files)) {
|
|
105
|
+
if (!isRecord(entry)) {
|
|
106
|
+
throw new Error(`Packaged method provenance file entry must be an object: ${rel}`);
|
|
107
|
+
}
|
|
108
|
+
if (typeof entry.sha256 !== "string" || !SHA256_RE.test(entry.sha256)) {
|
|
109
|
+
throw new Error(`Packaged method provenance file sha256 invalid: ${rel}`);
|
|
110
|
+
}
|
|
111
|
+
if (typeof entry.byteLength !== "number" ||
|
|
112
|
+
!Number.isInteger(entry.byteLength) ||
|
|
113
|
+
entry.byteLength < 0) {
|
|
114
|
+
throw new Error(`Packaged method provenance file byteLength invalid: ${rel}`);
|
|
115
|
+
}
|
|
116
|
+
if (typeof entry.gitBlob !== "string" || !GIT_BLOB_RE.test(entry.gitBlob)) {
|
|
117
|
+
throw new Error(`Packaged method provenance file gitBlob must be a 40-char lowercase git object id: ${rel}`);
|
|
118
|
+
}
|
|
119
|
+
files[rel] = {
|
|
120
|
+
sha256: entry.sha256,
|
|
121
|
+
byteLength: entry.byteLength,
|
|
122
|
+
gitBlob: entry.gitBlob,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
if (files["SKILL.md"] === undefined) {
|
|
126
|
+
throw new Error(`Packaged method provenance must include SKILL.md`);
|
|
127
|
+
}
|
|
128
|
+
return Object.freeze({
|
|
129
|
+
name: expectedName,
|
|
130
|
+
kind: "role-method-skill",
|
|
131
|
+
packageAdaptation: raw.packageAdaptation,
|
|
132
|
+
upstream: Object.freeze({
|
|
133
|
+
repository: upstream.repository,
|
|
134
|
+
path: upstream.path,
|
|
135
|
+
commit: upstream.commit,
|
|
136
|
+
...(tag === undefined ? {} : { tag }),
|
|
137
|
+
...(version === undefined ? {} : { version }),
|
|
138
|
+
license: upstream.license,
|
|
139
|
+
copyright: upstream.copyright,
|
|
140
|
+
attribution: upstream.attribution,
|
|
141
|
+
}),
|
|
142
|
+
files: Object.freeze(files),
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Load a package-owned method Skill and verify per-file provenance digests.
|
|
147
|
+
* Does not consult HOME or ambient Skill discovery paths.
|
|
148
|
+
*/
|
|
149
|
+
export async function loadPackagedMethodSkillMaterial(packageRoot, name) {
|
|
150
|
+
const rootDirectory = resolvePackagedMethodSkillRoot(packageRoot, name);
|
|
151
|
+
const skillPathConfigured = join(rootDirectory, "SKILL.md");
|
|
152
|
+
const provenancePath = join(rootDirectory, "provenance.json");
|
|
153
|
+
let provenanceRaw;
|
|
154
|
+
try {
|
|
155
|
+
provenanceRaw = await readFile(provenancePath, "utf8");
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
throw new PackagedMethodSkillUnavailableError(name, provenancePath, error);
|
|
159
|
+
}
|
|
160
|
+
let provenanceJson;
|
|
161
|
+
try {
|
|
162
|
+
provenanceJson = JSON.parse(provenanceRaw);
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
throw new Error(`Packaged method provenance is not valid JSON at ${provenancePath}`, {
|
|
166
|
+
cause: error,
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
const provenance = parseProvenance(provenanceJson, name);
|
|
170
|
+
// Verify every declared file digest + independent git blob against package bytes (no network).
|
|
171
|
+
for (const [rel, expected] of Object.entries(provenance.files)) {
|
|
172
|
+
const absolute = join(rootDirectory, rel);
|
|
173
|
+
let bytes;
|
|
174
|
+
try {
|
|
175
|
+
bytes = await readFile(absolute);
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
throw new PackagedMethodSkillUnavailableError(name, absolute, error);
|
|
179
|
+
}
|
|
180
|
+
const actualSha = sha256Hex(bytes);
|
|
181
|
+
const actualBlob = gitBlobOid(bytes);
|
|
182
|
+
if (actualSha !== expected.sha256 ||
|
|
183
|
+
bytes.byteLength !== expected.byteLength ||
|
|
184
|
+
actualBlob !== expected.gitBlob) {
|
|
185
|
+
throw new Error(`Packaged method file digest mismatch for ${name}/${rel}: expected sha256=${expected.sha256} byteLength=${expected.byteLength} gitBlob=${expected.gitBlob}, got sha256=${actualSha} byteLength=${bytes.byteLength} gitBlob=${actualBlob}`);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
let skillPath;
|
|
189
|
+
let raw;
|
|
190
|
+
try {
|
|
191
|
+
skillPath = await realpath(skillPathConfigured);
|
|
192
|
+
raw = await readFile(skillPath, "utf8");
|
|
193
|
+
}
|
|
194
|
+
catch (error) {
|
|
195
|
+
throw new PackagedMethodSkillUnavailableError(name, skillPathConfigured, error);
|
|
196
|
+
}
|
|
197
|
+
const body = stripSkillFrontmatter(raw).trim();
|
|
198
|
+
if (body.length === 0) {
|
|
199
|
+
throw new Error(`Canonical ${name} Skill is empty at ${skillPath}`);
|
|
200
|
+
}
|
|
201
|
+
const companionRelativePaths = REQUIRED_COMPANIONS[name].filter((rel) => provenance.files[rel] !== undefined);
|
|
202
|
+
for (const rel of REQUIRED_COMPANIONS[name]) {
|
|
203
|
+
if (provenance.files[rel] === undefined) {
|
|
204
|
+
throw new Error(`Packaged method ${name} missing required companion in provenance: ${rel}`);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return Object.freeze({
|
|
208
|
+
name,
|
|
209
|
+
rootDirectory,
|
|
210
|
+
skillPath,
|
|
211
|
+
raw,
|
|
212
|
+
body,
|
|
213
|
+
provenance,
|
|
214
|
+
companionRelativePaths: Object.freeze([...companionRelativePaths]),
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Observe one Pi-native packaged method Skill expansion from a user-turn text.
|
|
219
|
+
* Matches the structured `<skill name location>` block format only; rejects ambient
|
|
220
|
+
* home locations that are not in the allowed package path set.
|
|
221
|
+
*/
|
|
222
|
+
export function observePackagedMethodSkillInvocation(text, expected) {
|
|
223
|
+
// Structured skill-block grammar (same shape Pi expands); not free-text classification.
|
|
224
|
+
if (!text.startsWith("<skill name=\""))
|
|
225
|
+
return undefined;
|
|
226
|
+
const nameStart = "<skill name=\"".length;
|
|
227
|
+
const nameEnd = text.indexOf("\"", nameStart);
|
|
228
|
+
if (nameEnd <= nameStart)
|
|
229
|
+
return undefined;
|
|
230
|
+
const name = text.slice(nameStart, nameEnd);
|
|
231
|
+
if (name !== expected.name)
|
|
232
|
+
return undefined;
|
|
233
|
+
const locationMarker = "\" location=\"";
|
|
234
|
+
if (!text.startsWith(locationMarker, nameEnd))
|
|
235
|
+
return undefined;
|
|
236
|
+
const locationStart = nameEnd + locationMarker.length;
|
|
237
|
+
const locationEnd = text.indexOf("\"", locationStart);
|
|
238
|
+
if (locationEnd <= locationStart)
|
|
239
|
+
return undefined;
|
|
240
|
+
const location = text.slice(locationStart, locationEnd);
|
|
241
|
+
const openTail = ">\n";
|
|
242
|
+
if (!text.startsWith(openTail, locationEnd + 1))
|
|
243
|
+
return undefined;
|
|
244
|
+
const closeTag = "\n</skill>";
|
|
245
|
+
const closeAt = text.indexOf(closeTag, locationEnd + 1 + openTail.length);
|
|
246
|
+
if (closeAt === -1)
|
|
247
|
+
return undefined;
|
|
248
|
+
const afterClose = text.slice(closeAt + closeTag.length);
|
|
249
|
+
if (afterClose.length > 0 && !afterClose.startsWith("\n"))
|
|
250
|
+
return undefined;
|
|
251
|
+
if (!expected.allowedLocations.includes(location))
|
|
252
|
+
return undefined;
|
|
253
|
+
return Object.freeze({ name: expected.name, location });
|
|
254
|
+
}
|
|
@@ -10,6 +10,8 @@ import { NOTARY_OUTPUT_TOOL_NAME } from "./notary-contracts.js";
|
|
|
10
10
|
import { COUNTERSIGN_OUTPUT_TOOL_NAME } from "./countersign-contracts.js";
|
|
11
11
|
import { GLEANER_LEFT_OUTPUT_TOOL_NAME } from "./gleaner-left-contracts.js";
|
|
12
12
|
import { INSPECTOR_OUTPUT_TOOL_NAME } from "./inspector-contracts.js";
|
|
13
|
+
import { AUDITOR_OUTPUT_TOOL_NAME } from "./package-contracts/auditor-output.js";
|
|
14
|
+
import { EVIDENCE_CHILD_OUTPUT_TOOL_NAME } from "./package-contracts/evidence-child-output.js";
|
|
13
15
|
import {
|
|
14
16
|
DIARIST_OUTPUT_TOOL_NAME,
|
|
15
17
|
DIARIST_SOURCES_FLAG
|
|
@@ -27,6 +29,19 @@ const INSPECTOR_SESSION_MATERIALS = [
|
|
|
27
29
|
"souls/quality-law.md",
|
|
28
30
|
"souls/gate-output-guide.md"
|
|
29
31
|
];
|
|
32
|
+
const AUDITOR_PUBLIC_SESSION_MATERIALS = [
|
|
33
|
+
"CLAUDE.md",
|
|
34
|
+
"souls/judge-auditor.md",
|
|
35
|
+
"souls/doctor-auditor.md",
|
|
36
|
+
"souls/audit-law.md",
|
|
37
|
+
"souls/quality-law.md"
|
|
38
|
+
];
|
|
39
|
+
const EVIDENCE_CHILD_SESSION_MATERIALS = [
|
|
40
|
+
"CLAUDE.md",
|
|
41
|
+
"souls/evidence-child.md",
|
|
42
|
+
"souls/audit-law.md",
|
|
43
|
+
"souls/quality-law.md"
|
|
44
|
+
];
|
|
30
45
|
const PUBLIC_ROLE_RECORDS = [
|
|
31
46
|
{
|
|
32
47
|
role: "judge",
|
|
@@ -180,6 +195,25 @@ const PUBLIC_ROLE_RECORDS = [
|
|
|
180
195
|
activationStage: "load-and-install",
|
|
181
196
|
sessionMaterials: ["CLAUDE.md", "souls/navigator.md"]
|
|
182
197
|
},
|
|
198
|
+
// #675: 审刑院 / evidence-child are roles like any other — public ak-role entries.
|
|
199
|
+
{
|
|
200
|
+
role: "auditor",
|
|
201
|
+
phases: [null],
|
|
202
|
+
outputTool: AUDITOR_OUTPUT_TOOL_NAME,
|
|
203
|
+
inputFlag: void 0,
|
|
204
|
+
phaseFlag: void 0,
|
|
205
|
+
activationStage: "load-and-install",
|
|
206
|
+
sessionMaterials: AUDITOR_PUBLIC_SESSION_MATERIALS
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
role: "evidence-child",
|
|
210
|
+
phases: [null],
|
|
211
|
+
outputTool: EVIDENCE_CHILD_OUTPUT_TOOL_NAME,
|
|
212
|
+
inputFlag: void 0,
|
|
213
|
+
phaseFlag: void 0,
|
|
214
|
+
activationStage: "load-and-install",
|
|
215
|
+
sessionMaterials: EVIDENCE_CHILD_SESSION_MATERIALS
|
|
216
|
+
},
|
|
183
217
|
// #708 / ADR 0075 `diarist-is-role`: 起居郎 is a seat like any other. The
|
|
184
218
|
// frozen source catalog rides the shared input-flag seam; it is absent for a
|
|
185
219
|
// true-unbound summons (no ticket → no diary).
|
|
@@ -211,6 +245,8 @@ function packagedRoleOutputTool(role) {
|
|
|
211
245
|
return packagedRoleMetadata(role)?.outputTool;
|
|
212
246
|
}
|
|
213
247
|
export {
|
|
248
|
+
AUDITOR_PUBLIC_SESSION_MATERIALS,
|
|
249
|
+
EVIDENCE_CHILD_SESSION_MATERIALS,
|
|
214
250
|
INSPECTOR_SESSION_MATERIALS,
|
|
215
251
|
NOTARY_SESSION_MATERIALS,
|
|
216
252
|
PACKAGED_ROLE_REGISTRY,
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { lstat } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { resolveBookKeyFromGit } from "../activation-ledger-git.js";
|
|
4
|
+
import { activationBookDirectory, resolveActivationLedgerHome, } from "../activation-ledger-topology.js";
|
|
5
|
+
function encode(coordinates) {
|
|
6
|
+
return coordinates;
|
|
7
|
+
}
|
|
8
|
+
export function issuePiDurablePrincipalCoordinates(request) {
|
|
9
|
+
const ledgerHome = resolveActivationLedgerHome(request.home);
|
|
10
|
+
const bookKey = resolveBookKeyFromGit(request.cwd);
|
|
11
|
+
const runDirectory = join(activationBookDirectory(ledgerHome, bookKey), "runs", `${request.runId}@${request.role}`);
|
|
12
|
+
const sessionDirectory = join(runDirectory, "session");
|
|
13
|
+
return {
|
|
14
|
+
ledgerHome,
|
|
15
|
+
bookKey,
|
|
16
|
+
runDirectory,
|
|
17
|
+
sessionDirectory,
|
|
18
|
+
sessionFile: join(sessionDirectory, "session.jsonl"),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/** Pi's durable-principal codec and availability authority. */
|
|
22
|
+
export const piDurablePrincipalAuthority = {
|
|
23
|
+
issue(request) {
|
|
24
|
+
const coordinates = issuePiDurablePrincipalCoordinates(request);
|
|
25
|
+
return encode({
|
|
26
|
+
sessionDirectory: coordinates.sessionDirectory,
|
|
27
|
+
sessionFile: coordinates.sessionFile,
|
|
28
|
+
});
|
|
29
|
+
},
|
|
30
|
+
seal(coordinates) {
|
|
31
|
+
return encode({
|
|
32
|
+
sessionDirectory: coordinates.sessionDirectory,
|
|
33
|
+
sessionFile: coordinates.sessionFile,
|
|
34
|
+
});
|
|
35
|
+
},
|
|
36
|
+
decode(value) {
|
|
37
|
+
const record = value;
|
|
38
|
+
if (record === null || typeof record !== "object") {
|
|
39
|
+
throw new Error("durable principal payload is missing");
|
|
40
|
+
}
|
|
41
|
+
if (typeof record.sessionDirectory !== "string" || record.sessionDirectory.trim() === "") {
|
|
42
|
+
throw new Error("durable principal session directory is missing");
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
sessionDirectory: record.sessionDirectory,
|
|
46
|
+
sessionFile: typeof record.sessionFile === "string" && record.sessionFile.trim() !== ""
|
|
47
|
+
? record.sessionFile
|
|
48
|
+
: join(record.sessionDirectory, "session.jsonl"),
|
|
49
|
+
};
|
|
50
|
+
},
|
|
51
|
+
async isAvailable(principal) {
|
|
52
|
+
const { sessionFile } = this.decode(principal);
|
|
53
|
+
try {
|
|
54
|
+
const stat = await lstat(sessionFile);
|
|
55
|
+
return stat.isFile() && !stat.isSymbolicLink();
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
};
|
|
@@ -129,7 +129,7 @@ function enrichStreamEvent(event, observedHttpStatus) {
|
|
|
129
129
|
}
|
|
130
130
|
return event;
|
|
131
131
|
}
|
|
132
|
-
async function
|
|
132
|
+
async function openPiInProcessSession(options) {
|
|
133
133
|
const label = options.label ?? "Institutional sub-session";
|
|
134
134
|
const selection = options.selection;
|
|
135
135
|
let scratchDir;
|
|
@@ -457,10 +457,17 @@ async function openPiInstitutionalSession(options) {
|
|
|
457
457
|
});
|
|
458
458
|
}
|
|
459
459
|
}
|
|
460
|
+
const requestedThinking = selection.thinking;
|
|
461
|
+
const priorEntries = typeof sessionManager.getEntries === "function" ? sessionManager.getEntries() : [];
|
|
462
|
+
const reusedSession = priorEntries.some((entry) => {
|
|
463
|
+
if (typeof entry !== "object" || entry === null) return false;
|
|
464
|
+
const type = entry.type;
|
|
465
|
+
return type === "message" || type === "model_change" || type === "thinking_level_change";
|
|
466
|
+
});
|
|
460
467
|
const { session } = await createAgentSession({
|
|
461
468
|
cwd: options.cwd,
|
|
462
469
|
model: effectiveModel,
|
|
463
|
-
...
|
|
470
|
+
...requestedThinking === void 0 ? {} : { thinkingLevel: requestedThinking },
|
|
464
471
|
modelRuntime: runtime,
|
|
465
472
|
sessionManager,
|
|
466
473
|
settingsManager: settings,
|
|
@@ -470,9 +477,21 @@ async function openPiInstitutionalSession(options) {
|
|
|
470
477
|
...options.toolsAllowlist === void 0 ? {} : { tools: options.toolsAllowlist },
|
|
471
478
|
...customTools.length === 0 ? {} : { customTools }
|
|
472
479
|
});
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
480
|
+
if (reusedSession) {
|
|
481
|
+
try {
|
|
482
|
+
await session.setModel(effectiveModel);
|
|
483
|
+
if (requestedThinking !== void 0) {
|
|
484
|
+
session.setThinkingLevel(requestedThinking);
|
|
485
|
+
}
|
|
486
|
+
} catch (error) {
|
|
487
|
+
session.dispose();
|
|
488
|
+
throw withTypedReason(
|
|
489
|
+
error instanceof Error ? error : new Error(
|
|
490
|
+
`${label} failed to apply seat model/thinking for ${selection.provider}/${selection.model}`
|
|
491
|
+
),
|
|
492
|
+
requestedThinking !== void 0 ? "thinking" : "model"
|
|
493
|
+
);
|
|
494
|
+
}
|
|
476
495
|
}
|
|
477
496
|
const listeners = /* @__PURE__ */ new Set();
|
|
478
497
|
const accumulatedUsage = emptyUsage();
|
|
@@ -637,5 +656,5 @@ async function openPiInstitutionalSession(options) {
|
|
|
637
656
|
}
|
|
638
657
|
export {
|
|
639
658
|
DEFAULT_COMPLIANCE_IDLE_MAX_RETRIES,
|
|
640
|
-
|
|
659
|
+
openPiInProcessSession
|
|
641
660
|
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { hasUpstreamErrorTestimony, projectConfirmedRemotePayload, } from "../upstream-error-testimony.js";
|
|
2
|
+
export { hasUpstreamErrorTestimony } from "../upstream-error-testimony.js";
|
|
3
|
+
function nonEmptyString(value) {
|
|
4
|
+
return typeof value === "string" && value.trim() !== "" ? value : undefined;
|
|
5
|
+
}
|
|
6
|
+
function sessionStopDetails(input) {
|
|
7
|
+
const details = {};
|
|
8
|
+
const errorMessage = nonEmptyString(input.errorMessage);
|
|
9
|
+
if (errorMessage !== undefined)
|
|
10
|
+
details.errorMessage = errorMessage;
|
|
11
|
+
const api = nonEmptyString(input.api);
|
|
12
|
+
if (api !== undefined)
|
|
13
|
+
details.api = api;
|
|
14
|
+
const rawStopReason = nonEmptyString(input.rawStopReason);
|
|
15
|
+
if (rawStopReason !== undefined)
|
|
16
|
+
details.rawStopReason = rawStopReason;
|
|
17
|
+
const testimony = hasUpstreamErrorTestimony(input);
|
|
18
|
+
if (testimony) {
|
|
19
|
+
const provider = nonEmptyString(input.provider);
|
|
20
|
+
if (provider !== undefined)
|
|
21
|
+
details.provider = provider;
|
|
22
|
+
const model = nonEmptyString(input.model);
|
|
23
|
+
if (model !== undefined)
|
|
24
|
+
details.model = model;
|
|
25
|
+
}
|
|
26
|
+
if (typeof input.httpStatus === "number")
|
|
27
|
+
details.httpStatus = input.httpStatus;
|
|
28
|
+
if (input.diagnostics !== undefined)
|
|
29
|
+
details.diagnostics = input.diagnostics;
|
|
30
|
+
// SDK structured payload fields: project only when held on a confirmed-remote node.
|
|
31
|
+
if (testimony)
|
|
32
|
+
Object.assign(details, projectConfirmedRemotePayload(input));
|
|
33
|
+
return details;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Project a native session assistant stop onto the existing knownFailure chain.
|
|
37
|
+
* Classification follows two-way testimony: typed HTTP status or SDK structure
|
|
38
|
+
* keeps provider; stopReason, configured provider/model, or errorMessage prose
|
|
39
|
+
* alone is the existing unrecognized value. Present upstream payload is preserved
|
|
40
|
+
* in details without rewriting; missing fields are omitted.
|
|
41
|
+
*/
|
|
42
|
+
export function knownFailureFromProviderStop(input) {
|
|
43
|
+
if (input.stopReason !== "error" && input.stopReason !== "aborted")
|
|
44
|
+
return undefined;
|
|
45
|
+
const diagnostic = nonEmptyString(input.errorMessage);
|
|
46
|
+
const details = sessionStopDetails(input);
|
|
47
|
+
return {
|
|
48
|
+
cause: hasUpstreamErrorTestimony(input) ? "provider" : "unrecognized",
|
|
49
|
+
...(diagnostic === undefined ? {} : { diagnostic }),
|
|
50
|
+
...(Object.keys(details).length === 0 ? {} : { details }),
|
|
51
|
+
};
|
|
52
|
+
}
|