@akagilnc/pi-workflow-roles 0.1.2521 → 0.1.2653-next.71811ca

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 (109) hide show
  1. package/README.md +129 -39
  2. package/README.zh-CN.md +128 -39
  3. package/dist/activation-ledger-topology.js +1 -1
  4. package/dist/archivist-record-entry.js +47 -26
  5. package/dist/auditor-dossier-tool.js +3 -1
  6. package/dist/compliance-transport.js +17 -26
  7. package/dist/doctor-contracts.js +1 -2
  8. package/dist/dossier-resolution.js +4 -8
  9. package/dist/engine-detour-tool.js +33 -8
  10. package/dist/engine-detour.js +1 -0
  11. package/dist/evidence-child-executor.js +277 -424
  12. package/dist/host-contracts.js +22 -0
  13. package/dist/institutional-resolution.js +88 -0
  14. package/dist/merger-contracts.js +1 -2
  15. package/dist/navigator-attendance.js +16 -0
  16. package/dist/notary-contracts.js +2 -3
  17. package/dist/package-contracts/fixer-output.js +1 -2
  18. package/dist/packaged-role-registry.js +102 -9
  19. package/dist/pi/in-process-session.js +671 -0
  20. package/dist/public-cli/config.js +7 -5
  21. package/dist/public-cli/main.js +3767 -4113
  22. package/dist/reviewer-child-executor.js +6 -1
  23. package/dist/session-opening-materials.js +10 -38
  24. package/dist/sitian-appender.js +146 -0
  25. package/dist/sitian-contracts.js +21 -0
  26. package/dist/sitian-facade.js +15 -0
  27. package/dist/sitian-reader.js +52 -0
  28. package/extensions/role-runtime.ts +9 -7
  29. package/package.json +5 -5
  30. package/resources/engines/cursor.md +12 -26
  31. package/resources/engines/hermes.md +2 -23
  32. package/resources/engines/opus.md +1 -16
  33. package/resources/navigator-route-playbook.md +2 -2
  34. package/scripts/build-package.mjs +0 -1
  35. package/souls/quality-law.md +1 -1
  36. package/src/activation-ledger-topology.ts +1 -1
  37. package/src/archivist-record-entry.ts +57 -45
  38. package/src/auditor-dossier-tool.ts +4 -2
  39. package/src/canonical-skill-binding.ts +37 -27
  40. package/src/collector-role.ts +11 -20
  41. package/src/collector-tool-schemas.ts +1 -4
  42. package/src/compliance-transport.ts +19 -44
  43. package/src/doctor-auditor.ts +1 -5
  44. package/src/doctor-contracts.ts +1 -4
  45. package/src/doctor-role.ts +31 -8
  46. package/src/dossier-resolution.ts +8 -8
  47. package/src/engine-detour-tool.ts +48 -19
  48. package/src/engine-detour.ts +3 -0
  49. package/src/evidence-child-executor.ts +277 -485
  50. package/src/factory-board.ts +3 -3
  51. package/src/gatekeeper-role.ts +21 -10
  52. package/src/host-contracts.ts +386 -0
  53. package/src/in-process-session.ts +1 -115
  54. package/src/institutional-resolution.ts +135 -0
  55. package/src/judge-auditor.ts +1 -5
  56. package/src/judge-role.ts +37 -51
  57. package/src/merger-contracts.ts +1 -4
  58. package/src/merger-role.ts +7 -11
  59. package/src/navigator-attendance.ts +20 -1
  60. package/src/notary-contracts.ts +8 -11
  61. package/src/notary-role.ts +7 -23
  62. package/src/notary-source-run.ts +4 -3
  63. package/src/package-contracts/fixer-output.ts +1 -4
  64. package/src/package-resources/method-skill-binding.ts +10 -34
  65. package/src/packaged-role-registry.ts +122 -12
  66. package/src/pi/adapter.ts +192 -0
  67. package/src/pi/durable-principal.ts +98 -0
  68. package/src/pi/in-process-session.ts +819 -0
  69. package/src/pi/known-failure.ts +77 -0
  70. package/src/pi/pi-normalization.ts +284 -0
  71. package/src/pi/role-turn-host.ts +459 -0
  72. package/src/public-cli/auto-resume.ts +42 -44
  73. package/src/public-cli/cli.ts +171 -257
  74. package/src/public-cli/coder-run.ts +115 -433
  75. package/src/public-cli/collector-run.ts +62 -314
  76. package/src/public-cli/config.ts +7 -5
  77. package/src/public-cli/doctor-run.ts +41 -52
  78. package/src/public-cli/fixer-run.ts +122 -427
  79. package/src/public-cli/invocation.ts +287 -96
  80. package/src/public-cli/judge-run.ts +92 -422
  81. package/src/public-cli/merger-run.ts +167 -429
  82. package/src/public-cli/notary-run.ts +41 -47
  83. package/src/public-cli/option-definitions.ts +136 -3
  84. package/src/public-cli/post-admission.ts +497 -0
  85. package/src/public-cli/public-run-credentials.ts +4 -4
  86. package/src/public-cli/reviewer-dispatch-rejection.ts +106 -0
  87. package/src/public-cli/reviewer-run.ts +132 -449
  88. package/src/public-cli/run-lifecycle.ts +339 -327
  89. package/src/public-cli/settlement.ts +251 -134
  90. package/src/public-cli/terminal.ts +3 -9
  91. package/src/public-cli/turn-request.ts +87 -0
  92. package/src/reviewer-child-executor.ts +9 -1
  93. package/src/reviewer-role.ts +11 -20
  94. package/src/role-runtime.ts +129 -78
  95. package/src/session-opening-materials.ts +25 -39
  96. package/src/sitian-appender.ts +171 -0
  97. package/src/sitian-contracts.ts +106 -0
  98. package/src/sitian-facade.ts +18 -0
  99. package/src/sitian-reader.ts +62 -0
  100. package/src/worker-role.ts +42 -40
  101. package/src/worker-submission-gates.ts +33 -0
  102. package/dist/archivist-role-run-coordinates.js +0 -28
  103. package/dist/package-contracts/terminating-infrastructure.js +0 -90
  104. package/resources/engines/sonnet.md +0 -27
  105. package/resources/engines/zcode.md +0 -63
  106. package/src/archivist-role-run-coordinates.ts +0 -45
  107. package/src/package-contracts/terminating-infrastructure.ts +0 -132
  108. package/src/public-cli/explicit-internal.ts +0 -427
  109. package/src/public-cli/one-shot-dispatch.ts +0 -300
@@ -15,7 +15,12 @@ export function projectSharedChildFailure(error) {
15
15
  /** Reviewer policy adapter over the shared evidence-child lifecycle seam. */
16
16
  export async function executeReviewerChild(workspace, leg, context, options = {}) {
17
17
  try {
18
- return await executeEvidenceChild(workspace, leg.prompt, context, options);
18
+ return await executeEvidenceChild(workspace, leg.prompt, context, {
19
+ ...(options.signal === undefined ? {} : { signal: options.signal }),
20
+ ...(options.credentialScratchParent === undefined ? {} : { credentialScratchParent: options.credentialScratchParent }),
21
+ ...(options.runDirectory === undefined ? {} : { runDirectory: options.runDirectory }),
22
+ ...(options.packageRoot === undefined ? {} : { packageRoot: options.packageRoot }),
23
+ });
19
24
  }
20
25
  catch (error) {
21
26
  throw projectSharedChildFailure(error);
@@ -1,13 +1,13 @@
1
1
  /**
2
- * Session opening materials (#443): factory constitution + role soul + role-owned
3
- * extras, composed at the three existing loader seams. Missing files fail as
4
- * native readFile errors — no exists/hash/empty guards, no second loader.
5
- *
6
- * Auditor composition stays owned by loadAuditorSoul (blank-soul identity);
7
- * main roles and gatekeeper family share joinPackageMaterials here.
2
+ * Session opening materials (#443 / #524). Missing files fail as native readFile
3
+ * errors. Main-role materials derive from PUBLIC_ROLE_RECORDS; gatekeeper seats
4
+ * stay independent except notary (shared NOTARY_SESSION_MATERIALS). Navigator is
5
+ * name-only here, not a public role record. Auditor composition stays in
6
+ * loadAuditorSoul; loaders share joinPackageMaterials.
8
7
  */
9
8
  import { readFile } from "node:fs/promises";
10
9
  import { fileURLToPath } from "node:url";
10
+ import { NOTARY_SESSION_MATERIALS, PUBLIC_ROLE_RECORDS, } from "./packaged-role-registry.js";
11
11
  const packageRootUrl = new URL("..", import.meta.url);
12
12
  /** Self-locate one package-relative material. Native I/O errors propagate. */
13
13
  export async function readPackageMaterial(relativePath) {
@@ -21,43 +21,15 @@ export async function joinPackageMaterials(relativePaths) {
21
21
  }
22
22
  return chunks.join("\n\n");
23
23
  }
24
- /** Seven public main roles + Navigator. Ticket #443 injection roster. */
24
+ /** Derived projection: public records + navigator name-only materials. */
25
25
  export const MAIN_ROLE_SESSION_MATERIALS = {
26
- judge: [
27
- "CLAUDE.md",
28
- "souls/judge.md",
29
- "souls/audit-law.md",
30
- "souls/quality-law.md",
31
- "souls/judge-output-guide.md",
32
- ],
33
- fixer: [
34
- "CLAUDE.md",
35
- "souls/fixer.md",
36
- "souls/quality-law.md",
37
- "souls/fixer-output-guide.md",
38
- ],
39
- coder: [
40
- "CLAUDE.md",
41
- "souls/coder.md",
42
- "souls/quality-law.md",
43
- "souls/coder-output-guide.md",
44
- ],
45
- reviewer: [
46
- "CLAUDE.md",
47
- "souls/reviewer.md",
48
- "souls/audit-law.md",
49
- "souls/quality-law.md",
50
- ],
51
- collector: ["CLAUDE.md", "souls/collector.md"],
52
- doctor: ["CLAUDE.md", "souls/doctor.md"],
53
- merger: ["CLAUDE.md", "souls/merger.md"],
54
- notary: ["CLAUDE.md", "souls/notary.md", "souls/gate-output-guide.md"],
26
+ ...Object.fromEntries(PUBLIC_ROLE_RECORDS.map((record) => [record.role, record.sessionMaterials])),
55
27
  navigator: ["CLAUDE.md", "souls/navigator.md"],
56
28
  };
57
29
  export function loadMainRoleSessionMaterials(role) {
58
30
  return joinPackageMaterials(MAIN_ROLE_SESSION_MATERIALS[role]);
59
31
  }
60
- /** Gatekeeper province + Inspector/Notary officer sessions. */
32
+ /** Gatekeeper province; notary reuses the public notary materials definition. */
61
33
  export const GATEKEEPER_SESSION_MATERIALS = {
62
34
  gatekeeper: [
63
35
  "CLAUDE.md",
@@ -71,7 +43,7 @@ export const GATEKEEPER_SESSION_MATERIALS = {
71
43
  "souls/quality-law.md",
72
44
  "souls/gate-output-guide.md",
73
45
  ],
74
- notary: ["CLAUDE.md", "souls/notary.md", "souls/gate-output-guide.md"],
46
+ notary: NOTARY_SESSION_MATERIALS,
75
47
  };
76
48
  export function loadGatekeeperSessionMaterials(role) {
77
49
  return joinPackageMaterials(GATEKEEPER_SESSION_MATERIALS[role]);
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Sitian Appender kernel (ADR 0065).
3
+ * Computes destination automatically from ledger topology without destination parameters.
4
+ * Owns volume open, torn-tail recovery, entry-level idempotency, and commit boundary.
5
+ */
6
+ import { createHash, randomUUID } from "node:crypto";
7
+ import { appendFileSync, existsSync, readFileSync } from "node:fs";
8
+ import { basename, dirname, join, resolve } from "node:path";
9
+ import { resolveBookKeyFromGit } from "./activation-ledger-git.js";
10
+ import { activationBookDirectory, ensureRealDirectoryTree, errorText, physicallyContainedIn, resolveActivationLedgerHome, } from "./activation-ledger-topology.js";
11
+ import { SitianInfrastructureError, } from "./sitian-contracts.js";
12
+ function isRecord(value) {
13
+ return typeof value === "object" && value !== null && !Array.isArray(value);
14
+ }
15
+ /** Authorized S4 submission ledger kinds that share a common run submission volume. */
16
+ export const S4_SUBMISSION_LEDGER_KINDS = new Set([
17
+ "candidate",
18
+ "batchContext",
19
+ "outcome",
20
+ "sealed",
21
+ "post-seal-anomaly",
22
+ ]);
23
+ /** Compute the volume partition key for directory placement. */
24
+ export function resolveSitianVolumeCategory(kind) {
25
+ if (S4_SUBMISSION_LEDGER_KINDS.has(kind)) {
26
+ return "submission-ledger";
27
+ }
28
+ return kind;
29
+ }
30
+ function safeBookKey(cwd) {
31
+ try {
32
+ return resolveBookKeyFromGit(cwd);
33
+ }
34
+ catch {
35
+ return basename(resolve(cwd)) || "default";
36
+ }
37
+ }
38
+ /** Compute the destination directory and record file from ledger topology (ADR 0065). */
39
+ export function resolveSitianRecordPath(input) {
40
+ const cwd = input.cwd ?? process.cwd();
41
+ const ledgerHome = resolveActivationLedgerHome();
42
+ const category = resolveSitianVolumeCategory(input.kind);
43
+ let sessionDir;
44
+ if (input.sessionParent !== undefined && input.sessionParent.length > 0 && physicallyContainedIn(ledgerHome, input.sessionParent)) {
45
+ sessionDir = join(dirname(input.sessionParent), category);
46
+ }
47
+ else {
48
+ const bookKey = safeBookKey(cwd);
49
+ const bookDir = activationBookDirectory(ledgerHome, bookKey);
50
+ if (input.subject !== undefined) {
51
+ let subjectStr;
52
+ if (typeof input.subject === "string") {
53
+ subjectStr = input.subject;
54
+ }
55
+ else if (typeof input.subject.runId === "string" && input.subject.runId.length > 0) {
56
+ subjectStr = input.subject.runId;
57
+ }
58
+ else {
59
+ subjectStr = JSON.stringify(input.subject);
60
+ }
61
+ const digest = createHash("sha256").update(subjectStr).digest("hex").slice(0, 32);
62
+ sessionDir = join(bookDir, category, digest);
63
+ }
64
+ else {
65
+ sessionDir = join(bookDir, category);
66
+ }
67
+ }
68
+ const recordFile = join(sessionDir, "records.jsonl");
69
+ return { sessionDir, recordFile, ledgerHome };
70
+ }
71
+ /**
72
+ * Appends a canonical record to its self-computed volume under the Sitian contract.
73
+ * - Idempotency: checks volume by deterministic canonical identity; returns existing pointer on hit.
74
+ * - Torn-tail recovery: checks file tail; un-terminated trailing bytes are sealed with a newline and re-parsed.
75
+ * Substate a (valid JSON): committed on recovery, returns existing pointer.
76
+ * Substate b (malformed): preserved as bad line, check misses, appends new row.
77
+ * - Commit point: full JSON string ending with newline.
78
+ */
79
+ export function appendSitianRecord(input) {
80
+ try {
81
+ const { sessionDir, recordFile, ledgerHome } = resolveSitianRecordPath(input);
82
+ ensureRealDirectoryTree(ledgerHome, sessionDir);
83
+ const identity = input.identity ?? randomUUID();
84
+ const timestamp = input.timestamp ?? new Date().toISOString();
85
+ const host = input.host ?? "pi";
86
+ const record = {
87
+ level: input.level,
88
+ kind: input.kind,
89
+ identity,
90
+ ...(input.subject === undefined ? {} : { subject: input.subject }),
91
+ ...(input.sessionParent === undefined ? {} : { sessionParent: input.sessionParent }),
92
+ ...(input.priorEventId === undefined ? {} : { priorEventId: input.priorEventId }),
93
+ timestamp,
94
+ host,
95
+ ...(input.source === undefined ? {} : { source: input.source }),
96
+ ...(input.payload === undefined ? {} : { payload: input.payload }),
97
+ ...(input.raw === undefined ? {} : { raw: input.raw }),
98
+ ...(input.usage === undefined ? {} : { usage: input.usage }),
99
+ };
100
+ if (existsSync(recordFile)) {
101
+ const buffer = readFileSync(recordFile);
102
+ if (buffer.length > 0) {
103
+ // Torn-tail check: if last byte is not newline, seal the fragment with \n
104
+ if (buffer[buffer.length - 1] !== 0x0a) {
105
+ appendFileSync(recordFile, "\n", "utf8");
106
+ }
107
+ // Self-check volume by canonical identity
108
+ const text = readFileSync(recordFile, "utf8");
109
+ for (const line of text.split("\n")) {
110
+ const trimmed = line.trim();
111
+ if (!trimmed)
112
+ continue;
113
+ try {
114
+ const parsed = JSON.parse(trimmed);
115
+ if (isRecord(parsed) && parsed.identity === identity) {
116
+ // Existing record found (or substate a recovered record) -> return existing pointer
117
+ return {
118
+ identity,
119
+ recordFile,
120
+ kind: record.kind,
121
+ level: record.level,
122
+ };
123
+ }
124
+ }
125
+ catch {
126
+ // Malformed lines (including substate b preserved bad lines) are ignored during self-check
127
+ }
128
+ }
129
+ }
130
+ }
131
+ // Not found -> append new canonical row terminating with newline
132
+ const row = `${JSON.stringify(record)}\n`;
133
+ appendFileSync(recordFile, row, "utf8");
134
+ return {
135
+ identity,
136
+ recordFile,
137
+ kind: record.kind,
138
+ level: record.level,
139
+ };
140
+ }
141
+ catch (error) {
142
+ if (error instanceof SitianInfrastructureError)
143
+ throw error;
144
+ throw new SitianInfrastructureError(`Sitian appender persistence failure: ${errorText(error)}`, { cause: error });
145
+ }
146
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Sitian (司天台) canonical contracts, Layout schema, and pointer definitions.
3
+ * ADR 0065 single record entry + ADR 0068 Taishi analysis.
4
+ */
5
+ /** Lift direct-cause fs errno onto a wrap error (no chain walk). */
6
+ export function attachDirectErrnoCode(error, cause) {
7
+ if (cause === null || typeof cause !== "object" || !("code" in cause))
8
+ return;
9
+ const code = cause.code;
10
+ if (typeof code === "string")
11
+ error.code = code;
12
+ }
13
+ /** Typed infrastructure error for real ledger persistence / IO failures. */
14
+ export class SitianInfrastructureError extends Error {
15
+ knownCause = "session";
16
+ constructor(message, options) {
17
+ super(message, options);
18
+ this.name = "SitianInfrastructureError";
19
+ attachDirectErrnoCode(this, options?.cause);
20
+ }
21
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Sitian Facade (司天门面) — Sole entrypoint for record reporting across all producers.
3
+ * ADR 0065 single record entry, #520 r8.
4
+ */
5
+ import { appendSitianRecord } from "./sitian-appender.js";
6
+ export * from "./sitian-contracts.js";
7
+ export * from "./sitian-appender.js";
8
+ export * from "./sitian-reader.js";
9
+ /**
10
+ * Sole write API for Sitian canonical records.
11
+ * Returns typed RecordPointer with durable record identity and readable file location.
12
+ */
13
+ export function sitianReport(input) {
14
+ return appendSitianRecord(input);
15
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Sitian Reader kernel (ADR 0068 / #520 r8).
3
+ * Sole authoritative read path for canonical Sitian records.
4
+ * Traversal contract:
5
+ * - Malformed lines are exposed as typed malformed diagnostics and traversal continues.
6
+ * - Zero whitewashing, zero deduplication.
7
+ * - Canonical rows after malformed lines are always reachable.
8
+ */
9
+ import { existsSync } from "node:fs";
10
+ import { readFile } from "node:fs/promises";
11
+ function isRecord(value) {
12
+ return typeof value === "object" && value !== null && !Array.isArray(value);
13
+ }
14
+ /** Read a Sitian record volume with full traversal and non-destructive diagnostics. */
15
+ export async function readSitianRecords(recordFile) {
16
+ if (!existsSync(recordFile)) {
17
+ return { records: [], diagnostics: [] };
18
+ }
19
+ const text = await readFile(recordFile, "utf8");
20
+ const lines = text.split("\n");
21
+ const records = [];
22
+ const diagnostics = [];
23
+ for (let index = 0; index < lines.length; index += 1) {
24
+ const line = lines[index];
25
+ if (!line.trim())
26
+ continue;
27
+ try {
28
+ const parsed = JSON.parse(line);
29
+ if (isRecord(parsed)) {
30
+ records.push(parsed);
31
+ }
32
+ else {
33
+ const typeDesc = parsed === null ? "null" : Array.isArray(parsed) ? "array" : typeof parsed;
34
+ diagnostics.push({
35
+ kind: "malformed",
36
+ line: index + 1,
37
+ raw: line,
38
+ error: `expected JSON object, got ${typeDesc}`,
39
+ });
40
+ }
41
+ }
42
+ catch (error) {
43
+ diagnostics.push({
44
+ kind: "malformed",
45
+ line: index + 1,
46
+ raw: line,
47
+ error: error instanceof Error ? error.message : String(error),
48
+ });
49
+ }
50
+ }
51
+ return { records, diagnostics };
52
+ }
@@ -4,6 +4,7 @@ import { resolve } from "node:path";
4
4
 
5
5
  import { loadDoctorCase } from "../src/doctor-evidence.ts";
6
6
  import { loadNotarySourceRunLocator } from "../src/notary-source-run.ts";
7
+ import { createPiRoleHostAdapter, toPiContext } from "../src/pi/adapter.ts";
7
8
  import { loadAdmittedJudgeRequest } from "../src/public-cli/invocation.ts";
8
9
 
9
10
  import {
@@ -243,6 +244,7 @@ export async function loadNavigatorWorkContext(
243
244
 
244
245
  export default function roleRuntime(pi: ExtensionAPI): void {
245
246
  const reviewerAgent = createReviewerAgentRunner({ packageRoot });
247
+ const piHostAdapter = createPiRoleHostAdapter(pi, { transcriptFromContext });
246
248
  registerNavigatorModelCommand(pi);
247
249
  const navigatorSessionFactory = createNativeNavigatorSessionFactory();
248
250
  // #351: static provider list from extension setting (default ["kimi-coding"]).
@@ -263,13 +265,13 @@ export default function roleRuntime(pi: ExtensionAPI): void {
263
265
  collectorPackageExtensionPath: extensionPath,
264
266
  loadDoctorSoul: () => loadMainRoleSessionMaterials("doctor"),
265
267
  loadDoctorCase,
266
- auditDoctorCompliance: createPiDoctorAuditor(),
268
+ auditDoctorCompliance: (options) => createPiDoctorAuditor()({ ...options, context: toPiContext(options.context) }),
267
269
  loadNotarySoul: () => loadMainRoleSessionMaterials("notary"),
268
270
  loadNotarySourceRun: loadNotarySourceRunLocator,
269
- loadNavigatorWorkContext: (options) => loadNavigatorWorkContext(pi, options),
271
+ loadNavigatorWorkContext: (options) => loadNavigatorWorkContext(pi, { ...options, context: toPiContext(options.context) }),
270
272
  createNavigatorAttendance: (options) => {
271
273
  return createNavigatorAttendance({
272
- context: options.context,
274
+ context: toPiContext(options.context),
273
275
  role: options.role,
274
276
  phase: options.phase,
275
277
  subjectKey: options.subjectKey,
@@ -301,9 +303,9 @@ export default function roleRuntime(pi: ExtensionAPI): void {
301
303
  }
302
304
  return loadHomeCanonicalSkillBinding(name);
303
305
  },
304
- runReviewerDispatch: (dispatch, options) => reviewerAgent.run(dispatch, options),
306
+ runReviewerDispatch: (dispatch, options) => reviewerAgent.run(dispatch, { ...options, context: toPiContext(options.context) }),
305
307
  shutdownReviewerAgent: () => reviewerAgent.shutdown(),
306
- transcriptFromContext,
307
- auditSoulCompliance: createPiJudgeAuditor(),
308
- })(pi);
308
+ transcriptFromContext: (context) => context.transcript?.() ?? "",
309
+ auditSoulCompliance: (options) => createPiJudgeAuditor()({ ...options, context: toPiContext(options.context) }),
310
+ }, piHostAdapter)(pi);
309
311
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akagilnc/pi-workflow-roles",
3
- "version": "0.1.2521",
3
+ "version": "0.1.2653-next.71811ca",
4
4
  "description": "Soul-bound workflow roles for Pi",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -42,11 +42,11 @@
42
42
  "scripts": {
43
43
  "build": "tsx scripts/generate-tool-execution-observation-schema.ts && tsc -p tsconfig.build.json && node scripts/build-package.mjs",
44
44
  "prepack": "npm run build",
45
- "test": "node --import tsx --import ./scripts/test-process-env-preload.mjs --test test/unit/**/*.test.ts test/contract/**/*.test.ts",
46
- "test:fast": "node --import tsx --import ./scripts/test-process-env-preload.mjs --test test/unit/**/*.test.ts test/contract/**/*.test.ts",
47
- "test:integration": "node --import tsx --import ./scripts/test-process-env-preload.mjs --test test/unit/**/*.test.ts test/contract/**/*.test.ts test/integration/**/*.test.ts",
45
+ "test": "node --import tsx --test test/unit/**/*.test.ts test/contract/**/*.test.ts",
46
+ "test:fast": "node --import tsx --test test/unit/**/*.test.ts test/contract/**/*.test.ts",
47
+ "test:integration": "node --import tsx --test test/unit/**/*.test.ts test/contract/**/*.test.ts test/integration/**/*.test.ts",
48
48
  "test:all": "node scripts/run-test-all.mjs",
49
- "test:adjudication": "node --import tsx --import ./scripts/test-process-env-preload.mjs --test test/adjudication/**/*.test.ts",
49
+ "test:adjudication": "node --import tsx --test test/adjudication/**/*.test.ts",
50
50
  "typecheck": "tsc --noEmit"
51
51
  },
52
52
  "pi": {
@@ -7,40 +7,26 @@ Before invoking the engine, read `../engine-dispatch.md`, resolving that path
7
7
  relative to this note. This note only covers this engine's CLI technical
8
8
  parameters.
9
9
 
10
- ## Entrypoint (verified 2026-08-28)
10
+ ## Invocation examples (local Cursor Agent CLI)
11
11
 
12
- The machine entrypoint is **`cursor-agent`**. Do NOT use the bare `agent`
13
- name on this host: PATH resolves `agent` to the Grok CLI (`~/.grok/bin/agent`
14
- → grok 1.0.5, a different product billed to grok.com Build) — its flags
15
- differ and it fails labor invocations (`--force` unknown; billing 402 when
16
- the Grok Build balance is exhausted).
17
-
18
- ## Invocation (local Cursor Agent CLI)
19
-
20
- Run from the role project root. Non-interactive print mode; `-f/--force`
21
- allows command execution headlessly; `-p` prints responses for scripts:
12
+ The machine entrypoint is `agent` (also exposed as `cursor-agent`). Run from the
13
+ role project root. Non-interactive print mode:
22
14
 
23
15
  ```bash
24
- cursor-agent -p -f --output-format text --model <MODEL_ID> "YOUR_LABOR_PROMPT"
16
+ agent -p --force --output-format text "YOUR_LABOR_PROMPT"
25
17
  ```
26
18
 
27
- - Model ids come from `cursor-agent models`. Effort tiers are encoded in the
28
- id itself (e.g. `cursor-grok-4.6-low`, `cursor-grok-4.6-medium`,
29
- `cursor-grok-4.6-high`, plus `-fast` variants); some models also accept a
30
- bracket override form (`'claude-opus-4-8[context=1m,effort=high]'` — see
31
- `cursor-agent --help`).
32
- - Owner pool directive 2026-08-28: default labor model = `cursor-grok-4.6-low`.
33
- - Stream JSON events for long labor: `--output-format stream-json`.
19
+ Choose a model explicitly when the seat needs a known Cursor model id:
34
20
 
35
- Prefer `cursor-agent --help` on the host over any remembered flag set. Do not
36
- wrap this engine behind `ak-role` flags.
21
+ ```bash
22
+ agent -p --force --model grok-4.5 --output-format text "YOUR_LABOR_PROMPT"
23
+ ```
37
24
 
38
- ## Smoke test (run before first labor leg of a session)
25
+ Stream JSON events for long labor:
39
26
 
40
27
  ```bash
41
- cursor-agent -p -f --output-format text --model cursor-grok-4.6-low "Reply with exactly one word: OK"
28
+ agent -p --force --output-format stream-json "YOUR_LABOR_PROMPT"
42
29
  ```
43
30
 
44
- Expected: stdout ends with exactly `OK`, exit code 0. Verified 2026-08-28 on
45
- this host (Cursor subscription login). If it asks about directory trust, the
46
- `-f` flag (or `--trust`) is missing.
31
+ Prefer `agent --help` on the host over any remembered flag set. Do not wrap this
32
+ engine behind `ak-role` flags.
@@ -33,16 +33,8 @@ hermes -z "YOUR_LABOR_PROMPT" --in /path/to/project --no-restore-cwd \
33
33
  - `--usage-file PATH` (works with `-z` only) writes a JSON spend report
34
34
  (`estimated_cost_usd`, token counts, model, provider, `completed`/`failed`)
35
35
  **even when the run fails** — attach it to the leg's receipt for accounting.
36
- - Long prompts in scripting mode: write the prompt to a file, then pass it as
37
- the single `-z` argument — `hermes -z "$(cat PATH)" ...`. The substitution
38
- result is one argv entry; file content is not re-parsed by the shell.
39
- Smoke-verified 2026-08-28: clean final-response-only stdout.
40
- - `--query-file PATH` belongs to the `hermes chat` subcommand only (mutually
41
- exclusive with its `-q`); it is NOT a top-level flag and does NOT combine
42
- with `-z` — `hermes -z --query-file ...` fails with
43
- `-z/--oneshot: expected one argument` (incident: Ming #1585 fixer leg,
44
- 2026-08-28). `hermes chat --query-file` also prints a session summary
45
- instead of the bare final response, so it is unfit for labor pipelines.
36
+ - Long or untrusted prompts: `--query-file PATH` reads the prompt from a file
37
+ verbatim ("nothing is shell-interpreted"); mutually exclusive with `-q`.
46
38
  - Model/provider default comes from host `~/.hermes/config.yaml`
47
39
  (owner-selected; verified 2026-08-28: `poolside/laguna-s-2.1:free` on Nous
48
40
  Portal). Override with `-m provider/model` + `--provider` only when the
@@ -58,23 +50,10 @@ hermes -z "YOUR_LABOR_PROMPT" --in /path/to/project --no-restore-cwd \
58
50
  intermediate steps on stdout (unlike `-z`) — use when a labor run needs its
59
51
  steps inspected.
60
52
 
61
- ## Measured constraints (host, 2026-08-28)
62
-
63
- - The Nous free tier (`poolside/laguna-s-2.1:free`) rate-limits concurrent
64
- labor calls on one account. Measured: with ~5 factory legs dispatching
65
- simultaneously, losing legs saw sustained HTTP 429 across 9-29 detour
66
- attempts while the 1-2 winners completed normally (Ming_LLM books runs
67
- 01a046ec-*/01a046f4-*, 14:55-15:04 window).
68
- No concurrency ceiling has been measured beyond this observation; policy on
69
- concurrency and retries is the dispatcher's call, not this note's.
70
-
71
53
  ## Smoke test (run before first labor leg of a session)
72
54
 
73
55
  ```bash
74
56
  hermes -z "Reply with exactly one word: OK" --no-restore-cwd
75
- # long-prompt form used by labor legs:
76
- printf 'Reply with exactly one word: OK' > /tmp/smoke.txt
77
- hermes -z "$(cat /tmp/smoke.txt)" --no-restore-cwd
78
57
  ```
79
58
 
80
59
  Expected: stdout is exactly `OK`, exit code 0. Verified 2026-08-28 on this
@@ -18,12 +18,7 @@ requires `--verbose` — without it the CLI exits immediately with
18
18
  Include `--verbose` in stream-json argv. Measured with separate fd redirects
19
19
  (`1>` / `2>`): NDJSON event rows land on stdout (including intermediate
20
20
  `system` / `assistant` activity and a final `type:"result"` row); stderr is
21
- empty on the success path — except when stdin is an open stream supplying no
22
- data (e.g. a shell test without redirection): then a benign
23
- `Warning: no stdin data received in 3s, proceeding without it` lands on stderr
24
- after a 3-second wait (host-verified 2026-08-28); redirect `< /dev/null` in
25
- shell tests. The packaged detour tool spawns engines with stdin ignored
26
- (`/dev/null`), which avoids this path:
21
+ empty on the success path:
27
22
 
28
23
  ```bash
29
24
  claude -p --verbose --output-format=stream-json "YOUR_LABOR_PROMPT"
@@ -41,15 +36,5 @@ Use `--output-format=stream-json` (choices measured on this host: `text`, `json`
41
36
  works; take the labor body from the final `result` event's `result` field,
42
37
  not from intermediate stream rows.
43
38
 
44
- ## Headless permissions
45
-
46
- `--dangerously-skip-permissions` is required in headless labor: the CLI's
47
- permission prompts cannot be answered without a TTY and are auto-denied. In
48
- particular, reading any path outside the project root — such as frozen
49
- attachments under `~/.ak-roles/books/<book>/runs/<run>/attachments/` — is
50
- refused without the flag ("The read was not permitted — I don't have access to
51
- that file outside the current worktree") and succeeds with it (host-verified
52
- 2026-08-28, both directions).
53
-
54
39
  Prefer `claude --help` on the host over any remembered flag set. Do not wrap this
55
40
  engine behind `ak-role` flags.
@@ -9,8 +9,8 @@
9
9
  御史台
10
10
  ↓
11
11
  大理寺
12
- ├─ 有问题(通常) → 修内司 → 大理寺(修内司收卷不经御史台,直回大理寺)
13
- ├─ 需要再审(大理寺点名) → 御史台 → 大理寺
12
+ ├─ 有问题(通常) → 修内司 → 大理寺
13
+ ├─ 需要再审 → 御史台 → 大理寺
14
14
  └─ 收敛 → 调用者合并、关票
15
15
 
16
16
  ## 线上审查材料
@@ -13,7 +13,6 @@ const entries = [
13
13
  "activation-ledger-git",
14
14
  "activation-ledger-topology",
15
15
  "activation-reconciliation",
16
- "archivist-role-run-coordinates",
17
16
  "archivist-record-entry",
18
17
  "typed-provider-http",
19
18
  "upstream-error-testimony",
@@ -26,7 +26,7 @@
26
26
 
27
27
  名实必须相符:占着小型名义、消耗大型资源的测试,按错位缺陷处理。重型名单单列、串行调度,入列逐个有理由。
28
28
 
29
- 日常施工只跑触及面的聚焦测试;全量到绿只在家族或批次的**最终待合并状态**跑一次——**家族车道上的逐腿交卷不是收尾,不得据此索取全量**;之后再有修复,在新的最终状态重跑全量。
29
+ 日常施工只跑触及面的聚焦测试;家族或批次收尾,在最终待合并状态跑一次全量到绿;之后再有修复,重跑全量。
30
30
 
31
31
  ## 未完成交卷
32
32
 
@@ -28,7 +28,7 @@ export class ActivationLedgerError extends Error {
28
28
  * homes would split the family and can write into a consumer repository.
29
29
  * Process home must already be absolute; relative HOME is rejected before any write.
30
30
  */
31
- export function resolveActivationLedgerHome(home: () => string = homedir): string {
31
+ export function resolveActivationLedgerHome(home: () => string = () => process.env.HOME ?? homedir()): string {
32
32
  const processHome = home();
33
33
  if (typeof processHome !== "string" || processHome.length === 0 || !isAbsolute(processHome)) {
34
34
  throw new ActivationLedgerError(