@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
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Project native session assistant stops onto the host-contract knownFailure shape.
3
+ */
4
+ import type { RoleTurnKnownFailure } from "../host-contracts.ts";
5
+ import {
6
+ hasUpstreamErrorTestimony,
7
+ projectConfirmedRemotePayload,
8
+ } from "../upstream-error-testimony.ts";
9
+
10
+ export { hasUpstreamErrorTestimony } from "../upstream-error-testimony.ts";
11
+
12
+ function nonEmptyString(value: unknown): string | undefined {
13
+ return typeof value === "string" && value.trim() !== "" ? value : undefined;
14
+ }
15
+
16
+ function sessionStopDetails(input: {
17
+ readonly errorMessage?: string | null;
18
+ readonly provider?: string;
19
+ readonly model?: string;
20
+ readonly api?: string;
21
+ readonly rawStopReason?: string;
22
+ readonly httpStatus?: number;
23
+ readonly diagnostics?: unknown;
24
+ readonly body?: unknown;
25
+ readonly code?: unknown;
26
+ readonly errno?: unknown;
27
+ }): Record<string, unknown> {
28
+ const details: Record<string, unknown> = {};
29
+ const errorMessage = nonEmptyString(input.errorMessage);
30
+ if (errorMessage !== undefined) details.errorMessage = errorMessage;
31
+ const api = nonEmptyString(input.api);
32
+ if (api !== undefined) details.api = api;
33
+ const rawStopReason = nonEmptyString(input.rawStopReason);
34
+ if (rawStopReason !== undefined) details.rawStopReason = rawStopReason;
35
+ const testimony = hasUpstreamErrorTestimony(input);
36
+ if (testimony) {
37
+ const provider = nonEmptyString(input.provider);
38
+ if (provider !== undefined) details.provider = provider;
39
+ const model = nonEmptyString(input.model);
40
+ if (model !== undefined) details.model = model;
41
+ }
42
+ if (typeof input.httpStatus === "number") details.httpStatus = input.httpStatus;
43
+ if (input.diagnostics !== undefined) details.diagnostics = input.diagnostics;
44
+ // SDK structured payload fields: project only when held on a confirmed-remote node.
45
+ if (testimony) Object.assign(details, projectConfirmedRemotePayload(input));
46
+ return details;
47
+ }
48
+
49
+ /**
50
+ * Project a native session assistant stop onto the existing knownFailure chain.
51
+ * Classification follows two-way testimony: typed HTTP status or SDK structure
52
+ * keeps provider; stopReason, configured provider/model, or errorMessage prose
53
+ * alone is the existing unrecognized value. Present upstream payload is preserved
54
+ * in details without rewriting; missing fields are omitted.
55
+ */
56
+ export function knownFailureFromProviderStop(input: {
57
+ readonly stopReason?: string;
58
+ readonly errorMessage?: string | null;
59
+ readonly provider?: string;
60
+ readonly model?: string;
61
+ readonly api?: string;
62
+ readonly rawStopReason?: string;
63
+ readonly httpStatus?: number;
64
+ readonly diagnostics?: unknown;
65
+ readonly body?: unknown;
66
+ readonly code?: unknown;
67
+ readonly errno?: unknown;
68
+ }): RoleTurnKnownFailure | undefined {
69
+ if (input.stopReason !== "error" && input.stopReason !== "aborted") return undefined;
70
+ const diagnostic = nonEmptyString(input.errorMessage);
71
+ const details = sessionStopDetails(input);
72
+ return {
73
+ cause: hasUpstreamErrorTestimony(input) ? "provider" : "unrecognized",
74
+ ...(diagnostic === undefined ? {} : { diagnostic }),
75
+ ...(Object.keys(details).length === 0 ? {} : { details }),
76
+ };
77
+ }
@@ -0,0 +1,284 @@
1
+ /**
2
+ * Pi adapter session normalization translation point (#520 r8 / #513).
3
+ * Normalizes Pi native frames at attempt settlement to minimal canonical records.
4
+ * Promotes and owns session parsing primitives previously in ledger-session-read.ts.
5
+ */
6
+ import { readFile } from "node:fs/promises";
7
+ import { basename } from "node:path";
8
+
9
+ import {
10
+ sitianReport,
11
+ type RecordPointer,
12
+ type SitianSubject,
13
+ type SitianUsage,
14
+ } from "../sitian-facade.ts";
15
+
16
+ export type SessionRow = Record<string, unknown>;
17
+
18
+ function isRecord(value: unknown): value is Record<string, unknown> {
19
+ return typeof value === "object" && value !== null && !Array.isArray(value);
20
+ }
21
+
22
+ /** First and last record timestamps in encounter order. */
23
+ export function extractSessionTimestampSpan(
24
+ rows: readonly SessionRow[],
25
+ ): { startedAt?: string; endedAt?: string } {
26
+ let startedAt: string | undefined;
27
+ let endedAt: string | undefined;
28
+ for (const row of rows) {
29
+ if (typeof row.timestamp !== "string" || !row.timestamp) continue;
30
+ if (startedAt === undefined) startedAt = row.timestamp;
31
+ endedAt = row.timestamp;
32
+ }
33
+ return {
34
+ ...(startedAt !== undefined ? { startedAt } : {}),
35
+ ...(endedAt !== undefined ? { endedAt } : {}),
36
+ };
37
+ }
38
+
39
+ /**
40
+ * Ordered-unique model ids from session frames (first-seen order).
41
+ * Sources:
42
+ * - `model_change.modelId`
43
+ * - assistant `message.model`
44
+ */
45
+ export function extractSessionModelSequence(
46
+ rows: readonly SessionRow[],
47
+ ): string[] {
48
+ const seen = new Set<string>();
49
+ const ordered: string[] = [];
50
+ const push = (raw: string): void => {
51
+ const model = raw.trim();
52
+ if (model === "" || seen.has(model)) return;
53
+ seen.add(model);
54
+ ordered.push(model);
55
+ };
56
+ for (const row of rows) {
57
+ if (row.type === "model_change" && typeof row.modelId === "string") {
58
+ push(row.modelId);
59
+ }
60
+ const message = isRecord(row.message) ? row.message : undefined;
61
+ if (message?.role === "assistant" && typeof message.model === "string") {
62
+ push(message.model);
63
+ }
64
+ }
65
+ return ordered;
66
+ }
67
+
68
+ /** First line of a bash `command` argument (sole owner of this summary). */
69
+ export function bashCommandFirstLine(command: string): string {
70
+ const match = /^[^\r\n]*/.exec(command);
71
+ return match?.[0] ?? "";
72
+ }
73
+
74
+ export type SessionToolInterval = {
75
+ readonly toolCallId: string;
76
+ readonly toolName: string;
77
+ readonly startedAt: string;
78
+ readonly endedAt?: string | undefined;
79
+ readonly command?: string | undefined;
80
+ readonly isError?: boolean | undefined;
81
+ };
82
+
83
+ /**
84
+ * Pair toolCall frames → toolResult frames by toolCallId.
85
+ */
86
+ export function extractSessionToolIntervals(
87
+ rows: readonly SessionRow[],
88
+ ): SessionToolInterval[] {
89
+ type Open = {
90
+ toolCallId: string;
91
+ toolName: string;
92
+ startedAt: string;
93
+ endedAt?: string | undefined;
94
+ command?: string | undefined;
95
+ isError?: boolean | undefined;
96
+ };
97
+ const order: Open[] = [];
98
+ const openById = new Map<string, Open>();
99
+
100
+ for (const row of rows) {
101
+ const rowTimestamp = typeof row.timestamp === "string" ? row.timestamp : undefined;
102
+ const message = isRecord(row.message) ? row.message : undefined;
103
+
104
+ if (message?.role === "assistant" && Array.isArray(message.content)) {
105
+ const callTimestamp =
106
+ typeof message.timestamp === "string" && message.timestamp
107
+ ? message.timestamp
108
+ : rowTimestamp;
109
+ for (const part of message.content) {
110
+ if (!isRecord(part) || part.type !== "toolCall") continue;
111
+ if (typeof part.id !== "string" || part.id.length === 0) continue;
112
+ if (typeof part.name !== "string" || part.name.length === 0) continue;
113
+ const timestamp = callTimestamp ?? new Date().toISOString();
114
+ if (openById.has(part.id)) continue;
115
+
116
+ const args = isRecord(part.arguments) ? part.arguments : undefined;
117
+ const command =
118
+ part.name === "bash" &&
119
+ args !== undefined &&
120
+ typeof args.command === "string"
121
+ ? bashCommandFirstLine(args.command)
122
+ : undefined;
123
+
124
+ const interval: Open = {
125
+ toolCallId: part.id,
126
+ toolName: part.name,
127
+ startedAt: timestamp,
128
+ ...(command !== undefined ? { command } : {}),
129
+ };
130
+ order.push(interval);
131
+ openById.set(part.id, interval);
132
+ }
133
+ }
134
+
135
+ if (message?.role === "toolResult") {
136
+ if (typeof message.toolCallId !== "string" || message.toolCallId.length === 0) {
137
+ continue;
138
+ }
139
+ const resultTimestamp =
140
+ typeof message.timestamp === "string" && message.timestamp
141
+ ? message.timestamp
142
+ : rowTimestamp ?? new Date().toISOString();
143
+
144
+ const open = openById.get(message.toolCallId);
145
+ if (open === undefined) {
146
+ const toolName =
147
+ typeof message.toolName === "string" && message.toolName.length > 0
148
+ ? message.toolName
149
+ : "unknown";
150
+ order.push({
151
+ toolCallId: message.toolCallId,
152
+ toolName,
153
+ startedAt: resultTimestamp,
154
+ endedAt: resultTimestamp,
155
+ ...(typeof message.isError === "boolean" ? { isError: message.isError } : {}),
156
+ });
157
+ continue;
158
+ }
159
+ open.endedAt = resultTimestamp;
160
+ if (typeof message.isError === "boolean") {
161
+ open.isError = message.isError;
162
+ }
163
+ }
164
+ }
165
+
166
+ return order.map((interval) => ({
167
+ toolCallId: interval.toolCallId,
168
+ toolName: interval.toolName,
169
+ startedAt: interval.startedAt,
170
+ ...(interval.endedAt !== undefined ? { endedAt: interval.endedAt } : {}),
171
+ ...(interval.command !== undefined ? { command: interval.command } : {}),
172
+ ...(interval.isError !== undefined ? { isError: interval.isError } : {}),
173
+ }));
174
+ }
175
+
176
+ export type NormalizePiSessionAttemptOptions = {
177
+ readonly sessionFile: string;
178
+ readonly cwd?: string | undefined;
179
+ readonly subject?: SitianSubject | undefined;
180
+ };
181
+
182
+ /**
183
+ * Normalizes one Pi session attempt into canonical Sitian records.
184
+ * Carries raw pointers back to original frames without copying full transcripts (#513).
185
+ * Deterministically derives canonical identities (${sessionId}:${frameId}) for idempotent persistence.
186
+ */
187
+ export async function normalizePiSessionAttempt(
188
+ options: NormalizePiSessionAttemptOptions,
189
+ ): Promise<readonly RecordPointer[]> {
190
+ const text = await readFile(options.sessionFile, "utf8");
191
+ const lines = text.split("\n");
192
+ const pointers: RecordPointer[] = [];
193
+
194
+ const validRows: SessionRow[] = [];
195
+ let sessionId = basename(options.sessionFile, ".jsonl");
196
+ let aggregatedUsage: SitianUsage | undefined;
197
+
198
+ for (let index = 0; index < lines.length; index += 1) {
199
+ const line = lines[index]!;
200
+ if (!line.trim()) continue;
201
+
202
+ try {
203
+ const parsed = JSON.parse(line);
204
+ if (!isRecord(parsed)) {
205
+ throw new Error("non-object session frame");
206
+ }
207
+ validRows.push(parsed);
208
+
209
+ if (parsed.type === "session" && typeof parsed.id === "string" && parsed.id.length > 0) {
210
+ sessionId = parsed.id;
211
+ }
212
+
213
+ const message = isRecord(parsed.message) ? parsed.message : undefined;
214
+ if (message?.role === "assistant" && isRecord(message.usage)) {
215
+ const u = message.usage;
216
+ aggregatedUsage = {
217
+ promptTokens: (aggregatedUsage?.promptTokens ?? 0) + (typeof u.promptTokens === "number" ? u.promptTokens : 0),
218
+ completionTokens: (aggregatedUsage?.completionTokens ?? 0) + (typeof u.completionTokens === "number" ? u.completionTokens : 0),
219
+ totalTokens: (aggregatedUsage?.totalTokens ?? 0) + (typeof u.totalTokens === "number" ? u.totalTokens : 0),
220
+ };
221
+ }
222
+ } catch (error) {
223
+ // Normalization failure: record typed failure and keep traversing
224
+ const ptr = sitianReport({
225
+ level: "event",
226
+ kind: "normalization-failure",
227
+ cwd: options.cwd,
228
+ subject: options.subject,
229
+ identity: `${sessionId}:bad-line-${index + 1}`,
230
+ raw: { sessionFile: options.sessionFile, entryId: index + 1 },
231
+ payload: {
232
+ line: index + 1,
233
+ rawText: line,
234
+ error: error instanceof Error ? error.message : String(error),
235
+ },
236
+ source: "pi-normalization",
237
+ });
238
+ pointers.push(ptr);
239
+ }
240
+ }
241
+
242
+ const models = extractSessionModelSequence(validRows);
243
+ const span = extractSessionTimestampSpan(validRows);
244
+ const toolIntervals = extractSessionToolIntervals(validRows);
245
+
246
+ // Normalize paired tool intervals into canonical tool-call event records
247
+ for (const interval of toolIntervals) {
248
+ const ptr = sitianReport({
249
+ level: "event",
250
+ kind: "tool-call",
251
+ cwd: options.cwd,
252
+ subject: options.subject,
253
+ identity: `${sessionId}:${interval.toolCallId}`,
254
+ raw: { sessionFile: options.sessionFile, entryId: interval.toolCallId },
255
+ payload: interval,
256
+ timestamp: interval.startedAt,
257
+ source: "pi-normalization",
258
+ });
259
+ pointers.push(ptr);
260
+ }
261
+
262
+ // Normalize attempt summary into run-summary record
263
+ const summaryTimestamp = span.endedAt ?? span.startedAt ?? new Date().toISOString();
264
+ const summaryPtr = sitianReport({
265
+ level: "run-summary",
266
+ kind: "attempt-summary",
267
+ cwd: options.cwd,
268
+ subject: options.subject,
269
+ identity: `${sessionId}:summary`,
270
+ raw: { sessionFile: options.sessionFile, entryId: "summary" },
271
+ payload: {
272
+ startedAt: span.startedAt,
273
+ endedAt: span.endedAt,
274
+ models,
275
+ toolIntervals,
276
+ },
277
+ ...(aggregatedUsage !== undefined ? { usage: aggregatedUsage } : {}),
278
+ timestamp: summaryTimestamp,
279
+ source: "pi-normalization",
280
+ });
281
+ pointers.push(summaryPtr);
282
+
283
+ return pointers;
284
+ }