@akagilnc/pi-workflow-roles 0.1.3414 → 0.1.3439
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/archivist-record-entry.js +21 -12
- package/dist/archivist-record-topology.js +20 -0
- package/dist/auditor-dossier-tool.js +67 -76
- package/dist/canonical-json.js +66 -69
- package/dist/compliance-transport.js +99 -86
- package/dist/countersign-contracts.js +23 -25
- package/dist/doctor-contracts.js +169 -145
- package/dist/engine-detour-tool.js +83 -87
- package/dist/engine-detour.js +148 -183
- package/dist/evidence-child-executor.js +10 -1
- package/dist/exact-utf8.js +11 -10
- package/dist/git-object-id.js +10 -5
- package/dist/gleaner-left-contracts.js +33 -35
- package/dist/grok/production-host.js +229 -118
- package/dist/inspector-contracts.js +28 -31
- package/dist/institutional-resolution.js +101 -104
- package/dist/ledger-session-read.js +241 -0
- package/dist/merger-contracts.js +66 -56
- package/dist/notary-contracts.js +91 -100
- package/dist/open-tool-schema.js +32 -31
- package/dist/package-contracts/collector-output.js +56 -43
- package/dist/package-contracts/fixer-output.js +52 -50
- package/dist/package-contracts/fixer-packet.js +67 -64
- package/dist/package-contracts/gatekeeper-output.js +48 -56
- package/dist/package-contracts/judge-output.js +23 -20
- package/dist/package-contracts/navigator-output.js +35 -40
- package/dist/package-contracts/reviewer-output.js +94 -110
- package/dist/package-contracts/terminating-infrastructure.js +62 -90
- package/dist/package-contracts/worker-output.js +30 -11
- package/dist/package-resources/engine-material.js +58 -94
- package/dist/public-cli/config.js +420 -484
- package/dist/public-cli/main.js +1219 -524
- package/dist/public-cli/registry.js +107 -114
- package/dist/receipt-delivery-policy.js +74 -76
- package/dist/session-opening-materials.js +44 -47
- package/dist/sha256.js +5 -3
- package/dist/sitian-appender.js +204 -210
- package/dist/sitian-contracts.js +15 -19
- package/dist/sitian-facade.js +5 -10
- package/dist/sitian-reader.js +37 -46
- package/dist/stream-idle-guard.js +63 -71
- package/dist/ticket-seat-memory.js +244 -0
- package/package.json +1 -1
- package/scripts/build-package.mjs +41 -0
- package/src/analyst-gate-cycles-read.ts +152 -83
- package/src/analyst-ledger.ts +170 -43
- package/src/archivist-record-entry.ts +32 -11
- package/src/archivist-record-topology.ts +39 -0
- package/src/evidence-child-executor.ts +14 -1
- package/src/grok/production-host.ts +44 -9
- package/src/host-contracts.ts +18 -0
- package/src/host-transition-prior-native.ts +8 -1
- package/src/ledger-session-read.ts +56 -0
- package/src/pi/durable-principal.ts +6 -0
- package/src/public-cli/inspector-run.ts +21 -10
- package/src/public-cli/invocation.ts +4 -20
- package/src/public-cli/notary-run.ts +21 -4
- package/src/public-cli/post-admission.ts +333 -42
- package/src/public-cli/settlement.ts +266 -81
- package/src/session-opening-materials.ts +4 -2
- package/src/ticket-seat-memory.ts +454 -0
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { createHash } from "node:crypto";
|
|
2
1
|
import { existsSync, readFileSync, realpathSync, writeFileSync } from "node:fs";
|
|
3
2
|
import { dirname, resolve, join } from "node:path";
|
|
4
3
|
import { SessionManager } from "@earendil-works/pi-coding-agent";
|
|
@@ -12,6 +11,8 @@ import {
|
|
|
12
11
|
physicallyContainedIn,
|
|
13
12
|
resolveActivationLedgerHomeForPath
|
|
14
13
|
} from "./activation-ledger-topology.js";
|
|
14
|
+
import { subjectKeyedRecordDirectory } from "./archivist-record-topology.js";
|
|
15
|
+
import { subjectKeyedRecordDirectory as subjectKeyedRecordDirectory2 } from "./archivist-record-topology.js";
|
|
15
16
|
const CURRENT_SESSION_LEDGER = "current-session.json";
|
|
16
17
|
function readCurrentSession(sessionDir) {
|
|
17
18
|
const ledger = join(sessionDir, CURRENT_SESSION_LEDGER);
|
|
@@ -73,22 +74,22 @@ function assertRecentFinalFileUnderSessionDir(sessionDir, recentFile) {
|
|
|
73
74
|
);
|
|
74
75
|
}
|
|
75
76
|
}
|
|
76
|
-
function
|
|
77
|
+
function createRecordSessionOpen(options) {
|
|
77
78
|
const cwd = options.cwd;
|
|
78
79
|
const parentFile = options.parent?.getSessionFile();
|
|
79
80
|
const ledgerHome = resolveActivationLedgerHomeForPath(parentFile);
|
|
80
81
|
let sessionDir;
|
|
81
82
|
let parentSession;
|
|
82
83
|
if (options.subject !== void 0) {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
options.
|
|
87
|
-
|
|
88
|
-
);
|
|
84
|
+
sessionDir = subjectKeyedRecordDirectory({
|
|
85
|
+
cwd,
|
|
86
|
+
kind: options.kind,
|
|
87
|
+
subject: options.subject,
|
|
88
|
+
...parentFile === void 0 || parentFile.length === 0 ? {} : { parentSessionFile: parentFile }
|
|
89
|
+
});
|
|
89
90
|
parentSession = parentFile && parentFile.length > 0 ? parentFile : void 0;
|
|
90
91
|
} else if (parentFile === void 0 || parentFile.length === 0) {
|
|
91
|
-
return SessionManager.inMemory(cwd);
|
|
92
|
+
return { session: SessionManager.inMemory(cwd), resumed: false };
|
|
92
93
|
} else {
|
|
93
94
|
const parentResolved = resolve(parentFile);
|
|
94
95
|
sessionDir = physicallyContainedIn(ledgerHome, parentResolved) ? join(dirname(parentResolved), options.kind) : join(activationBookDirectory(ledgerHome, resolveBookKeyFromGit(cwd)), options.kind);
|
|
@@ -100,7 +101,10 @@ function createRecordSession(options) {
|
|
|
100
101
|
if (mayResumeSameNest && nestAlreadyExists) {
|
|
101
102
|
const recentFile = readCurrentSession(sessionDir);
|
|
102
103
|
assertRecentFinalFileUnderSessionDir(sessionDir, recentFile);
|
|
103
|
-
return
|
|
104
|
+
return {
|
|
105
|
+
session: SessionManager.open(recentFile, sessionDir, cwd),
|
|
106
|
+
resumed: true
|
|
107
|
+
};
|
|
104
108
|
}
|
|
105
109
|
const session = SessionManager.create(
|
|
106
110
|
cwd,
|
|
@@ -121,9 +125,14 @@ function createRecordSession(options) {
|
|
|
121
125
|
writeCurrentSession(sessionDir, file);
|
|
122
126
|
}
|
|
123
127
|
}
|
|
124
|
-
return session;
|
|
128
|
+
return { session, resumed: false };
|
|
129
|
+
}
|
|
130
|
+
function createRecordSession(options) {
|
|
131
|
+
return createRecordSessionOpen(options).session;
|
|
125
132
|
}
|
|
126
133
|
export {
|
|
127
134
|
WORKER_SUBMISSION_GATE_KIND,
|
|
128
|
-
createRecordSession
|
|
135
|
+
createRecordSession,
|
|
136
|
+
createRecordSessionOpen,
|
|
137
|
+
subjectKeyedRecordDirectory2 as subjectKeyedRecordDirectory
|
|
129
138
|
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { resolveBookKeyFromGit } from "./activation-ledger-git.js";
|
|
4
|
+
import {
|
|
5
|
+
activationBookDirectory,
|
|
6
|
+
resolveActivationLedgerHome,
|
|
7
|
+
resolveActivationLedgerHomeForPath
|
|
8
|
+
} from "./activation-ledger-topology.js";
|
|
9
|
+
function subjectKeyedRecordDirectory(input) {
|
|
10
|
+
const ledgerHome = input.parentSessionFile !== void 0 && input.parentSessionFile.length > 0 ? resolveActivationLedgerHomeForPath(input.parentSessionFile) : resolveActivationLedgerHome(input.home);
|
|
11
|
+
const digest = createHash("sha256").update(input.subject).digest("hex").slice(0, 32);
|
|
12
|
+
return join(
|
|
13
|
+
activationBookDirectory(ledgerHome, resolveBookKeyFromGit(input.cwd)),
|
|
14
|
+
input.kind,
|
|
15
|
+
digest
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
export {
|
|
19
|
+
subjectKeyedRecordDirectory
|
|
20
|
+
};
|
|
@@ -1,87 +1,78 @@
|
|
|
1
1
|
import { mkdirSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { dirname, join, resolve } from "node:path";
|
|
3
3
|
import { Type } from "typebox";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export const GATE_SUBMISSION_CANDIDATE_FILE = "gate-submission-candidate.json";
|
|
4
|
+
const AUDITOR_DOSSIER_TOOL_NAME = "ak_get_run_dossier";
|
|
5
|
+
const GATE_SUBMISSION_CANDIDATE_FILE = "gate-submission-candidate.json";
|
|
7
6
|
function isRecord(value) {
|
|
8
|
-
|
|
7
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9
8
|
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
return undefined;
|
|
15
|
-
// Sole layout: <run>/session/session.jsonl → climb two levels to the run directory.
|
|
16
|
-
return resolve(dirname(dirname(sessionFile)));
|
|
9
|
+
function auditorRunDirectory(context) {
|
|
10
|
+
const sessionFile = context.sessionManager?.getSessionFile?.();
|
|
11
|
+
if (sessionFile === void 0) return void 0;
|
|
12
|
+
return resolve(dirname(dirname(sessionFile)));
|
|
17
13
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
if (message.role !== "assistant" || !Array.isArray(message.content))
|
|
30
|
-
continue;
|
|
31
|
-
for (const part of message.content) {
|
|
32
|
-
if (isRecord(part) && part.type === "toolCall") {
|
|
33
|
-
return entry;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
14
|
+
function readLatestToolCallLeaf(context) {
|
|
15
|
+
const entries = [...context.sessionManager?.getEntries?.() ?? []];
|
|
16
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
17
|
+
const entry = entries[i];
|
|
18
|
+
if (!isRecord(entry) || entry.type !== "message" || !isRecord(entry.message)) continue;
|
|
19
|
+
const message = entry.message;
|
|
20
|
+
if (message.role !== "assistant" || !Array.isArray(message.content)) continue;
|
|
21
|
+
for (const part of message.content) {
|
|
22
|
+
if (isRecord(part) && part.type === "toolCall") {
|
|
23
|
+
return entry;
|
|
24
|
+
}
|
|
36
25
|
}
|
|
37
|
-
|
|
26
|
+
}
|
|
27
|
+
return void 0;
|
|
38
28
|
}
|
|
39
|
-
|
|
40
|
-
|
|
29
|
+
function gateSubmissionCandidatePath(runDirectory) {
|
|
30
|
+
return join(runDirectory, "artifacts", GATE_SUBMISSION_CANDIDATE_FILE);
|
|
41
31
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
return undefined;
|
|
51
|
-
const path = gateSubmissionCandidatePath(runDirectory);
|
|
52
|
-
mkdirSync(dirname(path), { recursive: true });
|
|
53
|
-
writeFileSync(path, `${JSON.stringify(leaf)}\n`, "utf8");
|
|
54
|
-
return path;
|
|
32
|
+
function persistGateSubmissionCandidate(runDirectory, context) {
|
|
33
|
+
const leaf = readLatestToolCallLeaf(context);
|
|
34
|
+
if (leaf === void 0) return void 0;
|
|
35
|
+
const path = gateSubmissionCandidatePath(runDirectory);
|
|
36
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
37
|
+
writeFileSync(path, `${JSON.stringify(leaf)}
|
|
38
|
+
`, "utf8");
|
|
39
|
+
return path;
|
|
55
40
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
};
|
|
85
|
-
},
|
|
86
|
-
};
|
|
41
|
+
function createAuditorDossierTool(runDirectory, options) {
|
|
42
|
+
return {
|
|
43
|
+
name: AUDITOR_DOSSIER_TOOL_NAME,
|
|
44
|
+
description: "\u5B9A\u4F4D\u672C\u5BA1\u8BA1\u5E2D\u7ED1\u5B9A\u7684 run \u5377\u5B97\u53CA\u5176\u8BC1\u636E\u5165\u53E3\u3002",
|
|
45
|
+
parameters: Type.Object({}, { additionalProperties: false }),
|
|
46
|
+
async execute(_id, _params) {
|
|
47
|
+
if (runDirectory === void 0) {
|
|
48
|
+
return {
|
|
49
|
+
content: [{ type: "text", text: "\u672C\u5BA1\u8BA1\u5E2D\u65E0\u7ED1\u5B9A run \u5377\u5B97\u8BB0\u5F55\u3002" }],
|
|
50
|
+
details: void 0
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
const sessionPath = join(runDirectory, "session", "session.jsonl");
|
|
54
|
+
const submissionCandidate = options?.submissionCandidate;
|
|
55
|
+
const details = {
|
|
56
|
+
runDirectory,
|
|
57
|
+
admittedRequest: join(runDirectory, "admitted-request.json"),
|
|
58
|
+
parentSessionCandidate: submissionCandidate ?? sessionPath,
|
|
59
|
+
attachments: join(runDirectory, "attachments"),
|
|
60
|
+
artifacts: join(runDirectory, "artifacts"),
|
|
61
|
+
...submissionCandidate === void 0 ? {} : { submissionCandidate }
|
|
62
|
+
};
|
|
63
|
+
return {
|
|
64
|
+
content: [{ type: "text", text: JSON.stringify(details) }],
|
|
65
|
+
details
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
};
|
|
87
69
|
}
|
|
70
|
+
export {
|
|
71
|
+
AUDITOR_DOSSIER_TOOL_NAME,
|
|
72
|
+
GATE_SUBMISSION_CANDIDATE_FILE,
|
|
73
|
+
auditorRunDirectory,
|
|
74
|
+
createAuditorDossierTool,
|
|
75
|
+
gateSubmissionCandidatePath,
|
|
76
|
+
persistGateSubmissionCandidate,
|
|
77
|
+
readLatestToolCallLeaf
|
|
78
|
+
};
|
package/dist/canonical-json.js
CHANGED
|
@@ -1,78 +1,75 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
reason;
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
const CANONICAL_JSON_VALIDATION_ERROR_CODE = "canonical-json-invalid";
|
|
2
|
+
class CanonicalJsonValidationError extends Error {
|
|
3
|
+
constructor(path, reason) {
|
|
4
|
+
super(`Canonical JSON validation failed at ${path}: ${reason}`);
|
|
5
|
+
this.path = path;
|
|
6
|
+
this.reason = reason;
|
|
7
|
+
this.name = "CanonicalJsonValidationError";
|
|
8
|
+
}
|
|
9
|
+
path;
|
|
10
|
+
reason;
|
|
11
|
+
code = CANONICAL_JSON_VALIDATION_ERROR_CODE;
|
|
12
12
|
}
|
|
13
13
|
function childPath(path, segment) {
|
|
14
|
-
|
|
14
|
+
return `${path}/${String(segment).replaceAll("~", "~0").replaceAll("/", "~1")}`;
|
|
15
15
|
}
|
|
16
16
|
function ownStringKeys(value, path) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
const keys = Reflect.ownKeys(value);
|
|
18
|
+
if (keys.some((key) => typeof key === "symbol")) {
|
|
19
|
+
throw new CanonicalJsonValidationError(childPath(path, "<symbol>"), "symbol-keyed member is not a JSON member");
|
|
20
|
+
}
|
|
21
|
+
return keys;
|
|
22
22
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
if (extraKey !== undefined)
|
|
53
|
-
throw new CanonicalJsonValidationError(childPath(path, extraKey), "non-index array member is not a JSON member");
|
|
54
|
-
const values = [];
|
|
55
|
-
for (let index = 0; index < item.length; index += 1) {
|
|
56
|
-
if (!Object.hasOwn(item, index))
|
|
57
|
-
throw new CanonicalJsonValidationError(childPath(path, index), "sparse array slot is not a JSON value");
|
|
58
|
-
values.push(serialize(item[index], childPath(path, index)));
|
|
59
|
-
}
|
|
60
|
-
return `[${values.join(",")}]`;
|
|
61
|
-
}
|
|
62
|
-
const prototype = Object.getPrototypeOf(item);
|
|
63
|
-
if (prototype !== Object.prototype && prototype !== null)
|
|
64
|
-
throw new CanonicalJsonValidationError(path, "object must be a plain record");
|
|
65
|
-
return `{${ownStringKeys(item, path).sort().map((key) => `${JSON.stringify(key)}:${serialize(item[key], childPath(path, key))}`).join(",")}}`;
|
|
66
|
-
}
|
|
67
|
-
finally {
|
|
68
|
-
ancestors.delete(item);
|
|
69
|
-
}
|
|
23
|
+
function canonicalJson(value) {
|
|
24
|
+
const ancestors = /* @__PURE__ */ new WeakSet();
|
|
25
|
+
const serialize = (item, path) => {
|
|
26
|
+
if (item === null) return "null";
|
|
27
|
+
switch (typeof item) {
|
|
28
|
+
case "boolean":
|
|
29
|
+
case "string":
|
|
30
|
+
return JSON.stringify(item);
|
|
31
|
+
case "number":
|
|
32
|
+
if (!Number.isFinite(item)) throw new CanonicalJsonValidationError(path, "number must be finite");
|
|
33
|
+
return JSON.stringify(item);
|
|
34
|
+
case "undefined":
|
|
35
|
+
case "function":
|
|
36
|
+
case "symbol":
|
|
37
|
+
case "bigint":
|
|
38
|
+
throw new CanonicalJsonValidationError(path, `${typeof item} is not a JSON value`);
|
|
39
|
+
case "object": {
|
|
40
|
+
if (ancestors.has(item)) throw new CanonicalJsonValidationError(path, "cycle is not a JSON value");
|
|
41
|
+
ancestors.add(item);
|
|
42
|
+
try {
|
|
43
|
+
if (Array.isArray(item)) {
|
|
44
|
+
if (Object.getPrototypeOf(item) !== Array.prototype) throw new CanonicalJsonValidationError(path, "array must not be a custom object");
|
|
45
|
+
const keys = ownStringKeys(item, path);
|
|
46
|
+
const extraKey = keys.find((key) => key !== "length" && (!/^(0|[1-9][0-9]*)$/.test(key) || Number(key) >= item.length));
|
|
47
|
+
if (extraKey !== void 0) throw new CanonicalJsonValidationError(childPath(path, extraKey), "non-index array member is not a JSON member");
|
|
48
|
+
const values = [];
|
|
49
|
+
for (let index = 0; index < item.length; index += 1) {
|
|
50
|
+
if (!Object.hasOwn(item, index)) throw new CanonicalJsonValidationError(childPath(path, index), "sparse array slot is not a JSON value");
|
|
51
|
+
values.push(serialize(item[index], childPath(path, index)));
|
|
70
52
|
}
|
|
53
|
+
return `[${values.join(",")}]`;
|
|
54
|
+
}
|
|
55
|
+
const prototype = Object.getPrototypeOf(item);
|
|
56
|
+
if (prototype !== Object.prototype && prototype !== null) throw new CanonicalJsonValidationError(path, "object must be a plain record");
|
|
57
|
+
return `{${ownStringKeys(item, path).sort().map((key) => `${JSON.stringify(key)}:${serialize(item[key], childPath(path, key))}`).join(",")}}`;
|
|
58
|
+
} finally {
|
|
59
|
+
ancestors.delete(item);
|
|
71
60
|
}
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
throw new Error("Unreachable canonical JSON value type");
|
|
64
|
+
};
|
|
65
|
+
return serialize(value, "$");
|
|
75
66
|
}
|
|
76
|
-
|
|
77
|
-
|
|
67
|
+
function canonicalJsonBytes(value) {
|
|
68
|
+
return new TextEncoder().encode(canonicalJson(value));
|
|
78
69
|
}
|
|
70
|
+
export {
|
|
71
|
+
CANONICAL_JSON_VALIDATION_ERROR_CODE,
|
|
72
|
+
CanonicalJsonValidationError,
|
|
73
|
+
canonicalJson,
|
|
74
|
+
canonicalJsonBytes
|
|
75
|
+
};
|
|
@@ -1,98 +1,111 @@
|
|
|
1
1
|
import { Type } from "typebox";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
executeAuditorChild
|
|
4
|
+
} from "./evidence-child-executor.js";
|
|
3
5
|
import { createAuditorDossierTool } from "./auditor-dossier-tool.js";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
: observation.kind;
|
|
17
|
-
super(`Compliance candidate unreadable: ${detail}`);
|
|
18
|
-
this.name = "ComplianceCandidateUnreadableError";
|
|
19
|
-
this.observation = observation;
|
|
20
|
-
this.candidate = candidate;
|
|
21
|
-
if (usage !== undefined)
|
|
22
|
-
this.usage = usage;
|
|
23
|
-
}
|
|
6
|
+
class ComplianceCandidateUnreadableError extends Error {
|
|
7
|
+
observation;
|
|
8
|
+
candidate;
|
|
9
|
+
usage;
|
|
10
|
+
constructor(observation, candidate, usage) {
|
|
11
|
+
const detail = observation.kind === "non-object-arguments" ? `${observation.kind}:${observation.type}` : observation.kind === "object-status-unreadable" ? `${observation.kind}:${observation.status}` : observation.kind === "missing-subject" ? `${observation.kind}:${observation.subject}` : observation.kind;
|
|
12
|
+
super(`Compliance candidate unreadable: ${detail}`);
|
|
13
|
+
this.name = "ComplianceCandidateUnreadableError";
|
|
14
|
+
this.observation = observation;
|
|
15
|
+
this.candidate = candidate;
|
|
16
|
+
if (usage !== void 0) this.usage = usage;
|
|
17
|
+
}
|
|
24
18
|
}
|
|
25
|
-
|
|
26
|
-
export const AUDITOR_DOSSIER_PROMPT = "本 run 卷宗已就绪。";
|
|
19
|
+
const AUDITOR_DOSSIER_PROMPT = "\u672C run \u5377\u5B97\u5DF2\u5C31\u7EEA\u3002";
|
|
27
20
|
const nonblank = Type.String({ minLength: 1, pattern: "\\S" });
|
|
28
21
|
const decisionGateSchema = Type.Object({ question: nonblank, options: Type.Array(nonblank, { minItems: 1 }) }, { additionalProperties: false });
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
return { name, description, parameters: complianceDecisionSchema, async execute(_id, params) { return { content: [{ type: "text", text: "审计决议已收" }], details: params, terminate: true }; } };
|
|
22
|
+
const complianceDecisionSchema = Type.Object({ status: Type.Unknown({ description: "pass | revise | escalate \u2014 \u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8" }), violations: Type.Array(nonblank, { description: "\u89C2\u5BDF\u5230\u7684\u5408\u89C4\u8FDD\u89C4" }), conflicts: Type.Array(nonblank, { description: "\u672A\u51B3\u6743\u5A01\u6216\u6267\u884C\u51B2\u7A81" }), decisionGate: Type.Union([decisionGateSchema, Type.Null()], { description: "\u5347\u7EA7\u95EE\u9898\u4E0E\u53EF\u9009\u9009\u9879" }) }, { additionalProperties: true, required: [] });
|
|
23
|
+
function createComplianceDecisionTool(name, description) {
|
|
24
|
+
return { name, description, parameters: complianceDecisionSchema, async execute(_id, params) {
|
|
25
|
+
return { content: [{ type: "text", text: "\u5BA1\u8BA1\u51B3\u8BAE\u5DF2\u6536" }], details: params, terminate: true };
|
|
26
|
+
} };
|
|
35
27
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
28
|
+
const COMPLIANCE_RESPONSE_ENTRY_TYPE = "ak_compliance_response";
|
|
29
|
+
const AUDITOR_PARENT_ATTEMPT_BINDING_ENTRY_TYPE = "ak_auditor_parent_attempt_binding";
|
|
30
|
+
const AUDITOR_COMPLIANCE_FAILURE_ENTRY_TYPE = "ak_auditor_compliance_failure";
|
|
39
31
|
import { attachDirectErrnoCode, sitianReport } from "./sitian-facade.js";
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
32
|
+
class ComplianceResponseRetentionError extends Error {
|
|
33
|
+
constructor(message, options) {
|
|
34
|
+
super(message, options);
|
|
35
|
+
this.name = "ComplianceResponseRetentionError";
|
|
36
|
+
attachDirectErrnoCode(this, options?.cause);
|
|
37
|
+
}
|
|
46
38
|
}
|
|
47
39
|
function retainComplianceResponse(context, response) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
40
|
+
try {
|
|
41
|
+
sitianReport({
|
|
42
|
+
level: "event",
|
|
43
|
+
kind: "auditor",
|
|
44
|
+
cwd: context.cwd,
|
|
45
|
+
sessionParent: context.sessionManager.getSessionFile(),
|
|
46
|
+
payload: { version: 1, response },
|
|
47
|
+
source: "compliance-transport"
|
|
48
|
+
});
|
|
49
|
+
} catch (error) {
|
|
50
|
+
throw new ComplianceResponseRetentionError(
|
|
51
|
+
`compliance response retention failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
52
|
+
{ cause: error }
|
|
53
|
+
);
|
|
54
|
+
}
|
|
61
55
|
}
|
|
62
|
-
function readListField(value) {
|
|
63
|
-
|
|
64
|
-
if (typeof arguments_ !== "object" || arguments_ === null || Array.isArray(arguments_)) {
|
|
65
|
-
throw new ComplianceCandidateUnreadableError({ kind: "non-object-arguments", type: arguments_ === null ? "null" : Array.isArray(arguments_) ? "array" : typeof arguments_ }, arguments_, usage);
|
|
66
|
-
}
|
|
67
|
-
const args = arguments_;
|
|
68
|
-
const status = args.status;
|
|
69
|
-
if (status === "pass")
|
|
70
|
-
return { status, ...(usage === undefined ? {} : { usage }) };
|
|
71
|
-
if (status === "revise")
|
|
72
|
-
return { status, violations: readListField(args.violations), ...(usage === undefined ? {} : { usage }) };
|
|
73
|
-
if (status === "escalate")
|
|
74
|
-
return { status, ...(Object.hasOwn(args, "conflicts") ? { conflicts: args.conflicts } : {}), ...(Object.hasOwn(args, "decisionGate") ? { decisionGate: args.decisionGate } : {}), ...(usage === undefined ? {} : { usage }) };
|
|
75
|
-
throw new ComplianceCandidateUnreadableError({ kind: "object-status-unreadable", status: status === undefined ? "missing" : "unknown" }, arguments_, usage);
|
|
56
|
+
function readListField(value) {
|
|
57
|
+
return Array.isArray(value) ? value : value === void 0 ? [] : [value];
|
|
76
58
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
59
|
+
function readComplianceCandidate(arguments_, usage) {
|
|
60
|
+
if (typeof arguments_ !== "object" || arguments_ === null || Array.isArray(arguments_)) {
|
|
61
|
+
throw new ComplianceCandidateUnreadableError(
|
|
62
|
+
{ kind: "non-object-arguments", type: arguments_ === null ? "null" : Array.isArray(arguments_) ? "array" : typeof arguments_ },
|
|
63
|
+
arguments_,
|
|
64
|
+
usage
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
const args = arguments_;
|
|
68
|
+
const status = args.status;
|
|
69
|
+
if (status === "pass") return { status, ...usage === void 0 ? {} : { usage } };
|
|
70
|
+
if (status === "revise") return { status, violations: readListField(args.violations), ...usage === void 0 ? {} : { usage } };
|
|
71
|
+
if (status === "escalate") return { status, ...Object.hasOwn(args, "conflicts") ? { conflicts: args.conflicts } : {}, ...Object.hasOwn(args, "decisionGate") ? { decisionGate: args.decisionGate } : {}, ...usage === void 0 ? {} : { usage } };
|
|
72
|
+
throw new ComplianceCandidateUnreadableError(
|
|
73
|
+
{ kind: "object-status-unreadable", status: status === void 0 ? "missing" : "unknown" },
|
|
74
|
+
arguments_,
|
|
75
|
+
usage
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
async function runComplianceAudit(options) {
|
|
79
|
+
const prompt = options.serializedInput ?? AUDITOR_DOSSIER_PROMPT;
|
|
80
|
+
const receipt = await executeAuditorChild({
|
|
81
|
+
tool: options.tool,
|
|
82
|
+
dossierTool: createAuditorDossierTool(options.runDirectory),
|
|
83
|
+
systemPrompt: options.systemPrompt,
|
|
84
|
+
prompt,
|
|
85
|
+
roleLabel: options.roleLabel,
|
|
86
|
+
context: options.context,
|
|
87
|
+
retainResponse: (response) => retainComplianceResponse(options.context, response),
|
|
88
|
+
...options.runDirectory === void 0 ? {} : { runDirectory: options.runDirectory },
|
|
89
|
+
...options.signal === void 0 ? {} : { signal: options.signal }
|
|
90
|
+
});
|
|
91
|
+
if (receipt.noReceiptLifecycle !== void 0) {
|
|
92
|
+
return {
|
|
93
|
+
status: "no-receipt",
|
|
94
|
+
...receipt.noReceiptLifecycle,
|
|
95
|
+
...receipt.response.usage === void 0 ? {} : { usage: receipt.response.usage }
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
return readComplianceCandidate(receipt.decision, receipt.response.usage);
|
|
98
99
|
}
|
|
100
|
+
export {
|
|
101
|
+
AUDITOR_COMPLIANCE_FAILURE_ENTRY_TYPE,
|
|
102
|
+
AUDITOR_DOSSIER_PROMPT,
|
|
103
|
+
AUDITOR_PARENT_ATTEMPT_BINDING_ENTRY_TYPE,
|
|
104
|
+
COMPLIANCE_RESPONSE_ENTRY_TYPE,
|
|
105
|
+
ComplianceCandidateUnreadableError,
|
|
106
|
+
ComplianceResponseRetentionError,
|
|
107
|
+
complianceDecisionSchema,
|
|
108
|
+
createComplianceDecisionTool,
|
|
109
|
+
readComplianceCandidate,
|
|
110
|
+
runComplianceAudit
|
|
111
|
+
};
|