@akagilnc/pi-workflow-roles 0.1.5946 → 0.1.5955
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/CLAUDE.md +1 -1
- package/dist/acp-host/production-host.js +34 -51
- package/dist/collector-tool-schemas.js +1 -1
- package/dist/diarist-contracts.js +8 -6
- package/dist/doctor-contracts.js +1 -1
- package/dist/headless-host/production-host.js +34 -51
- package/dist/migrate-book-topology.js +22 -36
- package/dist/package-contracts/fixer-output.js +1 -1
- package/dist/package-contracts/gatekeeper-output.js +2 -2
- package/dist/package-contracts/navigator-output.js +2 -2
- package/dist/package-contracts/reviewer-output.js +1 -1
- package/dist/package-contracts/terminating-infrastructure.js +6 -23
- package/dist/public-cli/main.js +33 -50
- package/dist/review-submission.js +1 -1
- package/dist/session-dialogue.js +26 -30
- package/package.json +1 -1
- package/src/collector-tool-schemas.ts +1 -1
- package/src/diarist-contracts.ts +10 -8
- package/src/doctor-contracts.ts +1 -1
- package/src/package-contracts/fixer-output.ts +1 -1
- package/src/package-contracts/gatekeeper-output.ts +2 -2
- package/src/package-contracts/navigator-output.ts +2 -2
- package/src/package-contracts/reviewer-output.ts +1 -1
- package/src/package-contracts/terminating-infrastructure.ts +10 -35
- package/src/review-submission.ts +1 -1
- package/src/session-dialogue.ts +22 -31
package/src/diarist-contracts.ts
CHANGED
|
@@ -31,10 +31,10 @@ export type DiaristOutput =
|
|
|
31
31
|
readonly ticketNumber?: number | null;
|
|
32
32
|
/**
|
|
33
33
|
* Dialogue bounds: one entry per session volume, each with one or more ranges.
|
|
34
|
-
* Empty / absent = lawful empty selection (no dialogue this turn).
|
|
34
|
+
* Empty / null / absent = lawful empty selection (no dialogue this turn).
|
|
35
35
|
* Malformed endpoints → accept hook reasks (`reask-not-explode`).
|
|
36
36
|
*/
|
|
37
|
-
readonly sessions?: readonly TicketProvenanceSession[];
|
|
37
|
+
readonly sessions?: readonly TicketProvenanceSession[] | null;
|
|
38
38
|
/** Per-ticket dialogue bounds for a single multi-ticket summons (#1107). */
|
|
39
39
|
readonly ticketSessions?: readonly {
|
|
40
40
|
readonly ticketNumber: number;
|
|
@@ -65,13 +65,13 @@ export function validateRecordedDiaristOutput(value: unknown): DiaristOutput {
|
|
|
65
65
|
|
|
66
66
|
/**
|
|
67
67
|
* Project sessions from a completed diarist payload.
|
|
68
|
-
*
|
|
68
|
+
* Null / absent key → empty (lawful). Non-null but unusable → undefined (caller reasks).
|
|
69
69
|
*/
|
|
70
70
|
export function projectDiaristSessions(
|
|
71
71
|
value: unknown,
|
|
72
72
|
): readonly TicketProvenanceSession[] | undefined {
|
|
73
73
|
const raw = (value as { sessions?: unknown } | null)?.sessions;
|
|
74
|
-
if (raw
|
|
74
|
+
if (raw == null) return [];
|
|
75
75
|
return projectTicketProvenanceSessions(raw);
|
|
76
76
|
}
|
|
77
77
|
|
|
@@ -115,15 +115,17 @@ export const diaristOutputSchema = withTerminatingOutputDeclarations(
|
|
|
115
115
|
ticketNumber: Type.Optional(
|
|
116
116
|
Type.Unknown({
|
|
117
117
|
description:
|
|
118
|
-
"
|
|
118
|
+
"仅有本庭对象时填票号(正整数);没有就填 null=真无票;下游走 typed 键;认不出用 status=escalate,不洗成无录。机械层不重判。",
|
|
119
119
|
}),
|
|
120
120
|
),
|
|
121
121
|
reason: Type.Unknown({
|
|
122
|
-
description: "status 为 escalate
|
|
122
|
+
description: "仅 status 为 escalate 时填上呈的原因;没有就填 null",
|
|
123
123
|
}),
|
|
124
|
-
sessions: Type.Optional(Type.Unknown({
|
|
124
|
+
sessions: Type.Optional(Type.Unknown({
|
|
125
|
+
description: `仅单票庭时填对话边界;没有就填 null。${DIARIST_SESSIONS_DESCRIPTION}`,
|
|
126
|
+
})),
|
|
125
127
|
ticketSessions: Type.Unknown({
|
|
126
|
-
description:
|
|
128
|
+
description: `仅多票庭时填逐票对话边界;没有就填 null。每票含 ticketNumber(本条边界所归票号,正整数)与 sessions(${DIARIST_SESSIONS_DESCRIPTION})。一次交卷各票各自分录。`,
|
|
127
129
|
}),
|
|
128
130
|
}),
|
|
129
131
|
),
|
package/src/doctor-contracts.ts
CHANGED
|
@@ -72,7 +72,7 @@ const doctorSubmissionObject = Type.Object({
|
|
|
72
72
|
`逐条资产观察与处方,原样留存。一条可含 targetKey、targetKind(${DOCTOR_TARGET_KINDS.join(" | ")})、observation、evidenceIds、disposition(${DOCTOR_DISPOSITIONS.join(" | ")})、assetEvidence(targetKey、targetKind、evidenceId)、guardrails(reproducibleFailure、owningSeamOrInvariant、deletionOrSimplificationSuffices,各项可含 answer、evidenceIds、explanation)、prescription(kind 为 ${DOCTOR_PRESCRIPTION_KINDS.join(" | ")},另可写 recommendation、necessityExplanation)、lastRealBite(kind 为 ${DOCTOR_BITE_KINDS.join(" | ")},另可写 targetKey、evidenceId、eligibleEvidenceIds)。不要求任何处方或可复用 finding;缺可复用资产或 bounded-bite 证据只排除对应资产处方。机器不核验。`,
|
|
73
73
|
}),
|
|
74
74
|
reason: Type.Unknown({
|
|
75
|
-
description: "
|
|
75
|
+
description: "仅 refused 时填证据不足以支撑如实证词的原因;没有就填 null",
|
|
76
76
|
}),
|
|
77
77
|
missingEvidence: Type.Unknown({
|
|
78
78
|
description: "如实证词所需而尚缺的证据,原样留存(如每项 need、targetKeys)。",
|
|
@@ -34,7 +34,7 @@ const fixerOutputObject = Type.Object({
|
|
|
34
34
|
diffItems: diffItemsField,
|
|
35
35
|
testEvidence: Type.Unknown({
|
|
36
36
|
description:
|
|
37
|
-
"
|
|
37
|
+
"仅 diff 含测试改动时填测试证据条;没有就填 null。机器不核验。可写 contract(测试改动所证明的契约)、minimumNecessaryCost(测试改动的一行最小必要成本)、measuredDuration(聚焦验证实测时长)。",
|
|
38
38
|
}),
|
|
39
39
|
});
|
|
40
40
|
|
|
@@ -19,10 +19,10 @@ export const gatekeeperDecisionSchema = openToolObject(
|
|
|
19
19
|
description: "dispatch | pass",
|
|
20
20
|
}),
|
|
21
21
|
officer: Type.Unknown({
|
|
22
|
-
description: "status 为 dispatch
|
|
22
|
+
description: "仅 status 为 dispatch 时填 inspector | notary;没有就填 null",
|
|
23
23
|
}),
|
|
24
24
|
findings: Type.Unknown({
|
|
25
|
-
description: "status 为 pass
|
|
25
|
+
description: "仅 status 为 pass 时填 string[] findings;没有就填 null",
|
|
26
26
|
}),
|
|
27
27
|
}),
|
|
28
28
|
);
|
|
@@ -19,7 +19,7 @@ export const NAVIGATOR_OUTPUT_TOOL_NAME = "ak_navigator_output";
|
|
|
19
19
|
*/
|
|
20
20
|
export const navigatorAdviceFields = {
|
|
21
21
|
prose: Type.Unknown({
|
|
22
|
-
description: "
|
|
22
|
+
description: "仅无状态分叉时填单条散文建议;没有就填 null。原样呈现。",
|
|
23
23
|
}),
|
|
24
24
|
byStatus: Type.Unknown({
|
|
25
25
|
description:
|
|
@@ -28,7 +28,7 @@ export const navigatorAdviceFields = {
|
|
|
28
28
|
}),
|
|
29
29
|
byRole: Type.Unknown({
|
|
30
30
|
description:
|
|
31
|
-
"
|
|
31
|
+
"仅直接入口不给角色时填整张路线表(键为衙门角色,值为该衙门 status → 建议);没有就填 null",
|
|
32
32
|
}),
|
|
33
33
|
} as const;
|
|
34
34
|
|
|
@@ -8,7 +8,7 @@ import { withTerminatingOutputDeclarations } from "./terminating-infrastructure.
|
|
|
8
8
|
export const REVIEWER_OUTPUT_TOOL_NAME = "ak_reviewer_output";
|
|
9
9
|
|
|
10
10
|
const REVIEWER_AMENDMENTS_DESCRIPTION =
|
|
11
|
-
"已运行 lens 的 amendments 承载 candidates、逐条处置与 verdict 的完整报告(非仅 verdict
|
|
11
|
+
"已运行 lens 的 amendments 承载 candidates、逐条处置与 verdict 的完整报告(非仅 verdict 行);各轴(completeness / correctness)仅有已产出报告时填报告;没有就填 null。hard-stop/usage error 为 refused 时,已产出报告仍照录对应 lens 字段。" as const;
|
|
12
12
|
// #1134: `status` alone is the trajectory field (#917 §6 two normal lens verdicts →
|
|
13
13
|
// completed; hard-stop / usage error → refused); its words ride the description.
|
|
14
14
|
// amendments/diagnostic are LLM/human-read narrative content returned as
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
* Package-owned shared infrastructure-failure declaration for every primary
|
|
3
3
|
* packaged-role output tool (#541 / #1214 A2).
|
|
4
4
|
*
|
|
5
|
-
* One module owns the
|
|
6
|
-
*
|
|
5
|
+
* One module owns the infrastructureFailure declaration composed into each
|
|
6
|
+
* output tool's schema. Name and semantic description only — no object type, so
|
|
7
|
+
* a null fill is not a shape rejection (#1134). The field is part of the role's
|
|
7
8
|
* original receipt: ledger records it as-is. Declaration alone does not abort
|
|
8
9
|
* the host (#1214 A2). True host/lifecycle failure still fails honestly on its
|
|
9
10
|
* own channel.
|
|
@@ -12,34 +13,11 @@ import { Type, type TSchema } from "typebox";
|
|
|
12
13
|
|
|
13
14
|
export const INFRASTRUCTURE_FAILURE_DECLARATION_KEY =
|
|
14
15
|
"infrastructureFailure" as const;
|
|
15
|
-
export const INFRASTRUCTURE_FAILURE_DIAGNOSTIC_KEY = "diagnostic" as const;
|
|
16
16
|
|
|
17
|
-
/**
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
* the declaration fragment.
|
|
22
|
-
*/
|
|
23
|
-
const infrastructureFailureNested = Type.Object(
|
|
24
|
-
{
|
|
25
|
-
[INFRASTRUCTURE_FAILURE_DIAGNOSTIC_KEY]: Type.Unknown({
|
|
26
|
-
description: "基础设施失败诊断字符串。",
|
|
27
|
-
}),
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
additionalProperties: true,
|
|
31
|
-
description: "仅基础设施真实失败时出现。",
|
|
32
|
-
},
|
|
33
|
-
);
|
|
34
|
-
// Open nested required so host cannot pure-shape-reject the declaration fragment.
|
|
35
|
-
(infrastructureFailureNested as unknown as { required: string[] }).required = [];
|
|
36
|
-
|
|
37
|
-
const infrastructureFailureDeclarationSchema = Type.Object(
|
|
38
|
-
{
|
|
39
|
-
[INFRASTRUCTURE_FAILURE_DECLARATION_KEY]: infrastructureFailureNested,
|
|
40
|
-
},
|
|
41
|
-
{ additionalProperties: true },
|
|
42
|
-
);
|
|
17
|
+
/** Name + semantic description. diagnostic's meaning lives in the description. */
|
|
18
|
+
const infrastructureFailureField = Type.Unknown({
|
|
19
|
+
description: "仅基础设施真实失败时填 {diagnostic};没有就填 null",
|
|
20
|
+
});
|
|
43
21
|
|
|
44
22
|
/**
|
|
45
23
|
* Compose declarations shared by terminating output tools: infrastructure failure,
|
|
@@ -62,7 +40,7 @@ export function withTerminatingOutputDeclarations<
|
|
|
62
40
|
? {
|
|
63
41
|
ticketNumber: Type.Unknown({
|
|
64
42
|
description:
|
|
65
|
-
"
|
|
43
|
+
"仅尚未绑定时填本票号(正整数、数字串或前导 #N;归位只读本字段);没有就填 null",
|
|
66
44
|
}),
|
|
67
45
|
}
|
|
68
46
|
: {}
|
|
@@ -72,15 +50,12 @@ export function withTerminatingOutputDeclarations<
|
|
|
72
50
|
? {
|
|
73
51
|
summary: Type.Unknown({
|
|
74
52
|
description:
|
|
75
|
-
"
|
|
53
|
+
"仅本席有结论时填一两句、20–50 字结论摘要;没有就填 null。不因缺失或超长拒收、截断或代填。",
|
|
76
54
|
}),
|
|
77
55
|
}
|
|
78
56
|
: {}
|
|
79
57
|
),
|
|
80
|
-
[INFRASTRUCTURE_FAILURE_DECLARATION_KEY]:
|
|
81
|
-
infrastructureFailureDeclarationSchema.properties[
|
|
82
|
-
INFRASTRUCTURE_FAILURE_DECLARATION_KEY
|
|
83
|
-
],
|
|
58
|
+
[INFRASTRUCTURE_FAILURE_DECLARATION_KEY]: infrastructureFailureField,
|
|
84
59
|
};
|
|
85
60
|
const object = Type.Object(properties, { additionalProperties: true });
|
|
86
61
|
const incoming = (schema as { required?: unknown }).required;
|
package/src/review-submission.ts
CHANGED
|
@@ -27,7 +27,7 @@ const reviewNarrativeFields = {
|
|
|
27
27
|
reason: Type.Optional(Type.Unknown({ description: "上呈理由" })),
|
|
28
28
|
violations: Type.Optional(Type.Unknown({ description: "违规条目" })),
|
|
29
29
|
conflicts: Type.Optional(Type.Unknown({ description: "待决冲突" })),
|
|
30
|
-
fix: Type.Optional(Type.Unknown({ description: "continue
|
|
30
|
+
fix: Type.Optional(Type.Unknown({ description: "仅 continue 时填补救说明(可写 summary 摘要,其余内容原样留存);没有就填 null" })),
|
|
31
31
|
classes: Type.Optional(Type.Unknown({ description: "已裁决 finding 类;可说明 name、owner、boundary、disposition,原样留存" })),
|
|
32
32
|
note: Type.Optional(Type.Unknown({ description: "裁决附注" })),
|
|
33
33
|
evidence: Type.Optional(Type.Unknown({ description: "留存证据" })),
|
package/src/session-dialogue.ts
CHANGED
|
@@ -6,7 +6,8 @@ import { isRecord } from "./unknown-value.ts";
|
|
|
6
6
|
* 排除按来源、不按正文:说话人自己写下的文字一律原样保留,其中引用了 ADR 段落
|
|
7
7
|
* 或工具结果也不删(#901 Out of Scope「不做正文过滤」)。
|
|
8
8
|
*
|
|
9
|
-
*
|
|
9
|
+
* 不入录的是工具结果载荷、入队行、请求快照与注入块。附件记录同样不入录,
|
|
10
|
+
* 只有 `queued_command` 例外:它是被吸收插话的带 uuid 说话记录(#1260)。
|
|
10
11
|
*
|
|
11
12
|
* 适配规则按宿主并列,不硬套某一宿主的类型名;一行产出 0..n 条对话事实。
|
|
12
13
|
*/
|
|
@@ -107,25 +108,12 @@ function isCodexOwnerResponseItemUser(message: Record<string, unknown>): boolean
|
|
|
107
108
|
return kinds.some((kind) => kind.startsWith("user."));
|
|
108
109
|
}
|
|
109
110
|
|
|
110
|
-
/**
|
|
111
|
-
* 入队事件适配:人类这次输入经队列的来源。
|
|
112
|
-
* 被吸收的插话靠入队事件入录(无独立消息记录,#901 用户故事 11)。
|
|
113
|
-
* 机器入队由整卷适配层排除(#918);本函数不读正文、不自判机器。
|
|
114
|
-
*/
|
|
115
|
-
function fromQueueEvent(row: Record<string, unknown>): DialogueEvent[] {
|
|
116
|
-
if (row.type !== "queue-operation" || row.operation !== "enqueue") return [];
|
|
117
|
-
const content = row.content;
|
|
118
|
-
if (typeof content !== "string" || content === "") return [];
|
|
119
|
-
const id = nativeEventId(row);
|
|
120
|
-
return [{ speaker: "owner", text: content, ...(id === undefined ? {} : { id }) }];
|
|
121
|
-
}
|
|
122
|
-
|
|
123
111
|
/**
|
|
124
112
|
* 票面 #918 准许的唯一固定起始形状:`<task-notification`。
|
|
125
113
|
* 其它标签不在御裁射程内——不得扩表,不得伪造 decision key / 「陛下拍定」。
|
|
126
114
|
* 开标签后可直接 `>`(无属性)、EOF 或空白再接属性;其它字符不成立。
|
|
127
115
|
*
|
|
128
|
-
*
|
|
116
|
+
* 无 origin 的 `queued_command` 只靠本固定形状排除;不得扩表。
|
|
129
117
|
* 用可变载荷正文(全等或子串)做 identity join 仍为锚定宪法所禁。
|
|
130
118
|
*/
|
|
131
119
|
const TASK_NOTIFICATION_OPEN_TAG = "<task-notification";
|
|
@@ -143,9 +131,20 @@ function hasFixedOpenTagPrefix(content: string, tag: string): boolean {
|
|
|
143
131
|
);
|
|
144
132
|
}
|
|
145
133
|
|
|
146
|
-
/**
|
|
147
|
-
|
|
148
|
-
|
|
134
|
+
/**
|
|
135
|
+
* 被吸收的中途插话取 `queued_command` 附件原文(#1260)。
|
|
136
|
+
* 来源按附件 `origin.kind` 判;缺 origin 就当真人,只排除固定开头。
|
|
137
|
+
* 入队行不再是来源,本函数不读入队行、不做正文比对。
|
|
138
|
+
*/
|
|
139
|
+
function fromQueuedCommandAttachment(row: Record<string, unknown>): DialogueEvent[] {
|
|
140
|
+
if (!isRecord(row.attachment) || row.attachment.type !== "queued_command") return [];
|
|
141
|
+
const kind = materializationOriginKind(row.attachment);
|
|
142
|
+
if (isNonOwnerOriginKind(kind)) return [];
|
|
143
|
+
const text = textParts(row.attachment.prompt).join("");
|
|
144
|
+
if (text === "") return [];
|
|
145
|
+
if (kind === undefined && hasFixedOpenTagPrefix(text, TASK_NOTIFICATION_OPEN_TAG)) return [];
|
|
146
|
+
const id = nativeEventId(row);
|
|
147
|
+
return [{ speaker: "owner", text, ...(id === undefined ? {} : { id }) }];
|
|
149
148
|
}
|
|
150
149
|
|
|
151
150
|
/**
|
|
@@ -172,7 +171,7 @@ function isNonOwnerOriginKind(kind: string | undefined): boolean {
|
|
|
172
171
|
}
|
|
173
172
|
|
|
174
173
|
/**
|
|
175
|
-
*
|
|
174
|
+
* 消息事件适配:助手回话,以及 `type=user` 的人类输入。
|
|
176
175
|
* 思考块、工具调用块、工具结果块按块排除;同消息的说话人 text 保留
|
|
177
176
|
* (#901 排除按来源不按正文;混合块不得整条丢弃)。
|
|
178
177
|
* Codex response_item user:仅 `content_item_kinds` 含 `user.*` 时入录。
|
|
@@ -199,27 +198,19 @@ function fromMessageEvent(row: Record<string, unknown>): DialogueEvent[] {
|
|
|
199
198
|
/**
|
|
200
199
|
* 整卷适配:返回与入参行等长的对话事实数组(该行不是对话则为空数组)。
|
|
201
200
|
*
|
|
201
|
+
* 说话来源只取 `type=user` 行与 `queued_command` 附件。入队行与 `api-request-blob`
|
|
202
|
+
* 不投。有原生 id 则带上,不另编。不做正文比对或 id 去重。
|
|
202
203
|
* 物化 user 只消费自身的 typed `origin.kind`:human 保留,具名非 human 排除。
|
|
203
|
-
* enqueue 没有与物化 user 的 typed 关联,故不得以位置把某个 user 来源反扣给它;
|
|
204
|
-
* 仅票面准许的 `<task-notification` 固定形状可直接排除,其余维持既有投影。
|
|
205
204
|
*/
|
|
206
205
|
export function adaptSessionDialogue(
|
|
207
206
|
rows: readonly (Record<string, unknown> | undefined)[],
|
|
208
207
|
): DialogueEvent[][] {
|
|
209
208
|
return rows.map((row) => {
|
|
210
209
|
if (row === undefined) return [];
|
|
210
|
+
if (row.type === "queue-operation" || row.type === "api-request-blob") return [];
|
|
211
|
+
if (row.type === "attachment") return fromQueuedCommandAttachment(row);
|
|
211
212
|
const originKind = materializationOriginKind(row);
|
|
212
213
|
if (isNonOwnerOriginKind(originKind)) return [];
|
|
213
|
-
if (
|
|
214
|
-
row.type === "queue-operation" &&
|
|
215
|
-
row.operation === "enqueue" &&
|
|
216
|
-
typeof row.content === "string" &&
|
|
217
|
-
isFixedNonOwnerEnqueueShape(row.content)
|
|
218
|
-
) {
|
|
219
|
-
return [];
|
|
220
|
-
}
|
|
221
|
-
const queued = fromQueueEvent(row);
|
|
222
|
-
if (queued.length > 0) return queued;
|
|
223
214
|
return fromMessageEvent(row);
|
|
224
215
|
});
|
|
225
216
|
}
|