@akagilnc/pi-workflow-roles 0.1.5873 → 0.1.5880
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/dist/acp-host/production-host.js +54 -1
- package/dist/headless-host/production-host.js +54 -1
- package/dist/migrate-book-topology.js +8 -0
- package/dist/public-cli/cli.js +7 -0
- package/dist/public-cli/dialogue-command.js +37 -0
- package/dist/public-cli/main.js +200 -1
- package/dist/public-cli/option-definitions.js +8 -0
- package/dist/public-cli/registry.js +2 -1
- package/dist/ticket-provenance.js +1 -1
- package/package.json +1 -1
- package/resources/diarist-collect.md +1 -1
- package/souls/countersign.md +8 -9
- package/src/public-cli/cli.ts +7 -0
- package/src/public-cli/dialogue-command.ts +53 -0
- package/src/public-cli/option-definitions.ts +9 -0
- package/src/public-cli/registry.ts +1 -0
- package/src/ticket-provenance.ts +1 -1
|
@@ -5597,7 +5597,8 @@ var init_registry = __esm({
|
|
|
5597
5597
|
"help",
|
|
5598
5598
|
"resume",
|
|
5599
5599
|
"new",
|
|
5600
|
-
"setup"
|
|
5600
|
+
"setup",
|
|
5601
|
+
"dialogue"
|
|
5601
5602
|
];
|
|
5602
5603
|
PUBLIC_DETERMINISTIC_COMMANDS = ["analyst"];
|
|
5603
5604
|
}
|
|
@@ -6664,6 +6665,14 @@ var init_option_definitions = __esm({
|
|
|
6664
6665
|
"ak-role new notary --source-run 01abc\u2026@countersign",
|
|
6665
6666
|
"ak-role --host grok-build new inspector --attach ./change.patch"
|
|
6666
6667
|
]
|
|
6668
|
+
},
|
|
6669
|
+
dialogue: {
|
|
6670
|
+
command: "dialogue",
|
|
6671
|
+
summary: "Print what a diary range projects from a session volume, one JSON object per line: speaker lines {line, id, speaker: owner|runner, text} and unparsable lines {line, raw}. line and id are what a range endpoint names; a repeated id is shown on its first line only, where it resolves. Same authorized session roots as the projection.",
|
|
6672
|
+
usage: ["ak-role dialogue <session.jsonl>"],
|
|
6673
|
+
examples: [
|
|
6674
|
+
"ak-role dialogue ~/.claude/projects/-Users-me-repo/0b1c\u2026.jsonl > /tmp/dialogue.jsonl"
|
|
6675
|
+
]
|
|
6667
6676
|
}
|
|
6668
6677
|
};
|
|
6669
6678
|
PUBLIC_COMMAND_HELP = {
|
|
@@ -15798,6 +15807,44 @@ var init_instruction_seat_run = __esm({
|
|
|
15798
15807
|
}
|
|
15799
15808
|
});
|
|
15800
15809
|
|
|
15810
|
+
// src/public-cli/dialogue-command.ts
|
|
15811
|
+
async function readSessionDialogue(path, home) {
|
|
15812
|
+
assertDialogueSessionSourcePath(path, home);
|
|
15813
|
+
const sessionLines = await readLedgerSessionJsonlLines(path);
|
|
15814
|
+
const dialogue = adaptSessionDialogue(sessionLines.map((entry) => entry.row));
|
|
15815
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
15816
|
+
const out = [];
|
|
15817
|
+
sessionLines.forEach((entry, index) => {
|
|
15818
|
+
if (entry.row === void 0) {
|
|
15819
|
+
out.push({ line: entry.line, raw: entry.raw });
|
|
15820
|
+
return;
|
|
15821
|
+
}
|
|
15822
|
+
for (const event of dialogue[index] ?? []) {
|
|
15823
|
+
const firstId = event.id !== void 0 && !seenIds.has(event.id);
|
|
15824
|
+
if (event.id !== void 0) seenIds.add(event.id);
|
|
15825
|
+
out.push({
|
|
15826
|
+
line: entry.line,
|
|
15827
|
+
...firstId ? { id: event.id } : {},
|
|
15828
|
+
speaker: event.speaker,
|
|
15829
|
+
text: event.text
|
|
15830
|
+
});
|
|
15831
|
+
}
|
|
15832
|
+
});
|
|
15833
|
+
return out;
|
|
15834
|
+
}
|
|
15835
|
+
function renderSessionDialogue(lines) {
|
|
15836
|
+
return lines.map((line2) => `${JSON.stringify(line2)}
|
|
15837
|
+
`).join("");
|
|
15838
|
+
}
|
|
15839
|
+
var init_dialogue_command = __esm({
|
|
15840
|
+
"src/public-cli/dialogue-command.ts"() {
|
|
15841
|
+
"use strict";
|
|
15842
|
+
init_ledger_session_read();
|
|
15843
|
+
init_session_dialogue();
|
|
15844
|
+
init_ticket_provenance();
|
|
15845
|
+
}
|
|
15846
|
+
});
|
|
15847
|
+
|
|
15801
15848
|
// src/analyst-book-key.ts
|
|
15802
15849
|
import { statSync as statSync6 } from "node:fs";
|
|
15803
15850
|
import { isAbsolute as isAbsolute7 } from "node:path";
|
|
@@ -18933,6 +18980,11 @@ async function runAkRole(argv, env) {
|
|
|
18933
18980
|
return { exitCode: 0 };
|
|
18934
18981
|
}
|
|
18935
18982
|
const home = resolveHome(env);
|
|
18983
|
+
if (parsed.command === "dialogue") {
|
|
18984
|
+
if (parsed.args.length !== 1) throw new CliUsageError("usage: ak-role dialogue <session.jsonl>");
|
|
18985
|
+
io.stdout(renderSessionDialogue(await readSessionDialogue(parsed.args[0], home)));
|
|
18986
|
+
return { exitCode: 0 };
|
|
18987
|
+
}
|
|
18936
18988
|
if (parsed.command === "roles") {
|
|
18937
18989
|
if (parsed.args.length > 0) {
|
|
18938
18990
|
throw new CliUsageError("roles takes no arguments");
|
|
@@ -19123,6 +19175,7 @@ var init_cli = __esm({
|
|
|
19123
19175
|
init_invocation();
|
|
19124
19176
|
init_option_definitions();
|
|
19125
19177
|
init_auto_resume();
|
|
19178
|
+
init_dialogue_command();
|
|
19126
19179
|
init_instruction_seat_run();
|
|
19127
19180
|
init_countersign_run();
|
|
19128
19181
|
init_analyst_run();
|
|
@@ -4906,7 +4906,8 @@ var init_registry = __esm({
|
|
|
4906
4906
|
"help",
|
|
4907
4907
|
"resume",
|
|
4908
4908
|
"new",
|
|
4909
|
-
"setup"
|
|
4909
|
+
"setup",
|
|
4910
|
+
"dialogue"
|
|
4910
4911
|
];
|
|
4911
4912
|
PUBLIC_DETERMINISTIC_COMMANDS = ["analyst"];
|
|
4912
4913
|
}
|
|
@@ -7898,6 +7899,14 @@ var init_option_definitions = __esm({
|
|
|
7898
7899
|
"ak-role new notary --source-run 01abc\u2026@countersign",
|
|
7899
7900
|
"ak-role --host grok-build new inspector --attach ./change.patch"
|
|
7900
7901
|
]
|
|
7902
|
+
},
|
|
7903
|
+
dialogue: {
|
|
7904
|
+
command: "dialogue",
|
|
7905
|
+
summary: "Print what a diary range projects from a session volume, one JSON object per line: speaker lines {line, id, speaker: owner|runner, text} and unparsable lines {line, raw}. line and id are what a range endpoint names; a repeated id is shown on its first line only, where it resolves. Same authorized session roots as the projection.",
|
|
7906
|
+
usage: ["ak-role dialogue <session.jsonl>"],
|
|
7907
|
+
examples: [
|
|
7908
|
+
"ak-role dialogue ~/.claude/projects/-Users-me-repo/0b1c\u2026.jsonl > /tmp/dialogue.jsonl"
|
|
7909
|
+
]
|
|
7901
7910
|
}
|
|
7902
7911
|
};
|
|
7903
7912
|
PUBLIC_COMMAND_HELP = {
|
|
@@ -17145,6 +17154,44 @@ var init_instruction_seat_run = __esm({
|
|
|
17145
17154
|
}
|
|
17146
17155
|
});
|
|
17147
17156
|
|
|
17157
|
+
// src/public-cli/dialogue-command.ts
|
|
17158
|
+
async function readSessionDialogue(path, home) {
|
|
17159
|
+
assertDialogueSessionSourcePath(path, home);
|
|
17160
|
+
const sessionLines = await readLedgerSessionJsonlLines(path);
|
|
17161
|
+
const dialogue = adaptSessionDialogue(sessionLines.map((entry) => entry.row));
|
|
17162
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
17163
|
+
const out = [];
|
|
17164
|
+
sessionLines.forEach((entry, index) => {
|
|
17165
|
+
if (entry.row === void 0) {
|
|
17166
|
+
out.push({ line: entry.line, raw: entry.raw });
|
|
17167
|
+
return;
|
|
17168
|
+
}
|
|
17169
|
+
for (const event of dialogue[index] ?? []) {
|
|
17170
|
+
const firstId = event.id !== void 0 && !seenIds.has(event.id);
|
|
17171
|
+
if (event.id !== void 0) seenIds.add(event.id);
|
|
17172
|
+
out.push({
|
|
17173
|
+
line: entry.line,
|
|
17174
|
+
...firstId ? { id: event.id } : {},
|
|
17175
|
+
speaker: event.speaker,
|
|
17176
|
+
text: event.text
|
|
17177
|
+
});
|
|
17178
|
+
}
|
|
17179
|
+
});
|
|
17180
|
+
return out;
|
|
17181
|
+
}
|
|
17182
|
+
function renderSessionDialogue(lines) {
|
|
17183
|
+
return lines.map((line2) => `${JSON.stringify(line2)}
|
|
17184
|
+
`).join("");
|
|
17185
|
+
}
|
|
17186
|
+
var init_dialogue_command = __esm({
|
|
17187
|
+
"src/public-cli/dialogue-command.ts"() {
|
|
17188
|
+
"use strict";
|
|
17189
|
+
init_ledger_session_read();
|
|
17190
|
+
init_session_dialogue();
|
|
17191
|
+
init_ticket_provenance();
|
|
17192
|
+
}
|
|
17193
|
+
});
|
|
17194
|
+
|
|
17148
17195
|
// src/analyst-book-key.ts
|
|
17149
17196
|
import { statSync as statSync6 } from "node:fs";
|
|
17150
17197
|
import { isAbsolute as isAbsolute8 } from "node:path";
|
|
@@ -20280,6 +20327,11 @@ async function runAkRole(argv, env) {
|
|
|
20280
20327
|
return { exitCode: 0 };
|
|
20281
20328
|
}
|
|
20282
20329
|
const home = resolveHome(env);
|
|
20330
|
+
if (parsed.command === "dialogue") {
|
|
20331
|
+
if (parsed.args.length !== 1) throw new CliUsageError("usage: ak-role dialogue <session.jsonl>");
|
|
20332
|
+
io.stdout(renderSessionDialogue(await readSessionDialogue(parsed.args[0], home)));
|
|
20333
|
+
return { exitCode: 0 };
|
|
20334
|
+
}
|
|
20283
20335
|
if (parsed.command === "roles") {
|
|
20284
20336
|
if (parsed.args.length > 0) {
|
|
20285
20337
|
throw new CliUsageError("roles takes no arguments");
|
|
@@ -20470,6 +20522,7 @@ var init_cli = __esm({
|
|
|
20470
20522
|
init_invocation();
|
|
20471
20523
|
init_option_definitions();
|
|
20472
20524
|
init_auto_resume();
|
|
20525
|
+
init_dialogue_command();
|
|
20473
20526
|
init_instruction_seat_run();
|
|
20474
20527
|
init_countersign_run();
|
|
20475
20528
|
init_analyst_run();
|
|
@@ -11261,6 +11261,14 @@ var init_option_definitions = __esm({
|
|
|
11261
11261
|
"ak-role new notary --source-run 01abc\u2026@countersign",
|
|
11262
11262
|
"ak-role --host grok-build new inspector --attach ./change.patch"
|
|
11263
11263
|
]
|
|
11264
|
+
},
|
|
11265
|
+
dialogue: {
|
|
11266
|
+
command: "dialogue",
|
|
11267
|
+
summary: "Print what a diary range projects from a session volume, one JSON object per line: speaker lines {line, id, speaker: owner|runner, text} and unparsable lines {line, raw}. line and id are what a range endpoint names; a repeated id is shown on its first line only, where it resolves. Same authorized session roots as the projection.",
|
|
11268
|
+
usage: ["ak-role dialogue <session.jsonl>"],
|
|
11269
|
+
examples: [
|
|
11270
|
+
"ak-role dialogue ~/.claude/projects/-Users-me-repo/0b1c\u2026.jsonl > /tmp/dialogue.jsonl"
|
|
11271
|
+
]
|
|
11264
11272
|
}
|
|
11265
11273
|
};
|
|
11266
11274
|
PUBLIC_COMMAND_HELP = {
|
package/dist/public-cli/cli.js
CHANGED
|
@@ -19,6 +19,7 @@ import { formatHostSelectionFailure, HostSelectionError, } from "./role-turn-hos
|
|
|
19
19
|
import { admittedSourceRunPath, parseAnalystArgv, parsePublicSeatArgv, } from "./invocation.js";
|
|
20
20
|
import { createTypedOptionConsumer, optionsForOwner, projectCommandHelp, projectOwnerOptions, PUBLIC_NAVIGATOR_HELP_NOTE, PUBLIC_ROLE_OPTION_OWNERS, renderHumanOwnerOptionLines, } from "./option-definitions.js";
|
|
21
21
|
import { TurnDispatchedFailure } from "./auto-resume.js";
|
|
22
|
+
import { readSessionDialogue, renderSessionDialogue } from "./dialogue-command.js";
|
|
22
23
|
import { continueParentAfterChild, presentAuditedOriginalOfUnsettledOfficer, runPublicInstructionSeat, runPublicInstructionSeatResume, } from "./instruction-seat-run.js";
|
|
23
24
|
import { latestPayloadEscalated } from "./countersign-run.js";
|
|
24
25
|
import { runPublicAnalyst } from "./analyst-run.js";
|
|
@@ -780,6 +781,12 @@ export async function runAkRole(argv, env) {
|
|
|
780
781
|
// Profile home only after home-free paths return. Failures keep real identity
|
|
781
782
|
// and settle through the outer catch — no $HOME fallback (#604).
|
|
782
783
|
const home = resolveHome(env);
|
|
784
|
+
if (parsed.command === "dialogue") {
|
|
785
|
+
if (parsed.args.length !== 1)
|
|
786
|
+
throw new CliUsageError("usage: ak-role dialogue <session.jsonl>");
|
|
787
|
+
io.stdout(renderSessionDialogue(await readSessionDialogue(parsed.args[0], home)));
|
|
788
|
+
return { exitCode: 0 };
|
|
789
|
+
}
|
|
783
790
|
if (parsed.command === "roles") {
|
|
784
791
|
if (parsed.args.length > 0) {
|
|
785
792
|
throw new CliUsageError("roles takes no arguments");
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ak-role dialogue <session>`: the speaker lines a diary range would project,
|
|
3
|
+
* one JSON object per line, so the diarist searches the dialogue instead of
|
|
4
|
+
* re-deriving the session format (owner 2026-10-21). Same read and adapter as
|
|
5
|
+
* the ticket-provenance projection — no second speaker rule.
|
|
6
|
+
*/
|
|
7
|
+
import { readLedgerSessionJsonlLines } from "../ledger-session-read.js";
|
|
8
|
+
import { adaptSessionDialogue } from "../session-dialogue.js";
|
|
9
|
+
import { assertDialogueSessionSourcePath } from "../ticket-provenance.js";
|
|
10
|
+
export async function readSessionDialogue(path, home) {
|
|
11
|
+
assertDialogueSessionSourcePath(path, home);
|
|
12
|
+
const sessionLines = await readLedgerSessionJsonlLines(path);
|
|
13
|
+
const dialogue = adaptSessionDialogue(sessionLines.map((entry) => entry.row));
|
|
14
|
+
const seenIds = new Set();
|
|
15
|
+
const out = [];
|
|
16
|
+
sessionLines.forEach((entry, index) => {
|
|
17
|
+
if (entry.row === undefined) {
|
|
18
|
+
out.push({ line: entry.line, raw: entry.raw });
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
for (const event of dialogue[index] ?? []) {
|
|
22
|
+
const firstId = event.id !== undefined && !seenIds.has(event.id);
|
|
23
|
+
if (event.id !== undefined)
|
|
24
|
+
seenIds.add(event.id);
|
|
25
|
+
out.push({
|
|
26
|
+
line: entry.line,
|
|
27
|
+
...(firstId ? { id: event.id } : {}),
|
|
28
|
+
speaker: event.speaker,
|
|
29
|
+
text: event.text,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
return out;
|
|
34
|
+
}
|
|
35
|
+
export function renderSessionDialogue(lines) {
|
|
36
|
+
return lines.map((line) => `${JSON.stringify(line)}\n`).join("");
|
|
37
|
+
}
|
package/dist/public-cli/main.js
CHANGED
|
@@ -10381,7 +10381,8 @@ var init_registry = __esm({
|
|
|
10381
10381
|
"help",
|
|
10382
10382
|
"resume",
|
|
10383
10383
|
"new",
|
|
10384
|
-
"setup"
|
|
10384
|
+
"setup",
|
|
10385
|
+
"dialogue"
|
|
10385
10386
|
];
|
|
10386
10387
|
PUBLIC_DETERMINISTIC_COMMANDS = ["analyst"];
|
|
10387
10388
|
}
|
|
@@ -13461,16 +13462,151 @@ var init_merger_git_state = __esm({
|
|
|
13461
13462
|
});
|
|
13462
13463
|
|
|
13463
13464
|
// src/session-dialogue.ts
|
|
13465
|
+
function nativeEventId(row) {
|
|
13466
|
+
for (const key of ["uuid", "id"]) {
|
|
13467
|
+
const value = row[key];
|
|
13468
|
+
if (typeof value === "string" && value !== "") return value;
|
|
13469
|
+
}
|
|
13470
|
+
for (const nestKey of ["message", "payload"]) {
|
|
13471
|
+
const nested = row[nestKey];
|
|
13472
|
+
if (!isRecord(nested)) continue;
|
|
13473
|
+
for (const key of ["uuid", "id"]) {
|
|
13474
|
+
const value = nested[key];
|
|
13475
|
+
if (typeof value === "string" && value !== "") return value;
|
|
13476
|
+
}
|
|
13477
|
+
}
|
|
13478
|
+
return void 0;
|
|
13479
|
+
}
|
|
13480
|
+
function textParts(content) {
|
|
13481
|
+
if (typeof content === "string") return content === "" ? [] : [content];
|
|
13482
|
+
if (!Array.isArray(content)) return [];
|
|
13483
|
+
const out = [];
|
|
13484
|
+
for (const part of content) {
|
|
13485
|
+
if (!isRecord(part) || !SPEAKER_TEXT_PART_TYPES.has(String(part.type))) continue;
|
|
13486
|
+
const text = part.text;
|
|
13487
|
+
if (typeof text === "string" && text !== "") out.push(text);
|
|
13488
|
+
}
|
|
13489
|
+
return out;
|
|
13490
|
+
}
|
|
13491
|
+
function responseItemMessage(row) {
|
|
13492
|
+
if (row.type !== "response_item" || !isRecord(row.payload)) return void 0;
|
|
13493
|
+
if (row.payload.type !== "message") return void 0;
|
|
13494
|
+
return row.payload;
|
|
13495
|
+
}
|
|
13496
|
+
function messageBody(row) {
|
|
13497
|
+
if (isRecord(row.message)) return row.message;
|
|
13498
|
+
return responseItemMessage(row);
|
|
13499
|
+
}
|
|
13500
|
+
function speakerOf(message) {
|
|
13501
|
+
if (message.role === "assistant") return "runner";
|
|
13502
|
+
if (message.role === "user") return "owner";
|
|
13503
|
+
return void 0;
|
|
13504
|
+
}
|
|
13505
|
+
function codexContentItemKinds(message) {
|
|
13506
|
+
const pass = message.internal_chat_message_metadata_passthrough;
|
|
13507
|
+
if (!isRecord(pass) || !Array.isArray(pass.content_item_kinds)) return void 0;
|
|
13508
|
+
const kinds = [];
|
|
13509
|
+
for (const kind of pass.content_item_kinds) {
|
|
13510
|
+
if (typeof kind === "string" && kind !== "") kinds.push(kind);
|
|
13511
|
+
}
|
|
13512
|
+
return kinds;
|
|
13513
|
+
}
|
|
13514
|
+
function isCodexOwnerResponseItemUser(message) {
|
|
13515
|
+
if (message.role !== "user") return false;
|
|
13516
|
+
const kinds = codexContentItemKinds(message);
|
|
13517
|
+
if (kinds === void 0) return false;
|
|
13518
|
+
return kinds.some((kind) => kind.startsWith("user."));
|
|
13519
|
+
}
|
|
13520
|
+
function fromQueueEvent(row) {
|
|
13521
|
+
if (row.type !== "queue-operation" || row.operation !== "enqueue") return [];
|
|
13522
|
+
const content = row.content;
|
|
13523
|
+
if (typeof content !== "string" || content === "") return [];
|
|
13524
|
+
const id = nativeEventId(row);
|
|
13525
|
+
return [{ speaker: "owner", text: content, ...id === void 0 ? {} : { id } }];
|
|
13526
|
+
}
|
|
13527
|
+
function hasFixedOpenTagPrefix(content, tag) {
|
|
13528
|
+
if (!content.startsWith(tag)) return false;
|
|
13529
|
+
const next = content.charAt(tag.length);
|
|
13530
|
+
return next === "" || next === ">" || next === " " || next === " " || next === "\n" || next === "\r";
|
|
13531
|
+
}
|
|
13532
|
+
function isFixedNonOwnerEnqueueShape(content) {
|
|
13533
|
+
return hasFixedOpenTagPrefix(content, TASK_NOTIFICATION_OPEN_TAG);
|
|
13534
|
+
}
|
|
13535
|
+
function materializationOriginKind(row) {
|
|
13536
|
+
if (!isRecord(row.origin)) return void 0;
|
|
13537
|
+
const kind = row.origin.kind;
|
|
13538
|
+
return typeof kind === "string" && kind !== "" ? kind : void 0;
|
|
13539
|
+
}
|
|
13540
|
+
function isNonOwnerOriginKind(kind) {
|
|
13541
|
+
if (kind === void 0) return false;
|
|
13542
|
+
return kind !== "human";
|
|
13543
|
+
}
|
|
13544
|
+
function fromMessageEvent(row) {
|
|
13545
|
+
const message = messageBody(row);
|
|
13546
|
+
if (message === void 0) return [];
|
|
13547
|
+
if (message.role === "toolResult") return [];
|
|
13548
|
+
const speaker = speakerOf(message);
|
|
13549
|
+
if (speaker === void 0) return [];
|
|
13550
|
+
if (row.type === "response_item" && speaker === "owner") {
|
|
13551
|
+
if (!isCodexOwnerResponseItemUser(message)) return [];
|
|
13552
|
+
}
|
|
13553
|
+
const parts = textParts(message.content);
|
|
13554
|
+
if (parts.length === 0) return [];
|
|
13555
|
+
const text = parts.join("");
|
|
13556
|
+
if (text === "") return [];
|
|
13557
|
+
const id = nativeEventId(row);
|
|
13558
|
+
return [{ speaker, text, ...id === void 0 ? {} : { id } }];
|
|
13559
|
+
}
|
|
13560
|
+
function adaptSessionDialogue(rows) {
|
|
13561
|
+
return rows.map((row) => {
|
|
13562
|
+
if (row === void 0) return [];
|
|
13563
|
+
const originKind = materializationOriginKind(row);
|
|
13564
|
+
if (isNonOwnerOriginKind(originKind)) return [];
|
|
13565
|
+
if (row.type === "queue-operation" && row.operation === "enqueue" && typeof row.content === "string" && isFixedNonOwnerEnqueueShape(row.content)) {
|
|
13566
|
+
return [];
|
|
13567
|
+
}
|
|
13568
|
+
const queued = fromQueueEvent(row);
|
|
13569
|
+
if (queued.length > 0) return queued;
|
|
13570
|
+
return fromMessageEvent(row);
|
|
13571
|
+
});
|
|
13572
|
+
}
|
|
13573
|
+
var SPEAKER_TEXT_PART_TYPES, TASK_NOTIFICATION_OPEN_TAG;
|
|
13464
13574
|
var init_session_dialogue = __esm({
|
|
13465
13575
|
"src/session-dialogue.ts"() {
|
|
13466
13576
|
"use strict";
|
|
13467
13577
|
init_unknown_value();
|
|
13578
|
+
SPEAKER_TEXT_PART_TYPES = /* @__PURE__ */ new Set(["text", "input_text", "output_text"]);
|
|
13579
|
+
TASK_NOTIFICATION_OPEN_TAG = "<task-notification";
|
|
13468
13580
|
}
|
|
13469
13581
|
});
|
|
13470
13582
|
|
|
13471
13583
|
// src/ticket-provenance.ts
|
|
13472
13584
|
import { readFile as readFile7 } from "node:fs/promises";
|
|
13473
13585
|
import { join as join12, resolve as resolve6 } from "node:path";
|
|
13586
|
+
function dialogueSessionSourceRoots(home) {
|
|
13587
|
+
const machineHome = typeof home === "string" && home.trim() !== "" ? home : packageMachineHome();
|
|
13588
|
+
return [
|
|
13589
|
+
join12(machineHome, ".claude", "projects"),
|
|
13590
|
+
join12(machineHome, ".codex", "sessions"),
|
|
13591
|
+
join12(machineHome, ".pi", "agent", "sessions")
|
|
13592
|
+
];
|
|
13593
|
+
}
|
|
13594
|
+
function isLedgerRoleSessionFile(absolute, home) {
|
|
13595
|
+
const machineHome = typeof home === "string" && home.trim() !== "" ? home : packageMachineHome();
|
|
13596
|
+
const ledgerHome = resolveActivationLedgerHome(machineHome);
|
|
13597
|
+
if (!physicallyContainedIn(ledgerHome, absolute)) return false;
|
|
13598
|
+
return sessionFileOf(runDirectoryOfSessionFile(absolute)) === absolute;
|
|
13599
|
+
}
|
|
13600
|
+
function assertDialogueSessionSourcePath(path, home) {
|
|
13601
|
+
const absolute = resolve6(path);
|
|
13602
|
+
for (const root of dialogueSessionSourceRoots(home)) {
|
|
13603
|
+
if (physicallyContainedIn(root, absolute)) return;
|
|
13604
|
+
}
|
|
13605
|
+
if (isLedgerRoleSessionFile(absolute, home)) return;
|
|
13606
|
+
throw new TicketProvenanceInputError(
|
|
13607
|
+
`session unreadable: ${path} (outside authorized source roots)`
|
|
13608
|
+
);
|
|
13609
|
+
}
|
|
13474
13610
|
function ticketProvenanceSubject(ticketNumber) {
|
|
13475
13611
|
if (!isSafePositiveTicketNumber(ticketNumber)) {
|
|
13476
13612
|
throw new Error(
|
|
@@ -13507,6 +13643,7 @@ async function rehomeUnboundTicketProvenance(runDirectory, ticketNumber, cwd, ho
|
|
|
13507
13643
|
}).join("");
|
|
13508
13644
|
if (block !== "") appendSitianRecordBlock(ticketInput, block);
|
|
13509
13645
|
}
|
|
13646
|
+
var TicketProvenanceInputError;
|
|
13510
13647
|
var init_ticket_provenance = __esm({
|
|
13511
13648
|
"src/ticket-provenance.ts"() {
|
|
13512
13649
|
"use strict";
|
|
@@ -13520,6 +13657,16 @@ var init_ticket_provenance = __esm({
|
|
|
13520
13657
|
init_sitian_reader();
|
|
13521
13658
|
init_ticket_provenance_contracts();
|
|
13522
13659
|
init_unknown_value();
|
|
13660
|
+
TicketProvenanceInputError = class extends Error {
|
|
13661
|
+
code = "ticket-provenance-input";
|
|
13662
|
+
constructor(message, options) {
|
|
13663
|
+
super(
|
|
13664
|
+
message,
|
|
13665
|
+
options?.cause === void 0 ? void 0 : { cause: options.cause }
|
|
13666
|
+
);
|
|
13667
|
+
this.name = "TicketProvenanceInputError";
|
|
13668
|
+
}
|
|
13669
|
+
};
|
|
13523
13670
|
}
|
|
13524
13671
|
});
|
|
13525
13672
|
|
|
@@ -14730,6 +14877,14 @@ var init_option_definitions = __esm({
|
|
|
14730
14877
|
"ak-role new notary --source-run 01abc\u2026@countersign",
|
|
14731
14878
|
"ak-role --host grok-build new inspector --attach ./change.patch"
|
|
14732
14879
|
]
|
|
14880
|
+
},
|
|
14881
|
+
dialogue: {
|
|
14882
|
+
command: "dialogue",
|
|
14883
|
+
summary: "Print what a diary range projects from a session volume, one JSON object per line: speaker lines {line, id, speaker: owner|runner, text} and unparsable lines {line, raw}. line and id are what a range endpoint names; a repeated id is shown on its first line only, where it resolves. Same authorized session roots as the projection.",
|
|
14884
|
+
usage: ["ak-role dialogue <session.jsonl>"],
|
|
14885
|
+
examples: [
|
|
14886
|
+
"ak-role dialogue ~/.claude/projects/-Users-me-repo/0b1c\u2026.jsonl > /tmp/dialogue.jsonl"
|
|
14887
|
+
]
|
|
14733
14888
|
}
|
|
14734
14889
|
};
|
|
14735
14890
|
PUBLIC_COMMAND_HELP = {
|
|
@@ -23900,6 +24055,44 @@ var init_post_admission = __esm({
|
|
|
23900
24055
|
}
|
|
23901
24056
|
});
|
|
23902
24057
|
|
|
24058
|
+
// src/public-cli/dialogue-command.ts
|
|
24059
|
+
async function readSessionDialogue(path, home) {
|
|
24060
|
+
assertDialogueSessionSourcePath(path, home);
|
|
24061
|
+
const sessionLines = await readLedgerSessionJsonlLines(path);
|
|
24062
|
+
const dialogue = adaptSessionDialogue(sessionLines.map((entry) => entry.row));
|
|
24063
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
24064
|
+
const out = [];
|
|
24065
|
+
sessionLines.forEach((entry, index) => {
|
|
24066
|
+
if (entry.row === void 0) {
|
|
24067
|
+
out.push({ line: entry.line, raw: entry.raw });
|
|
24068
|
+
return;
|
|
24069
|
+
}
|
|
24070
|
+
for (const event of dialogue[index] ?? []) {
|
|
24071
|
+
const firstId = event.id !== void 0 && !seenIds.has(event.id);
|
|
24072
|
+
if (event.id !== void 0) seenIds.add(event.id);
|
|
24073
|
+
out.push({
|
|
24074
|
+
line: entry.line,
|
|
24075
|
+
...firstId ? { id: event.id } : {},
|
|
24076
|
+
speaker: event.speaker,
|
|
24077
|
+
text: event.text
|
|
24078
|
+
});
|
|
24079
|
+
}
|
|
24080
|
+
});
|
|
24081
|
+
return out;
|
|
24082
|
+
}
|
|
24083
|
+
function renderSessionDialogue(lines) {
|
|
24084
|
+
return lines.map((line2) => `${JSON.stringify(line2)}
|
|
24085
|
+
`).join("");
|
|
24086
|
+
}
|
|
24087
|
+
var init_dialogue_command = __esm({
|
|
24088
|
+
"src/public-cli/dialogue-command.ts"() {
|
|
24089
|
+
"use strict";
|
|
24090
|
+
init_ledger_session_read();
|
|
24091
|
+
init_session_dialogue();
|
|
24092
|
+
init_ticket_provenance();
|
|
24093
|
+
}
|
|
24094
|
+
});
|
|
24095
|
+
|
|
23903
24096
|
// node_modules/.pnpm/typebox@1.3.8/node_modules/typebox/build/schema/types/_refine.mjs
|
|
23904
24097
|
function IsRefine2(value) {
|
|
23905
24098
|
return guard_exports.HasPropertyKey(value, "~refine") && guard_exports.IsArray(value["~refine"]) && guard_exports.Every(value["~refine"], 0, (value2) => guard_exports.IsObject(value2) && guard_exports.HasPropertyKey(value2, "check") && guard_exports.HasPropertyKey(value2, "error") && guard_exports.IsFunction(value2.check) && guard_exports.IsFunction(value2.error));
|
|
@@ -32946,6 +33139,11 @@ async function runAkRole(argv2, env) {
|
|
|
32946
33139
|
return { exitCode: 0 };
|
|
32947
33140
|
}
|
|
32948
33141
|
const home = resolveHome(env);
|
|
33142
|
+
if (parsed.command === "dialogue") {
|
|
33143
|
+
if (parsed.args.length !== 1) throw new CliUsageError("usage: ak-role dialogue <session.jsonl>");
|
|
33144
|
+
io.stdout(renderSessionDialogue(await readSessionDialogue(parsed.args[0], home)));
|
|
33145
|
+
return { exitCode: 0 };
|
|
33146
|
+
}
|
|
32949
33147
|
if (parsed.command === "roles") {
|
|
32950
33148
|
if (parsed.args.length > 0) {
|
|
32951
33149
|
throw new CliUsageError("roles takes no arguments");
|
|
@@ -33136,6 +33334,7 @@ var init_cli = __esm({
|
|
|
33136
33334
|
init_invocation();
|
|
33137
33335
|
init_option_definitions();
|
|
33138
33336
|
init_auto_resume();
|
|
33337
|
+
init_dialogue_command();
|
|
33139
33338
|
init_instruction_seat_run();
|
|
33140
33339
|
init_countersign_run();
|
|
33141
33340
|
init_analyst_run();
|
|
@@ -1141,6 +1141,14 @@ const SUPPORT_COMMAND_HELP = {
|
|
|
1141
1141
|
"ak-role --host grok-build new inspector --attach ./change.patch",
|
|
1142
1142
|
],
|
|
1143
1143
|
},
|
|
1144
|
+
dialogue: {
|
|
1145
|
+
command: "dialogue",
|
|
1146
|
+
summary: "Print what a diary range projects from a session volume, one JSON object per line: speaker lines {line, id, speaker: owner|runner, text} and unparsable lines {line, raw}. line and id are what a range endpoint names; a repeated id is shown on its first line only, where it resolves. Same authorized session roots as the projection.",
|
|
1147
|
+
usage: ["ak-role dialogue <session.jsonl>"],
|
|
1148
|
+
examples: [
|
|
1149
|
+
"ak-role dialogue ~/.claude/projects/-Users-me-repo/0b1c….jsonl > /tmp/dialogue.jsonl",
|
|
1150
|
+
],
|
|
1151
|
+
},
|
|
1144
1152
|
};
|
|
1145
1153
|
/**
|
|
1146
1154
|
* Sole public help-copy owner keyed by command/topic id.
|
|
@@ -54,7 +54,7 @@ function isLedgerRoleSessionFile(absolute, home) {
|
|
|
54
54
|
return sessionFileOf(runDirectoryOfSessionFile(absolute)) === absolute;
|
|
55
55
|
}
|
|
56
56
|
/** Real I/O seam gate: only host session stores or sitian role-run session.jsonl. */
|
|
57
|
-
function assertDialogueSessionSourcePath(path, home) {
|
|
57
|
+
export function assertDialogueSessionSourcePath(path, home) {
|
|
58
58
|
const absolute = resolve(path);
|
|
59
59
|
for (const root of dialogueSessionSourceRoots(home)) {
|
|
60
60
|
if (physicallyContainedIn(root, absolute))
|
package/package.json
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
你是 LLM,自己读以判断边界:
|
|
12
12
|
|
|
13
|
-
- 本仓相关会话卷(路径里的 `_` 在目录名里常写作 `-`;主 clone 与 worktree
|
|
13
|
+
- 本仓相关会话卷(路径里的 `_` 在目录名里常写作 `-`;主 clone 与 worktree 可能共用或分列,自行辨认)。读卷用 `ak-role dialogue <会话卷>`:每行一句说话(`line`、`id`、`speaker`、`text`),正是区间投影会收进录的那些行;`line` 与 `id` 就是交卷区间端点的写法,给了 `id` 的行才能用 id 指名
|
|
14
14
|
- 本票票面与评论:用 `gh` 或等价方式读 GitHub issue
|
|
15
15
|
|
|
16
16
|
指令明确列出多张要办的票时,逐票读卷判断各自相关边界;共同对话可以同时归入相关各票,无关他票对话不得混入。单票/多票交卷字段及不可用边界的处置见交卷工具的声明。
|
package/souls/countersign.md
CHANGED
|
@@ -15,14 +15,13 @@
|
|
|
15
15
|
3 第二法源合法性检查:判断第二法源 以及 输入的 prompt等 对比第一法源是否有超出,不足,曲解。如有,除非有陛下原话批准,否则直接封驳 要求改正或陛下批准。
|
|
16
16
|
4 派单文 是否要求了范围,是否给了你清单,是否让你不全量重审,以及是否有任何违反你Soul规定的。如果有,直接封驳,拿不准的直接上呈。
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
|
|
23
|
-
此步不成立即封驳,不必再走后三步。
|
|
18
|
+
**二、设计合法。** 陛下原话是第一法源的一部分:读它是为了知道哪些事已经拍定,条款逐条对原话的核销归符宝郎,本席不做。本步审的是设计答案的来路:
|
|
19
|
+
- 中书省问了而由宰相作答、没等陛下拍的每一题(中书省回执里有答案、未上呈的题),其答案须能从适用法(第一、第二法源)或已定事项(父票、前票里陛下拍定的,和中书省问答里陛下拍定并写进票面的;宰相自己的答案不算)推出来;判词里写出这条推导。推不出的,该题宰相答不了,改标陛下题,上呈,附原题原选项;不得以「合理」「承接设计」「现状如此」顶替推导。
|
|
20
|
+
- 中书省在题里否决某个做法的(「旧模型,不选」之类),否决须引法或已定事项;引不出的,该做法并列呈陛下。
|
|
21
|
+
- 对于修复票,判断根因是什么、证据在哪;对于设计票,判断设计能否从法推出,以及因果链本身站不站得住。
|
|
22
|
+
此步不成立即封驳或上呈,不必再走后三步。
|
|
24
23
|
|
|
25
|
-
**三、相抵**
|
|
24
|
+
**三、相抵** 票面、相关票与在飞分支,与法源和已定事项有无抵触。在飞分支里已做出来的东西与已定事项相抵的,是相抵,不是现状。票面自相抵同为相抵。
|
|
26
25
|
|
|
27
26
|
**四、缺失** 法源要求的,票面有没有漏:适用法只查两类:票面与某条 ADR 决定相抵的,和把某条决定留给别的票承接的,票面须写明该条与「由 #x 承接」;这两类之外的 ADR 没引不算缺失,不得为此封驳;验收面须覆盖票面每条主张;票面里每一条行为都须答得出《送庭前三问》第一问:起、停、续、终、接各归谁没写的行为,即缺失;前置产物、决定、答复须在;承重主张的源头不存在、不支持、已过时,同为缺失。缺失列表在能力范围内一次扫完,尽量避免因缺失导致多轮往返。
|
|
28
27
|
|
|
@@ -34,8 +33,8 @@
|
|
|
34
33
|
|
|
35
34
|
五步是审读,五问是裁决口径,对应关系固定,不重做:
|
|
36
35
|
1. 票面是否符合既定制度——由「相抵」答;
|
|
37
|
-
2.
|
|
38
|
-
3.
|
|
36
|
+
2. 设计是否合法——由「设计合法」答:宰相可答之题的答案可从法或已定事项推出,否决有出处;
|
|
37
|
+
3. 文书是否与法一致——由「缺失」「擅加」答:无夹带、无缺口;条款与陛下原话的对应归符宝郎;
|
|
39
38
|
4. 是否存在必须退回重议的问题;
|
|
40
39
|
5. 是否已具备正式发布与执行资格。
|
|
41
40
|
|
package/src/public-cli/cli.ts
CHANGED
|
@@ -79,6 +79,7 @@ import {
|
|
|
79
79
|
type TypedOptionConsumer,
|
|
80
80
|
} from "./option-definitions.ts";
|
|
81
81
|
import { TurnDispatchedFailure } from "./auto-resume.ts";
|
|
82
|
+
import { readSessionDialogue, renderSessionDialogue } from "./dialogue-command.ts";
|
|
82
83
|
import {
|
|
83
84
|
continueParentAfterChild,
|
|
84
85
|
presentAuditedOriginalOfUnsettledOfficer,
|
|
@@ -1157,6 +1158,12 @@ export async function runAkRole(
|
|
|
1157
1158
|
// and settle through the outer catch — no $HOME fallback (#604).
|
|
1158
1159
|
const home = resolveHome(env);
|
|
1159
1160
|
|
|
1161
|
+
if (parsed.command === "dialogue") {
|
|
1162
|
+
if (parsed.args.length !== 1) throw new CliUsageError("usage: ak-role dialogue <session.jsonl>");
|
|
1163
|
+
io.stdout(renderSessionDialogue(await readSessionDialogue(parsed.args[0]!, home)));
|
|
1164
|
+
return { exitCode: 0 };
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1160
1167
|
if (parsed.command === "roles") {
|
|
1161
1168
|
if (parsed.args.length > 0) {
|
|
1162
1169
|
throw new CliUsageError("roles takes no arguments");
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ak-role dialogue <session>`: the speaker lines a diary range would project,
|
|
3
|
+
* one JSON object per line, so the diarist searches the dialogue instead of
|
|
4
|
+
* re-deriving the session format (owner 2026-10-21). Same read and adapter as
|
|
5
|
+
* the ticket-provenance projection — no second speaker rule.
|
|
6
|
+
*/
|
|
7
|
+
import { readLedgerSessionJsonlLines } from "../ledger-session-read.ts";
|
|
8
|
+
import { adaptSessionDialogue, type DialogueSpeaker } from "../session-dialogue.ts";
|
|
9
|
+
import { assertDialogueSessionSourcePath } from "../ticket-provenance.ts";
|
|
10
|
+
|
|
11
|
+
export type SessionDialogueLine =
|
|
12
|
+
| {
|
|
13
|
+
/** 1-based file line, the same `line` a diary range endpoint names. */
|
|
14
|
+
readonly line: number;
|
|
15
|
+
/** Native id a range endpoint can name; only on its first line, since an id resolves there. */
|
|
16
|
+
readonly id?: string;
|
|
17
|
+
readonly speaker: DialogueSpeaker;
|
|
18
|
+
readonly text: string;
|
|
19
|
+
}
|
|
20
|
+
| {
|
|
21
|
+
/** Unparsable source line; a range covering it keeps these bytes in the record. */
|
|
22
|
+
readonly line: number;
|
|
23
|
+
readonly raw: string;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export async function readSessionDialogue(path: string, home?: string): Promise<SessionDialogueLine[]> {
|
|
27
|
+
assertDialogueSessionSourcePath(path, home);
|
|
28
|
+
const sessionLines = await readLedgerSessionJsonlLines(path);
|
|
29
|
+
const dialogue = adaptSessionDialogue(sessionLines.map((entry) => entry.row));
|
|
30
|
+
const seenIds = new Set<string>();
|
|
31
|
+
const out: SessionDialogueLine[] = [];
|
|
32
|
+
sessionLines.forEach((entry, index) => {
|
|
33
|
+
if (entry.row === undefined) {
|
|
34
|
+
out.push({ line: entry.line, raw: entry.raw });
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
for (const event of dialogue[index] ?? []) {
|
|
38
|
+
const firstId = event.id !== undefined && !seenIds.has(event.id);
|
|
39
|
+
if (event.id !== undefined) seenIds.add(event.id);
|
|
40
|
+
out.push({
|
|
41
|
+
line: entry.line,
|
|
42
|
+
...(firstId ? { id: event.id } : {}),
|
|
43
|
+
speaker: event.speaker,
|
|
44
|
+
text: event.text,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
return out;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function renderSessionDialogue(lines: readonly SessionDialogueLine[]): string {
|
|
52
|
+
return lines.map((line) => `${JSON.stringify(line)}\n`).join("");
|
|
53
|
+
}
|
|
@@ -1362,6 +1362,15 @@ const SUPPORT_COMMAND_HELP = {
|
|
|
1362
1362
|
"ak-role --host grok-build new inspector --attach ./change.patch",
|
|
1363
1363
|
],
|
|
1364
1364
|
},
|
|
1365
|
+
dialogue: {
|
|
1366
|
+
command: "dialogue",
|
|
1367
|
+
summary:
|
|
1368
|
+
"Print what a diary range projects from a session volume, one JSON object per line: speaker lines {line, id, speaker: owner|runner, text} and unparsable lines {line, raw}. line and id are what a range endpoint names; a repeated id is shown on its first line only, where it resolves. Same authorized session roots as the projection.",
|
|
1369
|
+
usage: ["ak-role dialogue <session.jsonl>"],
|
|
1370
|
+
examples: [
|
|
1371
|
+
"ak-role dialogue ~/.claude/projects/-Users-me-repo/0b1c….jsonl > /tmp/dialogue.jsonl",
|
|
1372
|
+
],
|
|
1373
|
+
},
|
|
1365
1374
|
} as const satisfies Record<string, PublicCommandHelpFacts>;
|
|
1366
1375
|
|
|
1367
1376
|
/**
|
package/src/ticket-provenance.ts
CHANGED
|
@@ -83,7 +83,7 @@ function isLedgerRoleSessionFile(absolute: string, home?: string): boolean {
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
/** Real I/O seam gate: only host session stores or sitian role-run session.jsonl. */
|
|
86
|
-
function assertDialogueSessionSourcePath(path: string, home?: string): void {
|
|
86
|
+
export function assertDialogueSessionSourcePath(path: string, home?: string): void {
|
|
87
87
|
const absolute = resolve(path);
|
|
88
88
|
for (const root of dialogueSessionSourceRoots(home)) {
|
|
89
89
|
if (physicallyContainedIn(root, absolute)) return;
|