@akagilnc/pi-workflow-roles 0.1.5235 → 0.1.5241

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.
@@ -127,20 +127,6 @@ export function resolveSitianRecordPathInLedger(
127
127
  return { sessionDir, recordFile, ledgerHome };
128
128
  }
129
129
 
130
- /**
131
- * Owner-visible ticket 起居录 path shape via the writer ticket joins
132
- * (ticketProvenanceUnderBookPaths). Ledger leaf is the package-owned `.ak-roles`
133
- * name (ADR 0048); variable slots keep owner labels; no fake-home path reverse.
134
- */
135
- export function projectTicketRecordsPathShape(): string {
136
- const { recordFile } = ticketProvenanceUnderBookPaths(
137
- join("~", ".ak-roles"),
138
- "<簿>",
139
- "<票号>",
140
- );
141
- return recordFile.replace(/\\/g, "/");
142
- }
143
-
144
130
  /** Compute a write destination from ambient ledger topology (ADR 0065). */
145
131
  export function resolveSitianRecordPath(input: SitianRecordInput): SitianRecordPath {
146
132
  const ledgerHome =
@@ -1,109 +0,0 @@
1
- /**
2
- * 系统随案递送起居录路径的中立指针段(ADR 0081:公共入口直接挂案卷,Soul 只说明用途不负责派送;
3
- * #709 公共入口通用递送与 #742 给事中受理链路同源;#858 告诉 LLM 路径,不另建取号/lookup)。
4
- * 指针输入沿 ADR 0079(指针是绑定材料由代码精准递送),不把卷宗正文塞进提示词。
5
- * 只告诉路径:不刷新、不生成、不校验内容、不新增拒收或停工条件、不从 instruction 抽票号。
6
- * 机器文本仅中立标识材料(ADR 0073),用途说明归角色材料所有。
7
- *
8
- * 递送挂载点唯一:`post-admission` 在 beforeDispatch 之后为每个公共入口挂载。
9
- * 全部公共入口(ordinary 已绑定/未绑定与 station-child)统一走 attachments 冻结 +
10
- * role-runtime `loadCaseDossierReadingMaterial` → readingMaterial →
11
- * systemPrompt.materials fold(#879 / #858:对话 instruction、空请求、resume
12
- * message 保持调用者原文;起居录作独立附件面,不新造 RoleTurnRequest.materials,
13
- * 不拼进 user-dialogue continuation)。
14
- *
15
- * #858: deliver returns typed FrozenAttachment[]; load currently re-derives the
16
- * freeze leaf under runDirectory because agent-start only has HostContext.runDirectory.
17
- * Consuming the typed frozenPath across that process boundary needs a design
18
- * revision of the existing envelope/persistence seam — not a local replica of
19
- * freezeAttachments' `00-` naming, not a drift throw, not readdir guessing.
20
- */
21
- import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
22
- import { tmpdir } from "node:os";
23
- import { join } from "node:path";
24
- import { projectTicketRecordsPathShape } from "../sitian-facade.js";
25
- import { resolveTicketProvenanceVolume } from "../ticket-provenance.js";
26
- import { freezeAttachmentsIntoRun, } from "./invocation.js";
27
- /** Bound-ticket section heading (presentation only). */
28
- const CASE_DOSSIER_SECTION_HEADING = "## 本票起居录(系统随案提供)";
29
- /** Unbound path-only heading — no 本票 claim when no typed ticket is on the run. */
30
- const UNBOUND_DOSSIER_PATH_HEADING = "## 起居录路径(系统随案提供)";
31
- /** Stable freeze key under run/attachments/ for station-child 0081 delivery. */
32
- const CASE_DOSSIER_ATTACH_KEY = "case-dossier";
33
- /** Leaf name of the frozen pointer section (content = purpose + paths). */
34
- const CASE_DOSSIER_ATTACH_FILE = "case-dossier-pointer.md";
35
- /**
36
- * Neutral 起居录 path pointer for every public entry (ADR 0081 delivery seam).
37
- * Always tells the canonical path shape so the seat LLM can read the diary
38
- * itself (陛下 2026-09-15: 只需要告诉llm这个路径). When a typed ticket identity is
39
- * already on the run, also project the concrete resolved file. Never claims a
40
- * volume or「本票」exists when unbound; never extracts a ticket from instruction.
41
- * Under-book shape comes only from sitian writer joins — no local replica.
42
- */
43
- export async function projectCaseDossierPointerSection(input) {
44
- if (input.ticketNumber === undefined) {
45
- return [
46
- UNBOUND_DOSSIER_PATH_HEADING,
47
- "",
48
- `记录卷宗:${projectTicketRecordsPathShape()}`,
49
- ].join("\n");
50
- }
51
- const volume = resolveTicketProvenanceVolume(input.ticketNumber, input.projectRoot, input.home);
52
- return [
53
- CASE_DOSSIER_SECTION_HEADING,
54
- "",
55
- `票号:#${input.ticketNumber}`,
56
- `记录卷宗:${volume.recordFile}`,
57
- ].join("\n");
58
- }
59
- /**
60
- * ADR 0081 delivery for every public entry (#879 / #858): freeze the pointer
61
- * section through the existing attachments seam. Role-runtime loads that freeze
62
- * via loadCaseDossierReadingMaterial onto readingMaterial; the envelope then
63
- * folds it into systemPrompt.materials. Caller / peer dialogue instruction stays
64
- * opaque; never RoleTurnRequest.materials, never user-dialogue continuation.
65
- * Always freezes the path pointer (canonical shape, or concrete file when a
66
- * typed ticket is already bound).
67
- */
68
- export async function deliverCaseDossierAsAttachment(input) {
69
- const section = await projectCaseDossierPointerSection({
70
- ticketNumber: input.ticketNumber,
71
- projectRoot: input.projectRoot,
72
- home: input.home,
73
- });
74
- // Stage in OS temp only — never leave a run-local .case-dossier-stage copy.
75
- const stagingDir = await mkdtemp(join(tmpdir(), "ak-case-dossier-"));
76
- try {
77
- const stagingPath = join(stagingDir, CASE_DOSSIER_ATTACH_FILE);
78
- await writeFile(stagingPath, `${section}\n`, "utf8");
79
- return await freezeAttachmentsIntoRun([stagingPath], input.runDirectory, CASE_DOSSIER_ATTACH_KEY);
80
- }
81
- finally {
82
- await rm(stagingDir, { recursive: true, force: true });
83
- }
84
- }
85
- /**
86
- * Load a previously frozen case-dossier attachment as reading material
87
- * (existing agent-start / systemPrompt.materials fold — not dialogue prompt,
88
- * not RoleTurnRequest.materials). Undefined when the run has no such freeze.
89
- *
90
- * #858: this join re-derives freezeAttachments' leaf naming because the
91
- * agent-start handler only receives runDirectory. Replacing it requires
92
- * threading deliver's typed frozenPath across the existing envelope seam
93
- * (design revision) — do not copy freeze's `00-` algorithm here again.
94
- */
95
- export async function loadCaseDossierReadingMaterial(runDirectory) {
96
- const frozenPath = join(runDirectory, "attachments", CASE_DOSSIER_ATTACH_KEY, `00-${CASE_DOSSIER_ATTACH_FILE}`);
97
- let section;
98
- try {
99
- section = await readFile(frozenPath, "utf8");
100
- }
101
- catch (error) {
102
- if (error.code === "ENOENT")
103
- return undefined;
104
- throw error;
105
- }
106
- if (section.trim() === "")
107
- return undefined;
108
- return { kind: "case-dossier-pointer", frozenPath, section };
109
- }
@@ -1,147 +0,0 @@
1
- /**
2
- * 系统随案递送起居录路径的中立指针段(ADR 0081:公共入口直接挂案卷,Soul 只说明用途不负责派送;
3
- * #709 公共入口通用递送与 #742 给事中受理链路同源;#858 告诉 LLM 路径,不另建取号/lookup)。
4
- * 指针输入沿 ADR 0079(指针是绑定材料由代码精准递送),不把卷宗正文塞进提示词。
5
- * 只告诉路径:不刷新、不生成、不校验内容、不新增拒收或停工条件、不从 instruction 抽票号。
6
- * 机器文本仅中立标识材料(ADR 0073),用途说明归角色材料所有。
7
- *
8
- * 递送挂载点唯一:`post-admission` 在 beforeDispatch 之后为每个公共入口挂载。
9
- * 全部公共入口(ordinary 已绑定/未绑定与 station-child)统一走 attachments 冻结 +
10
- * role-runtime `loadCaseDossierReadingMaterial` → readingMaterial →
11
- * systemPrompt.materials fold(#879 / #858:对话 instruction、空请求、resume
12
- * message 保持调用者原文;起居录作独立附件面,不新造 RoleTurnRequest.materials,
13
- * 不拼进 user-dialogue continuation)。
14
- *
15
- * #858: deliver returns typed FrozenAttachment[]; load currently re-derives the
16
- * freeze leaf under runDirectory because agent-start only has HostContext.runDirectory.
17
- * Consuming the typed frozenPath across that process boundary needs a design
18
- * revision of the existing envelope/persistence seam — not a local replica of
19
- * freezeAttachments' `00-` naming, not a drift throw, not readdir guessing.
20
- */
21
- import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
22
- import { tmpdir } from "node:os";
23
- import { join } from "node:path";
24
-
25
- import { projectTicketRecordsPathShape } from "../sitian-facade.ts";
26
- import { resolveTicketProvenanceVolume } from "../ticket-provenance.ts";
27
- import {
28
- freezeAttachmentsIntoRun,
29
- type FrozenAttachment,
30
- } from "./invocation.ts";
31
-
32
- /** Bound-ticket section heading (presentation only). */
33
- const CASE_DOSSIER_SECTION_HEADING = "## 本票起居录(系统随案提供)" as const;
34
-
35
- /** Unbound path-only heading — no 本票 claim when no typed ticket is on the run. */
36
- const UNBOUND_DOSSIER_PATH_HEADING = "## 起居录路径(系统随案提供)" as const;
37
-
38
- /** Stable freeze key under run/attachments/ for station-child 0081 delivery. */
39
- const CASE_DOSSIER_ATTACH_KEY = "case-dossier" as const;
40
-
41
- /** Leaf name of the frozen pointer section (content = purpose + paths). */
42
- const CASE_DOSSIER_ATTACH_FILE = "case-dossier-pointer.md" as const;
43
-
44
- /**
45
- * Neutral 起居录 path pointer for every public entry (ADR 0081 delivery seam).
46
- * Always tells the canonical path shape so the seat LLM can read the diary
47
- * itself (陛下 2026-09-15: 只需要告诉llm这个路径). When a typed ticket identity is
48
- * already on the run, also project the concrete resolved file. Never claims a
49
- * volume or「本票」exists when unbound; never extracts a ticket from instruction.
50
- * Under-book shape comes only from sitian writer joins — no local replica.
51
- */
52
- export async function projectCaseDossierPointerSection(input: {
53
- readonly ticketNumber: number | undefined;
54
- readonly projectRoot: string;
55
- readonly home: string;
56
- }): Promise<string> {
57
- if (input.ticketNumber === undefined) {
58
- return [
59
- UNBOUND_DOSSIER_PATH_HEADING,
60
- "",
61
- `记录卷宗:${projectTicketRecordsPathShape()}`,
62
- ].join("\n");
63
- }
64
- const volume = resolveTicketProvenanceVolume(
65
- input.ticketNumber,
66
- input.projectRoot,
67
- input.home,
68
- );
69
- return [
70
- CASE_DOSSIER_SECTION_HEADING,
71
- "",
72
- `票号:#${input.ticketNumber}`,
73
- `记录卷宗:${volume.recordFile}`,
74
- ].join("\n");
75
- }
76
-
77
- /**
78
- * ADR 0081 delivery for every public entry (#879 / #858): freeze the pointer
79
- * section through the existing attachments seam. Role-runtime loads that freeze
80
- * via loadCaseDossierReadingMaterial onto readingMaterial; the envelope then
81
- * folds it into systemPrompt.materials. Caller / peer dialogue instruction stays
82
- * opaque; never RoleTurnRequest.materials, never user-dialogue continuation.
83
- * Always freezes the path pointer (canonical shape, or concrete file when a
84
- * typed ticket is already bound).
85
- */
86
- export async function deliverCaseDossierAsAttachment(input: {
87
- readonly ticketNumber: number | undefined;
88
- readonly projectRoot: string;
89
- readonly home: string;
90
- readonly runDirectory: string;
91
- }): Promise<readonly FrozenAttachment[]> {
92
- const section = await projectCaseDossierPointerSection({
93
- ticketNumber: input.ticketNumber,
94
- projectRoot: input.projectRoot,
95
- home: input.home,
96
- });
97
- // Stage in OS temp only — never leave a run-local .case-dossier-stage copy.
98
- const stagingDir = await mkdtemp(join(tmpdir(), "ak-case-dossier-"));
99
- try {
100
- const stagingPath = join(stagingDir, CASE_DOSSIER_ATTACH_FILE);
101
- await writeFile(stagingPath, `${section}\n`, "utf8");
102
- return await freezeAttachmentsIntoRun(
103
- [stagingPath],
104
- input.runDirectory,
105
- CASE_DOSSIER_ATTACH_KEY,
106
- );
107
- } finally {
108
- await rm(stagingDir, { recursive: true, force: true });
109
- }
110
- }
111
-
112
- /** Typed reading-material face for a frozen station-child 0081 attachment. */
113
- export type CaseDossierReadingMaterial = {
114
- readonly kind: "case-dossier-pointer";
115
- readonly frozenPath: string;
116
- readonly section: string;
117
- };
118
-
119
- /**
120
- * Load a previously frozen case-dossier attachment as reading material
121
- * (existing agent-start / systemPrompt.materials fold — not dialogue prompt,
122
- * not RoleTurnRequest.materials). Undefined when the run has no such freeze.
123
- *
124
- * #858: this join re-derives freezeAttachments' leaf naming because the
125
- * agent-start handler only receives runDirectory. Replacing it requires
126
- * threading deliver's typed frozenPath across the existing envelope seam
127
- * (design revision) — do not copy freeze's `00-` algorithm here again.
128
- */
129
- export async function loadCaseDossierReadingMaterial(
130
- runDirectory: string,
131
- ): Promise<CaseDossierReadingMaterial | undefined> {
132
- const frozenPath = join(
133
- runDirectory,
134
- "attachments",
135
- CASE_DOSSIER_ATTACH_KEY,
136
- `00-${CASE_DOSSIER_ATTACH_FILE}`,
137
- );
138
- let section: string;
139
- try {
140
- section = await readFile(frozenPath, "utf8");
141
- } catch (error) {
142
- if ((error as NodeJS.ErrnoException).code === "ENOENT") return undefined;
143
- throw error;
144
- }
145
- if (section.trim() === "") return undefined;
146
- return { kind: "case-dossier-pointer", frozenPath, section };
147
- }