@akagilnc/pi-workflow-roles 0.1.3412 → 0.1.3439

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 (67) hide show
  1. package/dist/archivist-record-entry.js +21 -12
  2. package/dist/archivist-record-topology.js +20 -0
  3. package/dist/auditor-dossier-tool.js +67 -76
  4. package/dist/canonical-json.js +66 -69
  5. package/dist/compliance-transport.js +99 -86
  6. package/dist/countersign-contracts.js +23 -25
  7. package/dist/doctor-contracts.js +169 -145
  8. package/dist/engine-detour-tool.js +83 -87
  9. package/dist/engine-detour.js +148 -183
  10. package/dist/evidence-child-executor.js +10 -1
  11. package/dist/exact-utf8.js +11 -10
  12. package/dist/git-object-id.js +10 -5
  13. package/dist/gleaner-left-contracts.js +33 -35
  14. package/dist/grok/production-host.js +229 -118
  15. package/dist/inspector-contracts.js +28 -31
  16. package/dist/institutional-resolution.js +101 -104
  17. package/dist/ledger-session-read.js +241 -0
  18. package/dist/merger-contracts.js +66 -56
  19. package/dist/notary-contracts.js +91 -100
  20. package/dist/open-tool-schema.js +32 -31
  21. package/dist/package-contracts/collector-output.js +56 -43
  22. package/dist/package-contracts/fixer-output.js +52 -50
  23. package/dist/package-contracts/fixer-packet.js +67 -64
  24. package/dist/package-contracts/gatekeeper-output.js +48 -56
  25. package/dist/package-contracts/judge-output.js +23 -20
  26. package/dist/package-contracts/navigator-output.js +35 -40
  27. package/dist/package-contracts/reviewer-output.js +94 -110
  28. package/dist/package-contracts/terminating-infrastructure.js +62 -90
  29. package/dist/package-contracts/worker-output.js +30 -11
  30. package/dist/package-resources/engine-material.js +58 -94
  31. package/dist/public-cli/config.js +420 -484
  32. package/dist/public-cli/main.js +1219 -524
  33. package/dist/public-cli/registry.js +107 -114
  34. package/dist/receipt-delivery-policy.js +74 -76
  35. package/dist/session-opening-materials.js +44 -47
  36. package/dist/sha256.js +5 -3
  37. package/dist/sitian-appender.js +204 -210
  38. package/dist/sitian-contracts.js +15 -19
  39. package/dist/sitian-facade.js +5 -10
  40. package/dist/sitian-reader.js +37 -46
  41. package/dist/stream-idle-guard.js +63 -71
  42. package/dist/ticket-seat-memory.js +244 -0
  43. package/package.json +1 -1
  44. package/scripts/build-package.mjs +41 -0
  45. package/souls/audit-law.md +4 -0
  46. package/souls/countersign.md +1 -1
  47. package/souls/gleaner-left.md +1 -1
  48. package/souls/inspector.md +1 -1
  49. package/souls/notary.md +1 -1
  50. package/souls/reviewer.md +1 -1
  51. package/src/analyst-gate-cycles-read.ts +152 -83
  52. package/src/analyst-ledger.ts +170 -43
  53. package/src/archivist-record-entry.ts +32 -11
  54. package/src/archivist-record-topology.ts +39 -0
  55. package/src/evidence-child-executor.ts +14 -1
  56. package/src/grok/production-host.ts +44 -9
  57. package/src/host-contracts.ts +18 -0
  58. package/src/host-transition-prior-native.ts +8 -1
  59. package/src/ledger-session-read.ts +56 -0
  60. package/src/pi/durable-principal.ts +6 -0
  61. package/src/public-cli/inspector-run.ts +21 -10
  62. package/src/public-cli/invocation.ts +4 -20
  63. package/src/public-cli/notary-run.ts +21 -4
  64. package/src/public-cli/post-admission.ts +333 -42
  65. package/src/public-cli/settlement.ts +266 -81
  66. package/src/session-opening-materials.ts +4 -2
  67. package/src/ticket-seat-memory.ts +454 -0
@@ -1,75 +1,67 @@
1
- /**
2
- * Stream idle backstop (#102 / #155 a): first-wait + between-event silence only.
3
- * Not a total wall-clock for long thinking turns.
4
- *
5
- * Default silence budget is owner-final 183s (#102 2026-08-04),
6
- * same numeric value as header timeoutMs but a distinct body-idle clock.
7
- */
8
- export const DEFAULT_STREAM_IDLE_TIMEOUT_MS = 183_000;
9
- export const STREAM_IDLE_TIMEOUT_CODE = "AK_STREAM_IDLE_TIMEOUT";
10
- export class StreamIdleTimeoutError extends Error {
11
- code = STREAM_IDLE_TIMEOUT_CODE;
12
- idleTimeoutMs;
13
- constructor(idleTimeoutMs, options) {
14
- super(`stream idle timeout after ${idleTimeoutMs}ms`, options);
15
- this.name = "StreamIdleTimeoutError";
16
- this.idleTimeoutMs = idleTimeoutMs;
17
- }
1
+ const DEFAULT_STREAM_IDLE_TIMEOUT_MS = 183e3;
2
+ const STREAM_IDLE_TIMEOUT_CODE = "AK_STREAM_IDLE_TIMEOUT";
3
+ class StreamIdleTimeoutError extends Error {
4
+ code = STREAM_IDLE_TIMEOUT_CODE;
5
+ idleTimeoutMs;
6
+ constructor(idleTimeoutMs, options) {
7
+ super(`stream idle timeout after ${idleTimeoutMs}ms`, options);
8
+ this.name = "StreamIdleTimeoutError";
9
+ this.idleTimeoutMs = idleTimeoutMs;
10
+ }
18
11
  }
19
- export function isStreamIdleTimeoutError(value) {
20
- return value instanceof StreamIdleTimeoutError
21
- || (typeof value === "object"
22
- && value !== null
23
- && value.name === "StreamIdleTimeoutError"
24
- && value.code === STREAM_IDLE_TIMEOUT_CODE);
12
+ function isStreamIdleTimeoutError(value) {
13
+ return value instanceof StreamIdleTimeoutError || typeof value === "object" && value !== null && value.name === "StreamIdleTimeoutError" && value.code === STREAM_IDLE_TIMEOUT_CODE;
25
14
  }
26
- export function createStreamIdleGuard(options = {}) {
27
- const idleTimeoutMs = options.idleTimeoutMs ?? DEFAULT_STREAM_IDLE_TIMEOUT_MS;
28
- const parentSignal = options.parentSignal;
29
- const controller = new AbortController();
30
- let timer;
31
- let disposed = false;
32
- const clear = () => {
33
- if (timer !== undefined) {
34
- clearTimeout(timer);
35
- timer = undefined;
36
- }
37
- };
38
- const arm = () => {
39
- if (disposed || controller.signal.aborted || idleTimeoutMs <= 0)
40
- return;
41
- clear();
42
- timer = setTimeout(() => {
43
- timer = undefined;
44
- if (disposed || controller.signal.aborted)
45
- return;
46
- controller.abort(new StreamIdleTimeoutError(idleTimeoutMs));
47
- }, idleTimeoutMs);
48
- };
49
- const onParentAbort = () => {
50
- if (controller.signal.aborted)
51
- return;
52
- clear();
53
- controller.abort(parentSignal?.reason);
54
- };
55
- if (parentSignal !== undefined) {
56
- if (parentSignal.aborted) {
57
- controller.abort(parentSignal.reason);
58
- }
59
- else {
60
- parentSignal.addEventListener("abort", onParentAbort);
61
- }
15
+ function createStreamIdleGuard(options = {}) {
16
+ const idleTimeoutMs = options.idleTimeoutMs ?? DEFAULT_STREAM_IDLE_TIMEOUT_MS;
17
+ const parentSignal = options.parentSignal;
18
+ const controller = new AbortController();
19
+ let timer;
20
+ let disposed = false;
21
+ const clear = () => {
22
+ if (timer !== void 0) {
23
+ clearTimeout(timer);
24
+ timer = void 0;
25
+ }
26
+ };
27
+ const arm = () => {
28
+ if (disposed || controller.signal.aborted || idleTimeoutMs <= 0) return;
29
+ clear();
30
+ timer = setTimeout(() => {
31
+ timer = void 0;
32
+ if (disposed || controller.signal.aborted) return;
33
+ controller.abort(new StreamIdleTimeoutError(idleTimeoutMs));
34
+ }, idleTimeoutMs);
35
+ };
36
+ const onParentAbort = () => {
37
+ if (controller.signal.aborted) return;
38
+ clear();
39
+ controller.abort(parentSignal?.reason);
40
+ };
41
+ if (parentSignal !== void 0) {
42
+ if (parentSignal.aborted) {
43
+ controller.abort(parentSignal.reason);
44
+ } else {
45
+ parentSignal.addEventListener("abort", onParentAbort);
46
+ }
47
+ }
48
+ arm();
49
+ return {
50
+ signal: controller.signal,
51
+ poke() {
52
+ arm();
53
+ },
54
+ dispose() {
55
+ disposed = true;
56
+ clear();
57
+ parentSignal?.removeEventListener("abort", onParentAbort);
62
58
  }
63
- arm();
64
- return {
65
- signal: controller.signal,
66
- poke() {
67
- arm();
68
- },
69
- dispose() {
70
- disposed = true;
71
- clear();
72
- parentSignal?.removeEventListener("abort", onParentAbort);
73
- },
74
- };
59
+ };
75
60
  }
61
+ export {
62
+ DEFAULT_STREAM_IDLE_TIMEOUT_MS,
63
+ STREAM_IDLE_TIMEOUT_CODE,
64
+ StreamIdleTimeoutError,
65
+ createStreamIdleGuard,
66
+ isStreamIdleTimeoutError
67
+ };
@@ -0,0 +1,244 @@
1
+ import { existsSync } from "node:fs";
2
+ import { readFile, writeFile } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ import { pathToFileURL } from "node:url";
5
+ import { homeFromRunDirectory } from "./activation-ledger-topology.js";
6
+ import { subjectKeyedRecordDirectory } from "./archivist-record-topology.js";
7
+ import { resolvePackageRootDir } from "./session-opening-materials.js";
8
+ const TICKET_SEAT_RUN_BINDING_ENTRY_TYPE = "ak_ticket_seat_run_binding";
9
+ function isTicketSeatRunBindingRow(row) {
10
+ return row.type === "custom" && row.customType === TICKET_SEAT_RUN_BINDING_ENTRY_TYPE;
11
+ }
12
+ function ticketSeatRunBindingRunId(row) {
13
+ if (!isTicketSeatRunBindingRow(row)) return void 0;
14
+ if (row.data === null || typeof row.data !== "object" || Array.isArray(row.data)) {
15
+ return void 0;
16
+ }
17
+ const runId = row.data.runId;
18
+ return typeof runId === "string" && runId.length > 0 ? runId : void 0;
19
+ }
20
+ async function loadCreateRecordSessionOpen() {
21
+ const packageRoot = resolvePackageRootDir(import.meta.url);
22
+ const built = join(packageRoot, "dist/archivist-record-entry.js");
23
+ const source = join(packageRoot, "src/archivist-record-entry.ts");
24
+ const target = existsSync(built) ? built : source;
25
+ const mod = await import(pathToFileURL(target).href);
26
+ return mod.createRecordSessionOpen;
27
+ }
28
+ const TICKET_SEAT_MEMORY_KIND = "auditor-roles";
29
+ const TICKET_SEAT_MEMORY_SEATS = ["inspector", "notary", "auditor"];
30
+ function isTicketSeatMemorySeat(value) {
31
+ return TICKET_SEAT_MEMORY_SEATS.includes(value);
32
+ }
33
+ function isTicketSeatMemoryBound(input) {
34
+ return isTicketSeatMemorySeat(input.role) && typeof input.ticketNumber === "number" && Number.isSafeInteger(input.ticketNumber) && input.ticketNumber >= 1;
35
+ }
36
+ function isEnoent(error) {
37
+ return error instanceof Error && "code" in error && error.code === "ENOENT";
38
+ }
39
+ function ticketSeatMemorySubject(ticketNumber, seat) {
40
+ if (!Number.isSafeInteger(ticketNumber) || ticketNumber < 1) {
41
+ throw new Error(
42
+ `ticket-seat memory subject requires a positive ticket number, got ${String(ticketNumber)}`
43
+ );
44
+ }
45
+ return `${ticketNumber}:${seat}`;
46
+ }
47
+ function ticketSeatMemorySessionDirectory(input) {
48
+ return subjectKeyedRecordDirectory({
49
+ cwd: input.cwd,
50
+ kind: TICKET_SEAT_MEMORY_KIND,
51
+ subject: ticketSeatMemorySubject(input.ticketNumber, input.seat),
52
+ ...input.parentSessionFile === void 0 ? {} : { parentSessionFile: input.parentSessionFile },
53
+ ...input.home === void 0 ? {} : { home: input.home }
54
+ });
55
+ }
56
+ async function readRunAdmittedPageFacts(runDirectory) {
57
+ try {
58
+ const raw = JSON.parse(
59
+ await readFile(join(runDirectory, "admitted-request.json"), "utf8")
60
+ );
61
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
62
+ return {};
63
+ }
64
+ const record = raw;
65
+ const ticketNumber = record.ticketNumber;
66
+ const projectRoot = record.projectRoot;
67
+ return {
68
+ ...typeof ticketNumber === "number" && Number.isSafeInteger(ticketNumber) && ticketNumber >= 1 ? { ticketNumber } : {},
69
+ ...typeof projectRoot === "string" ? { projectRoot } : {}
70
+ };
71
+ } catch (error) {
72
+ if (isEnoent(error)) return {};
73
+ throw error;
74
+ }
75
+ }
76
+ async function readInvocationTicketNumber(runDirectory) {
77
+ try {
78
+ const raw = JSON.parse(
79
+ await readFile(join(runDirectory, "invocation.json"), "utf8")
80
+ );
81
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw)) {
82
+ return void 0;
83
+ }
84
+ const ticketNumber = raw.ticketNumber;
85
+ if (typeof ticketNumber === "number" && Number.isSafeInteger(ticketNumber) && ticketNumber >= 1) {
86
+ return ticketNumber;
87
+ }
88
+ } catch (error) {
89
+ if (isEnoent(error)) return void 0;
90
+ throw error;
91
+ }
92
+ return void 0;
93
+ }
94
+ async function readRunTicketNumber(runDirectory) {
95
+ const admitted = await readRunAdmittedPageFacts(runDirectory);
96
+ if (admitted.ticketNumber !== void 0) return admitted.ticketNumber;
97
+ return readInvocationTicketNumber(runDirectory);
98
+ }
99
+ async function resolveTicketSeatMemoryNestDirectories(input) {
100
+ if (input.seats.length === 0) return [];
101
+ const admitted = await readRunAdmittedPageFacts(input.runDirectory);
102
+ const ticketNumber = admitted.ticketNumber ?? await readInvocationTicketNumber(input.runDirectory);
103
+ if (ticketNumber === void 0) return [];
104
+ let home;
105
+ try {
106
+ home = homeFromRunDirectory(input.runDirectory);
107
+ } catch {
108
+ return [];
109
+ }
110
+ const projectRoot = admitted.projectRoot;
111
+ if (projectRoot === void 0) return [];
112
+ return input.seats.map(
113
+ (seat) => ticketSeatMemorySessionDirectory({
114
+ ticketNumber,
115
+ seat,
116
+ cwd: projectRoot,
117
+ home
118
+ })
119
+ );
120
+ }
121
+ async function openTicketSeatMemoryCoordinates(input) {
122
+ const createRecordSessionOpen = await loadCreateRecordSessionOpen();
123
+ const opened = createRecordSessionOpen({
124
+ cwd: input.cwd,
125
+ kind: TICKET_SEAT_MEMORY_KIND,
126
+ subject: ticketSeatMemorySubject(input.ticketNumber, input.seat),
127
+ parent: {
128
+ getSessionFile: () => input.ledgerAnchorSessionFile
129
+ }
130
+ });
131
+ if (input.runId !== void 0) {
132
+ const data = { version: 1, runId: input.runId };
133
+ opened.session.appendCustomEntry(TICKET_SEAT_RUN_BINDING_ENTRY_TYPE, data);
134
+ }
135
+ const sessionFile = opened.session.getSessionFile();
136
+ const sessionDirectory = opened.session.getSessionDir();
137
+ if (typeof sessionFile !== "string" || sessionFile.length === 0) {
138
+ throw new Error(
139
+ `ticket-seat memory principal missing session file for ticket #${input.ticketNumber} seat ${input.seat}`
140
+ );
141
+ }
142
+ if (typeof sessionDirectory !== "string" || sessionDirectory.length === 0) {
143
+ throw new Error(
144
+ `ticket-seat memory principal missing session directory for ticket #${input.ticketNumber} seat ${input.seat}`
145
+ );
146
+ }
147
+ return { sessionDirectory, sessionFile, resumed: opened.resumed };
148
+ }
149
+ async function rebindAdmittedToTicketSeatMemory(input) {
150
+ const ticketNumber = input.admitted.ticketNumber;
151
+ if (ticketNumber === void 0) return void 0;
152
+ const anchor = input.principalAuthority.decode(input.admitted.principal);
153
+ const opened = await openTicketSeatMemoryCoordinates({
154
+ ticketNumber,
155
+ seat: input.seat,
156
+ cwd: input.admitted.projectRoot,
157
+ ledgerAnchorSessionFile: anchor.sessionFile,
158
+ // Analyst attributes frame/model/tool to this binding interval only (#636 D).
159
+ runId: input.admitted.runId
160
+ });
161
+ const coordinates = {
162
+ sessionDirectory: opened.sessionDirectory,
163
+ sessionFile: opened.sessionFile
164
+ };
165
+ const principal = input.principalAuthority.seal(coordinates);
166
+ input.principalAuthority.decode(principal);
167
+ input.admitted.principal = principal;
168
+ for (const page of ["admitted-request.json", "invocation.json"]) {
169
+ const path = join(input.admitted.runDirectory, page);
170
+ try {
171
+ const raw = JSON.parse(await readFile(path, "utf8"));
172
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw)) continue;
173
+ const next = {
174
+ ...raw,
175
+ sessionDirectory: coordinates.sessionDirectory,
176
+ sessionFile: coordinates.sessionFile
177
+ };
178
+ await writeFile(path, `${JSON.stringify(next, null, 2)}
179
+ `, "utf8");
180
+ } catch (error) {
181
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") {
182
+ continue;
183
+ }
184
+ throw error;
185
+ }
186
+ }
187
+ return { coordinates, resumed: opened.resumed };
188
+ }
189
+ const TICKET_SEAT_LAST_HOST_FILE = "last-host.json";
190
+ async function readTicketSeatMemoryLastHost(sessionDirectory) {
191
+ try {
192
+ const raw = JSON.parse(
193
+ await readFile(join(sessionDirectory, TICKET_SEAT_LAST_HOST_FILE), "utf8")
194
+ );
195
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw) || typeof raw.host !== "string" || raw.host.length === 0) {
196
+ throw new Error(
197
+ `ticket-seat memory last-host page is damaged under ${sessionDirectory}`
198
+ );
199
+ }
200
+ const host = raw.host;
201
+ const runDirectory = raw.runDirectory;
202
+ return {
203
+ host,
204
+ ...typeof runDirectory === "string" && runDirectory.length > 0 ? { runDirectory } : {}
205
+ };
206
+ } catch (error) {
207
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") {
208
+ return void 0;
209
+ }
210
+ throw error;
211
+ }
212
+ }
213
+ async function writeTicketSeatMemoryLastHost(sessionDirectory, host, runDirectory) {
214
+ if (host.trim() === "") {
215
+ throw new Error("ticket-seat memory last-host requires a non-empty host");
216
+ }
217
+ const body = {
218
+ host,
219
+ ...runDirectory !== void 0 && runDirectory.length > 0 ? { runDirectory } : {}
220
+ };
221
+ await writeFile(
222
+ join(sessionDirectory, TICKET_SEAT_LAST_HOST_FILE),
223
+ `${JSON.stringify(body, null, 2)}
224
+ `,
225
+ "utf8"
226
+ );
227
+ }
228
+ export {
229
+ TICKET_SEAT_MEMORY_KIND,
230
+ TICKET_SEAT_MEMORY_SEATS,
231
+ TICKET_SEAT_RUN_BINDING_ENTRY_TYPE,
232
+ isTicketSeatMemoryBound,
233
+ isTicketSeatMemorySeat,
234
+ isTicketSeatRunBindingRow,
235
+ openTicketSeatMemoryCoordinates,
236
+ readRunTicketNumber,
237
+ readTicketSeatMemoryLastHost,
238
+ rebindAdmittedToTicketSeatMemory,
239
+ resolveTicketSeatMemoryNestDirectories,
240
+ ticketSeatMemorySessionDirectory,
241
+ ticketSeatMemorySubject,
242
+ ticketSeatRunBindingRunId,
243
+ writeTicketSeatMemoryLastHost
244
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akagilnc/pi-workflow-roles",
3
- "version": "0.1.3412",
3
+ "version": "0.1.3439",
4
4
  "description": "Soul-bound workflow roles for Pi",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -21,6 +21,47 @@ const entries = [
21
21
  "activation-ledger-topology",
22
22
  "activation-reconciliation",
23
23
  "archivist-record-entry",
24
+ // Pure subject nest topology — cold discovery without SessionManager (#636).
25
+ "archivist-record-topology",
26
+ // Officer ticket-seat pure read + deferred open (#636 public-bin cold graph).
27
+ "ticket-seat-memory",
28
+ // ticket-seat-memory → session-opening-materials (#636 non-bundle graph closure).
29
+ "session-opening-materials",
30
+ // Value-import closure of published non-bundle roots (build-package-only loadable).
31
+ "auditor-dossier-tool",
32
+ "canonical-json",
33
+ "compliance-transport",
34
+ "countersign-contracts",
35
+ "doctor-contracts",
36
+ "engine-detour",
37
+ "engine-detour-tool",
38
+ "exact-utf8",
39
+ "git-object-id",
40
+ "gleaner-left-contracts",
41
+ "inspector-contracts",
42
+ "institutional-resolution",
43
+ "merger-contracts",
44
+ "notary-contracts",
45
+ "open-tool-schema",
46
+ "package-contracts/collector-output",
47
+ "package-contracts/fixer-output",
48
+ "package-contracts/fixer-packet",
49
+ "package-contracts/gatekeeper-output",
50
+ "package-contracts/judge-output",
51
+ "package-contracts/navigator-output",
52
+ "package-contracts/reviewer-output",
53
+ "package-contracts/terminating-infrastructure",
54
+ "package-contracts/worker-output",
55
+ "package-resources/engine-material",
56
+ "public-cli/config",
57
+ "public-cli/registry",
58
+ "receipt-delivery-policy",
59
+ "sha256",
60
+ "sitian-appender",
61
+ "sitian-contracts",
62
+ "sitian-facade",
63
+ "sitian-reader",
64
+ "stream-idle-guard",
24
65
  "typed-provider-http",
25
66
  "upstream-error-testimony",
26
67
  ];
@@ -21,3 +21,7 @@ finding 提**类别**,不提实例;实例只作证据。同类一次说全
21
21
  御批门槛:重大决策、设计、改变实际行为的机制与约束,须追到陛下原话或 ADR 绑定原话的 key。实现细节(字段名、内部形状、修法选择)依现行法源(accepted ADR、仓级宪法、全局硬规)成立即可,不因无逐字原话驳回。
22
22
 
23
23
  打回不设轮次上限;审官判断已不收敛(同类问题反复、修理只增不减)即可上呈。修理 diff 自身按同尺复核;修理引入的新残留是修理方的缺陷,不是新一轮的 finding。
24
+
25
+ ## 取证边界(owner 2026-09-05)
26
+
27
+ 取证只读。探针、临时文件、临时家只准落在本次工作区(worktree)与系统临时目录之内;**这两处之外的任何路径——尤其真家 `~/.ak-roles`、`~/.pi`、别的工作区——一律不得删除、覆写或移动**,「用完恢复原样」不构成先破坏再恢复的许可。违者即事故(2026-09-05 真家整删)。
@@ -16,7 +16,7 @@
16
16
 
17
17
  **四、擅加。** 票面有没有超出法源的机制、约束、验收、术语:每条承重主张追到原话或决策键为止,追不到即加戏。
18
18
 
19
- 各步取证不受限——读码、开卷、传召皆可,用完恢复原样。
19
+ 各步取证按《审法·取证边界》:读码、开卷、传召皆可;只读,探针只落 worktree 与临时目录,不得删改其外任何路径。
20
20
 
21
21
  ## 审读五问
22
22
 
@@ -6,5 +6,5 @@
6
6
  - 无锚定:不接收票面、判词与庭审史。案件=合并候选的全幅 diff 与仓库现状,看其本身对不对劲,此外不接收方向性指令。
7
7
  - 拾遗之责:bug 与边界、安全、命名与一致性、文档漂移、复杂度增长、测试质量、跨片接缝等。
8
8
  - 量尺:宿主宪法、仓级 ADR 与《复杂度与测试质量法》。
9
- - 取证工具不受限,一切自取;探针用后清理干净如实记录即可。
9
+ - 取证工具一切自取,按《审法·取证边界》:只读;探针只落 worktree 与临时目录,不得删改其外任何路径,如实记录。
10
10
  - 只上弹章,不修复、不裁决。
@@ -6,6 +6,6 @@
6
6
 
7
7
  主张必须附证据或法的具体条目。按尺逐条封驳。
8
8
 
9
- 取证不受限,但用完恢复原样。
9
+ 取证按《审法·取证边界》:只读;探针只落 worktree 与临时目录,不得删改其外任何路径。
10
10
 
11
11
  无法解决的上抛给陛下解决。
package/souls/notary.md CHANGED
@@ -6,4 +6,4 @@
6
6
 
7
7
  **二、核旨**:以所读起居录为据,核受审之物——**票面与判词**——有没有加戏:每一条**重大决策/设计/改变实际行为的**机制/约束条款逐条追到陛下原话或 ADR 绑定原话的 key 值为止(门槛见审刑院法典);票面本身是不是陛下要的同样逐条追,**不因票面已签押、判词已引用而免核**。引 ADR 之名而无 key 绑定、引票面而票面无原话,同为加戏。判词与票面对不对得上不归你。任一病成立,点名该条驳回;拿不准陛下本意的,上呈。
8
8
 
9
- 方法:按条封驳。取证不受限,用完恢复原样。无法解决的上抛陛下。
9
+ 方法:按条封驳。取证按《审法·取证边界》:只读;探针只落 worktree 与临时目录,不得删改其外任何路径。无法解决的上抛陛下。
package/souls/reviewer.md CHANGED
@@ -4,6 +4,6 @@
4
4
 
5
5
  - 风闻奏事,言不为狱:弹章(finding)不是权威、不负坐实义务。弹章须指明所劾之处(文件/条文指针),说错无罪。
6
6
  - 独立机关,直属陛下:不接收输入 prompt。案件=固定的被评审目标,目标或事实前提无法成立时如实拒绝;方法=canonical Skill;其余一切自取。
7
- - 取证工具不受限,一切自取。有权抽查≠有责核实:对存疑处可开卷、可下探针,用后清理干净如实记录即可。不整卷复读取证腿已读之物、不跑全量测试套件。
7
+ - 取证工具一切自取,按《审法·取证边界》:只读;探针只落 worktree 与临时目录,不得删改其外任何路径。有权抽查≠有责核实:对存疑处可开卷、可下探针,如实记录即可。不整卷复读取证腿已读之物、不跑全量测试套件。
8
8
  - 劾前逐项过改动清单。固定目标内每项改动都要标明由票面哪条驱动:标不出来的即为夹带(默认值、护栏、平行机制、仅测试用的生产钩子同论);票面有要求而清单中没有的即为缺口。二者同为 finding。
9
9
  - 重点劾三事:违宪(与既裁法源 ADR、铁律相抵)、测试必要性(最小必要成本法)、复杂度(可删不删、同形状第二份)。劾的范围=眼前一切:票面、实现、测试、输入 prompt 与给你的派单命令本身。唯一例外是陛下亲笔——援引此例外必须引陛下原话为证。