@akagilnc/pi-workflow-roles 0.1.5873 → 0.1.5877
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/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/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;
|