@akagilnc/pi-workflow-roles 0.1.3565 → 0.1.3572

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/README.md +4 -1
  2. package/README.zh-CN.md +1 -1
  3. package/dist/acp-host/production-host.js +755 -60
  4. package/dist/diarist-contracts.js +72 -0
  5. package/dist/package-contracts/terminating-tools.js +20 -2
  6. package/dist/packaged-role-registry.js +20 -0
  7. package/dist/public-cli/main.js +533 -634
  8. package/dist/public-cli/registry.js +4 -1
  9. package/extensions/role-runtime.ts +1 -0
  10. package/package.json +1 -1
  11. package/resources/diarist-collect.md +6 -10
  12. package/souls/diarist.md +9 -0
  13. package/src/acp-host/production-host.ts +1 -0
  14. package/src/acp-host/role-envelope.ts +2 -1
  15. package/src/diarist-contracts.ts +88 -0
  16. package/src/diarist-role.ts +60 -0
  17. package/src/diarist.ts +253 -179
  18. package/src/host-contracts.ts +6 -1
  19. package/src/package-contracts/terminating-tools.ts +22 -2
  20. package/src/packaged-role-registry.ts +20 -0
  21. package/src/pi/role-turn-host.ts +8 -0
  22. package/src/public-cli/cli.ts +29 -0
  23. package/src/public-cli/countersign-run.ts +9 -129
  24. package/src/public-cli/diarist-run.ts +312 -0
  25. package/src/public-cli/invocation.ts +23 -2
  26. package/src/public-cli/option-definitions.ts +18 -0
  27. package/src/public-cli/post-admission.ts +2 -2
  28. package/src/public-cli/registry.ts +3 -0
  29. package/src/public-cli/run-lifecycle.ts +31 -3
  30. package/src/public-cli/settlement.ts +50 -2
  31. package/src/public-cli/terminal.ts +2 -1
  32. package/src/role-runtime.ts +117 -6
  33. package/src/ticket-provenance-contracts.ts +1 -0
  34. package/src/ticket-provenance.ts +0 -23
  35. package/src/diarist-llm-collector.ts +0 -324
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Public 起居郎 (diarist) terminating receipt contracts — ADR 0075 `diarist-is-role`.
3
+ * Lawful explicit release: completed, with empty or nonempty selections.
4
+ * Machine facts about the volume come from the mechanical sitian seam, never
5
+ * from model self-report (锚定宪法); this module owns the receipt shape only.
6
+ */
7
+ export const DIARIST_OUTPUT_TOOL_NAME = "ak_diarist_output";
8
+ export const DIARIST_ACCEPTED_TEXT = "起居郎回执已接受";
9
+ /** Internal transport: frozen candidate-catalog path for this turn's ticket. */
10
+ export const DIARIST_SOURCES_FLAG = {
11
+ name: "ak-diarist-sources",
12
+ definition: {
13
+ description: "Frozen per-ticket source catalog the diarist selects from",
14
+ type: "string",
15
+ },
16
+ };
17
+ export function validateRecordedDiaristOutput(value) {
18
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
19
+ throw new Error("Diarist output has no execution discriminator");
20
+ }
21
+ let status;
22
+ try {
23
+ status = value.status;
24
+ }
25
+ catch {
26
+ throw new Error("Diarist output has no execution discriminator");
27
+ }
28
+ if (status === "completed") {
29
+ return value;
30
+ }
31
+ throw new Error("Diarist output has no execution discriminator");
32
+ }
33
+ /**
34
+ * Lenient projection of submitted selections (第 0 条: shape is not an admission
35
+ * gate). Rows that carry no usable candidateIndex are dropped from the commit,
36
+ * never bounced back at the role.
37
+ */
38
+ export function projectDiaristSelections(value) {
39
+ const rows = value?.selections;
40
+ if (!Array.isArray(rows))
41
+ return [];
42
+ const out = [];
43
+ for (const row of rows) {
44
+ if (row === null || typeof row !== "object" || Array.isArray(row))
45
+ continue;
46
+ const record = row;
47
+ const index = record.candidateIndex;
48
+ if (typeof index !== "number" || !Number.isInteger(index) || index < 0)
49
+ continue;
50
+ const quotes = Array.isArray(record.quotes)
51
+ ? record.quotes.filter((q) => typeof q === "string" && q.length > 0)
52
+ : [];
53
+ out.push({
54
+ candidateIndex: index,
55
+ quotes,
56
+ ...(typeof record.note === "string" ? { note: record.note } : {}),
57
+ });
58
+ }
59
+ return out;
60
+ }
61
+ /** Machine-facing facts from an accepted receipt. Submitted rows retained as-is. */
62
+ export function diaristDecisiveFacts(output) {
63
+ const facts = { status: output.status };
64
+ const selections = output.selections;
65
+ if (Array.isArray(selections))
66
+ facts.selections = selections;
67
+ // Mechanical sitian facts recorded by the envelope at accept time.
68
+ const sitian = output.sitian;
69
+ if (sitian !== undefined)
70
+ facts.sitian = sitian;
71
+ return facts;
72
+ }
@@ -15,8 +15,9 @@ import { NOTARY_ACCEPTED_TEXT, NOTARY_OUTPUT_TOOL_NAME, validateRecordedNotaryOu
15
15
  import { COUNTERSIGN_ACCEPTED_TEXT, COUNTERSIGN_OUTPUT_TOOL_NAME, validateRecordedCountersignOutput } from "../countersign-contracts.js";
16
16
  import { GLEANER_LEFT_ACCEPTED_TEXT, GLEANER_LEFT_OUTPUT_TOOL_NAME, validateRecordedGleanerLeftOutput } from "../gleaner-left-contracts.js";
17
17
  import { INSPECTOR_ACCEPTED_TEXT, INSPECTOR_OUTPUT_TOOL_NAME, validateRecordedInspectorOutput } from "../inspector-contracts.js";
18
+ import { DIARIST_ACCEPTED_TEXT, DIARIST_OUTPUT_TOOL_NAME, validateRecordedDiaristOutput } from "../diarist-contracts.js";
18
19
  import { CODER_ACCEPTED_TEXT, CODER_OUTPUT_TOOL_NAME, FIXER_ACCEPTED_TEXT, FIXER_OUTPUT_TOOL_NAME, validateAcceptedWorkerDetails, } from "./worker-output.js";
19
- 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, };
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, };
20
21
  export const TERMINATING_TOOL_NAMES = [
21
22
  CODER_OUTPUT_TOOL_NAME,
22
23
  FIXER_OUTPUT_TOOL_NAME,
@@ -31,6 +32,7 @@ export const TERMINATING_TOOL_NAMES = [
31
32
  INSPECTOR_OUTPUT_TOOL_NAME,
32
33
  GATEKEEPER_OUTPUT_TOOL_NAME,
33
34
  NAVIGATOR_OUTPUT_TOOL_NAME,
35
+ DIARIST_OUTPUT_TOOL_NAME,
34
36
  ];
35
37
  export function isTerminatingToolName(name) {
36
38
  return TERMINATING_TOOL_NAMES.includes(name);
@@ -63,6 +65,8 @@ export function acceptedTextFor(toolName) {
63
65
  return GATEKEEPER_ACCEPTED_TEXT;
64
66
  case NAVIGATOR_OUTPUT_TOOL_NAME:
65
67
  return NAVIGATOR_ACCEPTED_TEXT;
68
+ case DIARIST_OUTPUT_TOOL_NAME:
69
+ return DIARIST_ACCEPTED_TEXT;
66
70
  }
67
71
  }
68
72
  export class AcceptedDetailsContractError extends CorrectableSubmissionError {
@@ -114,6 +118,7 @@ export function validateAcceptedDetails(toolName, details) {
114
118
  [INSPECTOR_OUTPUT_TOOL_NAME]: ["pass", "bounce"],
115
119
  [GATEKEEPER_OUTPUT_TOOL_NAME]: ["dispatch", "pass"],
116
120
  [NAVIGATOR_OUTPUT_TOOL_NAME]: ["advice"],
121
+ [DIARIST_OUTPUT_TOOL_NAME]: ["completed"],
117
122
  };
118
123
  const collectorDiscriminator = toolName === COLLECTOR_OUTPUT_TOOL && Array.isArray(candidate?.groups);
119
124
  const baseDiscriminator = discriminator;
@@ -151,6 +156,8 @@ export function validateAcceptedDetails(toolName, details) {
151
156
  return validateRecordedGatekeeperOutput(details);
152
157
  case NAVIGATOR_OUTPUT_TOOL_NAME:
153
158
  return validateRecordedNavigatorOutput(details);
159
+ case DIARIST_OUTPUT_TOOL_NAME:
160
+ return validateRecordedDiaristOutput(details);
154
161
  }
155
162
  }
156
163
  catch (error) {
@@ -177,6 +184,16 @@ export function validateAcceptedLifecycle(toolName, argumentsValue, detailsValue
177
184
  throw new Error("accepted tool lifecycle details mismatch");
178
185
  return details;
179
186
  }
187
+ if (toolName === DIARIST_OUTPUT_TOOL_NAME) {
188
+ // Envelope-owned mechanical sitian facts are runtime-bound on details only
189
+ // (same shape as the Doctor runtime cost); the submitted arguments carry the
190
+ // role's own selections. Machine facts never come from model self-report.
191
+ const { sitian: _mechanical, ...submitted } = details;
192
+ const testimony = validateAcceptedDetails(toolName, argumentsValue);
193
+ if (!deepEqual(testimony, submitted))
194
+ throw new Error("accepted tool lifecycle details mismatch");
195
+ return details;
196
+ }
180
197
  const argumentsDetails = validateAcceptedDetails(toolName, argumentsValue);
181
198
  if (!deepEqual(argumentsDetails, details))
182
199
  throw new Error("accepted tool lifecycle details mismatch");
@@ -192,7 +209,8 @@ export function acceptedFacts(toolName, details) {
192
209
  case GLEANER_LEFT_OUTPUT_TOOL_NAME:
193
210
  case INSPECTOR_OUTPUT_TOOL_NAME:
194
211
  case GATEKEEPER_OUTPUT_TOOL_NAME:
195
- case NAVIGATOR_OUTPUT_TOOL_NAME: return { status: details.status };
212
+ case NAVIGATOR_OUTPUT_TOOL_NAME:
213
+ case DIARIST_OUTPUT_TOOL_NAME: return { status: details.status };
196
214
  case JUDGE_OUTPUT_TOOL_NAME: return { status: details.judgeStatus };
197
215
  case COUNTERSIGN_OUTPUT_TOOL_NAME: return { status: details.countersignStatus };
198
216
  case MERGER_OUTPUT_TOOL_NAME: {
@@ -10,6 +10,10 @@ 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 {
14
+ DIARIST_OUTPUT_TOOL_NAME,
15
+ DIARIST_SOURCES_FLAG
16
+ } from "./diarist-contracts.js";
13
17
  const NOTARY_SESSION_MATERIALS = [
14
18
  "CLAUDE.md",
15
19
  "souls/notary.md",
@@ -175,6 +179,22 @@ const PUBLIC_ROLE_RECORDS = [
175
179
  phaseFlag: void 0,
176
180
  activationStage: "load-and-install",
177
181
  sessionMaterials: ["CLAUDE.md", "souls/navigator.md"]
182
+ },
183
+ // #708 / ADR 0075 `diarist-is-role`: 起居郎 is a seat like any other. The
184
+ // frozen source catalog rides the shared input-flag seam; it is absent for a
185
+ // true-unbound summons (no ticket → no diary).
186
+ {
187
+ role: "diarist",
188
+ phases: [null],
189
+ outputTool: DIARIST_OUTPUT_TOOL_NAME,
190
+ inputFlag: DIARIST_SOURCES_FLAG.name,
191
+ phaseFlag: void 0,
192
+ activationStage: "load-and-install",
193
+ sessionMaterials: [
194
+ "CLAUDE.md",
195
+ "souls/diarist.md",
196
+ "resources/diarist-collect.md"
197
+ ]
178
198
  }
179
199
  ];
180
200
  const PACKAGED_ROLE_REGISTRY = PUBLIC_ROLE_RECORDS.map(({ sessionMaterials: _omit, ...metadata }) => metadata);