@akagilnc/pi-workflow-roles 0.1.2296 → 0.1.2310

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/README.md CHANGED
@@ -161,6 +161,13 @@ Generated from `src/public-cli/option-definitions.ts`. Prefer `ak-role help <com
161
161
  | `--project` | — | `path` | no | no | option | — | Project root with one ordinary in-progress merge (defaults to cwd). |
162
162
  | `--attach` | — | `path` | no | yes | option | — | Attach a regular file; frozen at admission (repeatable). |
163
163
 
164
+ ### `notary`
165
+
166
+ | Spelling | Aliases | Value | Required | Repeatable | Form | Modes/Phases | Description |
167
+ | --- | --- | --- | --- | --- | --- | --- | --- |
168
+ | `--project` | — | `path` | no | no | option | — | Project root for ledger identity (defaults to process cwd). |
169
+ | `--source-run` | — | `runId@role\|path` | yes | no | option | — | Required source run locator (runId@role under the book home, or path to that run directory). Zero prompt/attachment projection. |
170
+
164
171
  ### `analyst`
165
172
 
166
173
  | Spelling | Aliases | Value | Required | Repeatable | Form | Modes/Phases | Description |
package/README.zh-CN.md CHANGED
@@ -190,6 +190,13 @@ ak-role merger --project /path/to/worktree "Reconcile the active merge."
190
190
  | `--project` | — | `path` | 否 | 否 | option | — | 已有进行中 ordinary merge 的项目根(默认 cwd)。 |
191
191
  | `--attach` | — | `path` | 否 | 是 | option | — | 附加普通文件;受理即冻结(可重复)。 |
192
192
 
193
+ ### `notary`
194
+
195
+ | 拼写 | 别名 | 值 | 必填 | 可重复 | 形式 | 模式/阶段 | 说明 |
196
+ | --- | --- | --- | --- | --- | --- | --- | --- |
197
+ | `--project` | — | `path` | 否 | 否 | option | — | 卷宗身份用的项目根(默认进程 cwd)。 |
198
+ | `--source-run` | — | `runId@role\|path` | 是 | 否 | option | — | 必填源 run 定位符(簿内 runId@role,或该 run 目录路径)。零 prompt/附件投影。 |
199
+
193
200
  ### `analyst`
194
201
 
195
202
  | 拼写 | 别名 | 值 | 必填 | 可重复 | 形式 | 模式/阶段 | 说明 |
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Public Notary (符宝郎) terminating receipt contracts.
3
+ * Lawful explicit releases: pass | bounce | incomplete(with non-empty reason).
4
+ * Residual incomplete (no explicit release) is projected by public settlement, not here.
5
+ */
6
+ import { Type } from "typebox";
7
+ import { readActivationEngineLaborFallbackField, seatFallbackBaseStatus, seatFallbackStatusHasLawfulEvidence, withEngineLaborFallbackField, } from "./engine-labor-fallback.js";
8
+ import { openToolObject } from "./open-tool-schema.js";
9
+ export const NOTARY_OUTPUT_TOOL_NAME = "ak_notary_output";
10
+ export const NOTARY_ACCEPTED_TEXT = "Notary output accepted";
11
+ export const NOTARY_SOURCE_RUN_FLAG = {
12
+ name: "ak-notary-source-run",
13
+ definition: {
14
+ description: "Absolute source run directory bound for Notary self-fetch",
15
+ type: "string",
16
+ },
17
+ };
18
+ /** Package-owned kickoff only — callers supply zero prompt bytes (ADR 0067 / #448). */
19
+ export const NOTARY_FIXED_KICKOFF = "Notary review. Bound source-run locator is on the session materials; fetch authoritative ticket, git, and dossier evidence yourself; submit one typed decision.";
20
+ export const notaryOutputSchema = openToolObject(Type.Object({
21
+ status: Type.Unknown({
22
+ description: "pass | bounce | incomplete — guidance, not a schema gate.",
23
+ }),
24
+ findings: Type.Unknown({
25
+ description: "string[] findings retained with pass or bounce.",
26
+ }),
27
+ reason: Type.Unknown({
28
+ description: "Why the notary decision is incomplete.",
29
+ }),
30
+ }));
31
+ function isRecord(value) {
32
+ return typeof value === "object" && value !== null && !Array.isArray(value);
33
+ }
34
+ function asStringArray(value) {
35
+ if (!Array.isArray(value))
36
+ return [];
37
+ return value.filter((item) => typeof item === "string");
38
+ }
39
+ /**
40
+ * Project one explicit Notary release. Throws when there is no lawful explicit
41
+ * pass / bounce / incomplete(reason) — callers map that to residual incomplete.
42
+ */
43
+ export function validateNotaryOutput(value) {
44
+ if (!isRecord(value)) {
45
+ throw new Error("Notary output has no recognized execution discriminator");
46
+ }
47
+ const statusRaw = typeof value.status === "string" ? value.status : undefined;
48
+ if (statusRaw === undefined || !seatFallbackStatusHasLawfulEvidence(statusRaw, value)) {
49
+ throw new Error("Notary output has no recognized execution discriminator");
50
+ }
51
+ const status = seatFallbackBaseStatus(statusRaw);
52
+ if (status === "incomplete") {
53
+ const reason = value.reason;
54
+ if (typeof reason !== "string" || reason.trim() === "") {
55
+ throw new Error("Notary incomplete requires a non-empty reason");
56
+ }
57
+ return structuredClone(value);
58
+ }
59
+ if (status === "bounce") {
60
+ const clone = structuredClone(value);
61
+ if (clone.disposition === undefined)
62
+ clone.disposition = "rewrite";
63
+ if (!Array.isArray(clone.findings))
64
+ clone.findings = asStringArray(clone.findings);
65
+ return clone;
66
+ }
67
+ if (status === "pass") {
68
+ const clone = structuredClone(value);
69
+ if (!Array.isArray(clone.findings))
70
+ clone.findings = asStringArray(clone.findings);
71
+ return clone;
72
+ }
73
+ throw new Error("Notary output has no recognized execution discriminator");
74
+ }
75
+ /** Shape check for recorded accepted details (may include engineLaborFallback). */
76
+ export function validateRecordedNotaryOutput(value) {
77
+ return validateNotaryOutput(value);
78
+ }
79
+ export function withNotaryAcceptedDetails(output) {
80
+ return withEngineLaborFallbackField(output, readActivationEngineLaborFallbackField());
81
+ }
82
+ export function notaryDecisiveFacts(output) {
83
+ const status = seatFallbackBaseStatus(String(output.status));
84
+ const facts = { status, officer: "notary" };
85
+ if (status === "pass" || status === "bounce") {
86
+ const findings = output.findings;
87
+ facts.findingsCount = Array.isArray(findings) ? findings.length : 0;
88
+ }
89
+ if (status === "bounce") {
90
+ facts.disposition = "rewrite";
91
+ }
92
+ if (status === "incomplete") {
93
+ facts.reason = output.reason;
94
+ }
95
+ return facts;
96
+ }
@@ -9,8 +9,9 @@ import { isAuditEscalationResult } from "../audit-escalation.js";
9
9
  import { seatFallbackBaseStatus, seatFallbackStatusHasLawfulEvidence, } from "../engine-labor-fallback.js";
10
10
  import { DOCTOR_OUTPUT_TOOL_NAME, validateDoctorSubmissionShape, validateRecordedDoctorOutput } from "../doctor-contracts.js";
11
11
  import { MERGER_ACCEPTED_TEXT, MERGER_OUTPUT_TOOL_NAME, validateMergerOutput } from "../merger-contracts.js";
12
+ import { NOTARY_ACCEPTED_TEXT, NOTARY_OUTPUT_TOOL_NAME, validateRecordedNotaryOutput } from "../notary-contracts.js";
12
13
  import { CODER_ACCEPTED_TEXT, CODER_OUTPUT_TOOL_NAME, FIXER_ACCEPTED_TEXT, FIXER_OUTPUT_TOOL_NAME, validateAcceptedWorkerDetails, } from "./worker-output.js";
13
- 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, };
14
+ 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, };
14
15
  export const TERMINATING_TOOL_NAMES = [
15
16
  CODER_OUTPUT_TOOL_NAME,
16
17
  FIXER_OUTPUT_TOOL_NAME,
@@ -19,6 +20,7 @@ export const TERMINATING_TOOL_NAMES = [
19
20
  COLLECTOR_OUTPUT_TOOL,
20
21
  DOCTOR_OUTPUT_TOOL_NAME,
21
22
  MERGER_OUTPUT_TOOL_NAME,
23
+ NOTARY_OUTPUT_TOOL_NAME,
22
24
  ];
23
25
  export function isTerminatingToolName(name) {
24
26
  return TERMINATING_TOOL_NAMES.includes(name);
@@ -39,6 +41,8 @@ export function acceptedTextFor(toolName) {
39
41
  return "Doctor output accepted";
40
42
  case MERGER_OUTPUT_TOOL_NAME:
41
43
  return MERGER_ACCEPTED_TEXT;
44
+ case NOTARY_OUTPUT_TOOL_NAME:
45
+ return NOTARY_ACCEPTED_TEXT;
42
46
  }
43
47
  }
44
48
  export class AcceptedDetailsContractError extends Error {
@@ -78,6 +82,7 @@ export function validateAcceptedDetails(toolName, details) {
78
82
  [COLLECTOR_OUTPUT_TOOL]: [],
79
83
  [DOCTOR_OUTPUT_TOOL_NAME]: ["completed", "refused"],
80
84
  [MERGER_OUTPUT_TOOL_NAME]: ["completed", "escalate"],
85
+ [NOTARY_OUTPUT_TOOL_NAME]: ["pass", "bounce", "incomplete"],
81
86
  };
82
87
  const collectorDiscriminator = toolName === COLLECTOR_OUTPUT_TOOL && Array.isArray(candidate?.groups);
83
88
  const baseDiscriminator = typeof discriminator === "string" ? seatFallbackBaseStatus(discriminator) : discriminator;
@@ -107,6 +112,8 @@ export function validateAcceptedDetails(toolName, details) {
107
112
  return validateRecordedDoctorOutput(details);
108
113
  case MERGER_OUTPUT_TOOL_NAME:
109
114
  return validateMergerOutput(details);
115
+ case NOTARY_OUTPUT_TOOL_NAME:
116
+ return validateRecordedNotaryOutput(details);
110
117
  }
111
118
  }
112
119
  catch (error) {
@@ -143,7 +150,8 @@ export function acceptedFacts(toolName, details) {
143
150
  case CODER_OUTPUT_TOOL_NAME:
144
151
  case FIXER_OUTPUT_TOOL_NAME:
145
152
  case REVIEWER_OUTPUT_TOOL_NAME:
146
- case DOCTOR_OUTPUT_TOOL_NAME: return { status: details.status };
153
+ case DOCTOR_OUTPUT_TOOL_NAME:
154
+ case NOTARY_OUTPUT_TOOL_NAME: return { status: details.status };
147
155
  case JUDGE_OUTPUT_TOOL_NAME: return { status: details.judgeStatus };
148
156
  case MERGER_OUTPUT_TOOL_NAME: {
149
157
  const output = details;
@@ -4,6 +4,7 @@ import { REVIEWER_OUTPUT_TOOL_NAME } from "./package-contracts/reviewer-output.j
4
4
  import { CODER_OUTPUT_TOOL_NAME, FIXER_OUTPUT_TOOL_NAME } from "./package-contracts/worker-output.js";
5
5
  import { DOCTOR_OUTPUT_TOOL_NAME } from "./doctor-contracts.js";
6
6
  import { MERGER_OUTPUT_TOOL_NAME } from "./merger-contracts.js";
7
+ import { NOTARY_OUTPUT_TOOL_NAME } from "./notary-contracts.js";
7
8
  const PACKAGED_ROLE_REGISTRY = [
8
9
  { role: "judge", phases: [null], outputTool: JUDGE_OUTPUT_TOOL_NAME, inputFlag: void 0, phaseFlag: void 0, activationStage: "load-and-install" },
9
10
  { role: "fixer", phases: ["plan", "apply"], outputTool: FIXER_OUTPUT_TOOL_NAME, inputFlag: "ak-fix-packet", phaseFlag: "ak-fixer-phase", activationStage: "load-and-install" },
@@ -11,7 +12,8 @@ const PACKAGED_ROLE_REGISTRY = [
11
12
  { role: "reviewer", phases: [null], outputTool: REVIEWER_OUTPUT_TOOL_NAME, inputFlag: void 0, phaseFlag: void 0, activationStage: "load-and-install" },
12
13
  { role: "collector", phases: [null], outputTool: COLLECTOR_OUTPUT_TOOL, inputFlag: "ak-collector-repo", phaseFlag: void 0, activationStage: "load-and-install" },
13
14
  { role: "doctor", phases: [null], outputTool: DOCTOR_OUTPUT_TOOL_NAME, inputFlag: "ak-doctor-case", phaseFlag: void 0, activationStage: "load-and-install" },
14
- { role: "merger", phases: [null], outputTool: MERGER_OUTPUT_TOOL_NAME, inputFlag: "ak-merger-input", phaseFlag: void 0, activationStage: "prepare-git-and-install" }
15
+ { role: "merger", phases: [null], outputTool: MERGER_OUTPUT_TOOL_NAME, inputFlag: "ak-merger-input", phaseFlag: void 0, activationStage: "prepare-git-and-install" },
16
+ { role: "notary", phases: [null], outputTool: NOTARY_OUTPUT_TOOL_NAME, inputFlag: "ak-notary-source-run", phaseFlag: void 0, activationStage: "load-and-install" }
15
17
  ];
16
18
  function packagedRoleMetadata(role) {
17
19
  return PACKAGED_ROLE_REGISTRY.find((entry) => entry.role === role);