@akagilnc/pi-workflow-roles 0.1.5762 → 0.1.5797
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 +685 -285
- package/dist/external-host-turn-loop.js +3 -0
- package/dist/headless-host/production-host.js +658 -258
- package/dist/migrate-book-topology.js +70 -29
- package/dist/navigator-attendance.js +1 -1
- package/dist/packaged-role-registry.js +3 -2
- package/dist/pi/role-turn-host.js +6 -1
- package/dist/public-cli/instruction-seat-run.js +152 -60
- package/dist/public-cli/invocation.js +98 -46
- package/dist/public-cli/main.js +482 -222
- package/dist/public-cli/option-definitions.js +4 -4
- package/dist/public-cli/post-admission.js +19 -28
- package/dist/public-cli/run-lifecycle.js +10 -21
- package/dist/public-cli/turn-request.js +3 -0
- package/dist/public-role-summons.js +11 -8
- package/dist/report-ticket-tool.js +3 -3
- package/dist/role-run-placement.js +14 -2
- package/dist/role-run-relocation.js +2 -2
- package/dist/run-dossier.js +5 -4
- package/dist/run-terminal-artifacts.js +0 -7
- package/dist/session-identity.js +3 -2
- package/dist/sitian-appender.js +12 -3
- package/dist/submission-ledger.js +24 -0
- package/dist/ticket-progress.js +306 -0
- package/dist/user-dialogue-stdin.js +23 -17
- package/package.json +1 -1
- package/src/external-host-turn-loop.ts +7 -1
- package/src/host-contracts.ts +1 -1
- package/src/navigator-attendance.ts +2 -1
- package/src/packaged-role-registry.ts +3 -2
- package/src/pi/adapter.ts +57 -45
- package/src/pi/role-turn-host.ts +6 -1
- package/src/prepared-role-turn.ts +6 -0
- package/src/public-cli/instruction-seat-run.ts +166 -68
- package/src/public-cli/invocation.ts +120 -46
- package/src/public-cli/option-definitions.ts +5 -4
- package/src/public-cli/post-admission.ts +19 -30
- package/src/public-cli/run-lifecycle.ts +10 -27
- package/src/public-cli/turn-request.ts +3 -0
- package/src/public-role-summons.ts +27 -16
- package/src/report-ticket-tool.ts +7 -3
- package/src/role-envelope.ts +5 -0
- package/src/role-run-placement.ts +19 -2
- package/src/role-run-relocation.ts +2 -2
- package/src/role-runtime.ts +19 -2
- package/src/run-dossier.ts +5 -3
- package/src/run-terminal-artifacts.ts +0 -8
- package/src/session-identity.ts +3 -2
- package/src/sitian-appender.ts +14 -3
- package/src/submission-ledger.ts +27 -0
- package/src/ticket-progress.ts +383 -0
- package/src/user-dialogue-stdin.ts +21 -14
|
@@ -509,8 +509,8 @@ const NOTARY_OPTIONS = [
|
|
|
509
509
|
repeatable: false,
|
|
510
510
|
form: "option",
|
|
511
511
|
description: {
|
|
512
|
-
en: "Required source run locator (runId@role under the book home, or path to that run directory).
|
|
513
|
-
zh: "必填源 run 定位符(簿内 runId@role,或该 run
|
|
512
|
+
en: "Required source run locator (runId@role under the book home, or path to that run directory). Binds the audited identity; review dialogue is the fixed Notary dispatch (verdict stays in the ledger). Missing-ticket and unreadable-status reasks keep their existing diagnostic text.",
|
|
513
|
+
zh: "必填源 run 定位符(簿内 runId@role,或该 run 目录路径)。绑定受审身份;审稿对话为符宝郎固定派单文(判词留在卷宗自行读取)。缺票号与读不出 status 的重交仍递既有诊断原文。",
|
|
514
514
|
},
|
|
515
515
|
},
|
|
516
516
|
];
|
|
@@ -1040,7 +1040,7 @@ const ROLE_COMMAND_HELP = {
|
|
|
1040
1040
|
},
|
|
1041
1041
|
notary: {
|
|
1042
1042
|
command: "notary",
|
|
1043
|
-
summary: "Direct Notary summons; duties: souls/notary.md.
|
|
1043
|
+
summary: "Direct Notary summons; duties: souls/notary.md. Review uses fixed dispatch — binds --source-run identity; does not accept caller review prompt; verdict stays in the ledger. Missing-ticket (#1171) and unreadable-status reasks deliver their existing diagnostic text on the same seat, not the review sentence.",
|
|
1044
1044
|
usage: ["ak-role notary --source-run <runId@role|path> [options]"],
|
|
1045
1045
|
examples: [
|
|
1046
1046
|
"ak-role notary --source-run 01a034f1-75bf-71a6-bcf5-d1299145b1a5@judge",
|
|
@@ -1101,7 +1101,7 @@ const SUPPORT_COMMAND_HELP = {
|
|
|
1101
1101
|
},
|
|
1102
1102
|
resume: {
|
|
1103
1103
|
command: "resume",
|
|
1104
|
-
summary: "Resume a role run under the live seat table (model/host/engine); session principal must still exist. Every callable seat
|
|
1104
|
+
summary: "Resume a role run under the live seat table (model/host/engine); session principal must still exist. Every callable seat accepts the optional caller message and passes it through unchanged as the continuation prompt. Notary new/direct review calls use only --source-run plus the fixed review dispatch (no caller review prompt); public manual resume still passes the caller message. Global --model/--thinking/--host/--engine must be placed before <runId> (either before `resume` or between `resume` and <runId>); the one argv after <runId> is the opaque message, not a flag position (#471).",
|
|
1105
1105
|
usage: ["ak-role resume <runId> [message]"],
|
|
1106
1106
|
examples: [
|
|
1107
1107
|
"ak-role resume 01abc…",
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { randomUUID } from "node:crypto";
|
|
9
9
|
import { writeFile } from "node:fs/promises";
|
|
10
|
-
import {
|
|
10
|
+
import { findRunDirectoryById, resolveLiveRunDirectoryPath, readRoleRunState, } from "./run-lifecycle.js";
|
|
11
11
|
import { CliUsageError } from "./cli-errors.js";
|
|
12
12
|
import { projectPublicTurnAxes } from "./turn-request.js";
|
|
13
13
|
import { appendCallerFileFlagPaths, bindAdmittedTicketNumber, relocateAdmittedRunToTicket, } from "./invocation.js";
|
|
@@ -394,31 +394,26 @@ function settlementScopeForTurn(request) {
|
|
|
394
394
|
};
|
|
395
395
|
}
|
|
396
396
|
/**
|
|
397
|
-
* #1132: one 没交卷催交 turn, dispatched through the SAME settlement path
|
|
398
|
-
* first turn.
|
|
397
|
+
* #1132 / #1208: one 没交卷催交 turn, dispatched through the SAME settlement path
|
|
398
|
+
* as the first turn.
|
|
399
399
|
*
|
|
400
|
-
*
|
|
401
|
-
*
|
|
402
|
-
*
|
|
403
|
-
*
|
|
404
|
-
*
|
|
405
|
-
* `settleCompletedHostTurn` the first turn uses (ADR 0080): the runner/host
|
|
406
|
-
* failure re-read, the shouldPresent gate, the fresh-seal check, open-court
|
|
407
|
-
* cleanup, cancel re-reads, run-state persist, and the stderr mirror.
|
|
400
|
+
* A delivery turn is an ordinary host turn on this same run/session: this builds
|
|
401
|
+
* the host-neutral resume request (the adapter's stored native session id,
|
|
402
|
+
* ADR 0082). #1208: resend this turn's actual prompt — never substitute
|
|
403
|
+
* delivery-state / run-stats JSON for dialogue. Counts, rejections, and
|
|
404
|
+
* no_receipt facts stay on receiptDelivery / lifecycle settlement.
|
|
408
405
|
*
|
|
409
406
|
* The caller owns the live delivery policy; the request projects its next send.
|
|
410
407
|
*/
|
|
411
408
|
/** Bare in-call催交 resume: hostSessionId absent; adapter is the sole load authority. */
|
|
412
409
|
function buildReceiptDeliveryRequest(input) {
|
|
413
410
|
const { request, receiptDelivery } = input;
|
|
411
|
+
// #1199: progress instruction is this turn's prompt (envelope books continuation.prompt).
|
|
414
412
|
return {
|
|
415
413
|
...request,
|
|
416
414
|
continuation: {
|
|
417
415
|
kind: "resume",
|
|
418
|
-
prompt:
|
|
419
|
-
...receiptDelivery.deliveryState(),
|
|
420
|
-
deliveryTurns: receiptDelivery.issuedDeliveryRequests() + 1,
|
|
421
|
-
}),
|
|
416
|
+
prompt: request.continuation.prompt,
|
|
422
417
|
},
|
|
423
418
|
deliveryRequestLimit: receiptDelivery.limit,
|
|
424
419
|
};
|
|
@@ -1076,6 +1071,7 @@ export function resumeTurnRequestProjectionOptions(admitted, request, env, summo
|
|
|
1076
1071
|
const officerDialogue = isStationChildOfficerDialogue(admitted.role, env);
|
|
1077
1072
|
const fileFlags = summonsPrepared?.attachments ?? [];
|
|
1078
1073
|
let prompt;
|
|
1074
|
+
// #1199: progress instruction = this prompt (actual seat input, file flags included).
|
|
1079
1075
|
if (request.message !== undefined) {
|
|
1080
1076
|
if (summonsPrepared !== undefined) {
|
|
1081
1077
|
// #755: same-ticket review / open-court — caller words + caller file flags.
|
|
@@ -1099,8 +1095,8 @@ export function resumeTurnRequestProjectionOptions(admitted, request, env, summo
|
|
|
1099
1095
|
: appendCallerFileFlagPaths(body, fileFlags);
|
|
1100
1096
|
}
|
|
1101
1097
|
else if (request.summons !== undefined) {
|
|
1102
|
-
//
|
|
1103
|
-
//
|
|
1098
|
+
// Same-ticket summons without prepared dialogue. Notary review fills via
|
|
1099
|
+
// resolveReviewSeatDialogueBody (#1208); other seats carry parent/caller words.
|
|
1104
1100
|
prompt = "";
|
|
1105
1101
|
}
|
|
1106
1102
|
else {
|
|
@@ -1339,21 +1335,15 @@ export async function runPostAdmissionSeatResume(input) {
|
|
|
1339
1335
|
buildInitialPayload: () => ({ resumeTurn: false }),
|
|
1340
1336
|
buildResumePayload: () => ({ resumeTurn: true }),
|
|
1341
1337
|
toRequest: async (payload) => {
|
|
1342
|
-
// #840 r8
|
|
1343
|
-
//
|
|
1344
|
-
//
|
|
1345
|
-
// host-needed resume trigger — never engine handbook material,
|
|
1346
|
-
// which would replace a 审核循环 same-ticket continuation with a bare outsourcing
|
|
1347
|
-
// 「重新读」 envelope (#755 contract, resumeTurnRequestProjectionOptions
|
|
1348
|
-
// above). RESUME_TRANSPORT_ENVELOPE is the same package-owned,
|
|
1349
|
-
// non-semantic trigger that projection already uses for a
|
|
1350
|
-
// same-ticket summons carrying no instruction/attachments.
|
|
1338
|
+
// #840 r8 / #1208: call-local retry keeps this court's frozen summons /
|
|
1339
|
+
// 交卷 body / attachments and resends the same turn prompt — never a
|
|
1340
|
+
// filler phrase or engine handbook substitute.
|
|
1351
1341
|
if (payload.resumeTurn && firstTurn !== undefined) {
|
|
1352
1342
|
return {
|
|
1353
1343
|
...firstTurn,
|
|
1354
1344
|
continuation: {
|
|
1355
1345
|
kind: "resume",
|
|
1356
|
-
prompt:
|
|
1346
|
+
prompt: firstTurn.continuation.prompt,
|
|
1357
1347
|
},
|
|
1358
1348
|
};
|
|
1359
1349
|
}
|
|
@@ -1460,6 +1450,7 @@ async function writeResumeDiagnostic(runDirectory, runId, failure, role) {
|
|
|
1460
1450
|
* entering; manual resume never re-admits.
|
|
1461
1451
|
*/
|
|
1462
1452
|
export async function runPostAdmissionOneShot(input) {
|
|
1453
|
+
// #1208: auto-resume resends this turn's actual prompt, never a filler phrase.
|
|
1463
1454
|
return await runPostAdmissionResumable({
|
|
1464
1455
|
admitted: input.admitted,
|
|
1465
1456
|
env: input.env,
|
|
@@ -1469,7 +1460,7 @@ export async function runPostAdmissionOneShot(input) {
|
|
|
1469
1460
|
...input.request,
|
|
1470
1461
|
continuation: {
|
|
1471
1462
|
kind: "resume",
|
|
1472
|
-
prompt:
|
|
1463
|
+
prompt: input.request.continuation.prompt,
|
|
1473
1464
|
},
|
|
1474
1465
|
}),
|
|
1475
1466
|
adapters: input.adapters,
|
|
@@ -13,7 +13,7 @@ import { findRoleRunDirectory, listBookRunDirectories, parseRunLeaf, sessionFile
|
|
|
13
13
|
import { isSafePositiveTicketNumber } from "../run-ticket-number.js";
|
|
14
14
|
import { CliUsageError } from "./cli-errors.js";
|
|
15
15
|
import { parseCollectorRepository } from "../collector-config.js";
|
|
16
|
-
import { retainedRunPathsMatch, rewriteAdmittedRoleRunPage,
|
|
16
|
+
import { retainedRunPathsMatch, rewriteAdmittedRoleRunPage, rewritePrincipalSessionPaths, } from "../role-run-relocation.js";
|
|
17
17
|
import { packagedResumeSourcePath, packagedRoleMetadata, } from "../packaged-role-registry.js";
|
|
18
18
|
import { admittedReviewerBaseFault, admittedSourceRunPath, recordEffectiveInvocationModel, requireAuthorityRef, isReviewerLens, normalizeAdmittedAttachment, } from "./invocation.js";
|
|
19
19
|
import { readPageSync, writeSectionSync } from "../run-dossier.js";
|
|
@@ -23,23 +23,6 @@ import { isRecord, errorText, isEnoent } from "../unknown-value.js";
|
|
|
23
23
|
* source: runWithAutoResumeLoop receives the effective value once per call.
|
|
24
24
|
*/
|
|
25
25
|
export const AUTO_RESUME_LIMIT = 2;
|
|
26
|
-
/**
|
|
27
|
-
* Package-owned non-empty Chinese neutral resume transport (#959 / ADR 0073).
|
|
28
|
-
* Used by:
|
|
29
|
-
* - auto-resume (all seats via buildAutoResumeContinuationPrompt) — required so
|
|
30
|
-
* hosts that reject empty stdin (codex) still receive a prompt.
|
|
31
|
-
* Public manual resume forwards only the caller's bytes (#987).
|
|
32
|
-
*/
|
|
33
|
-
export const RESUME_TRANSPORT_ENVELOPE = "继续。";
|
|
34
|
-
/**
|
|
35
|
-
* Auto-resume continuation only (#959 / ADR 0080).
|
|
36
|
-
* Always non-empty Chinese neutral envelope. Engine / outsourcing material
|
|
37
|
-
* rides startup readingMaterial (#1167), never this continuation.
|
|
38
|
-
* Never call this from manual `ak-role resume`.
|
|
39
|
-
*/
|
|
40
|
-
export function buildAutoResumeContinuationPrompt() {
|
|
41
|
-
return RESUME_TRANSPORT_ENVELOPE;
|
|
42
|
-
}
|
|
43
26
|
const WRITER_LOCK_FILE = "writer.lock";
|
|
44
27
|
export async function writeRoleRunState(runDirectory, record) {
|
|
45
28
|
const payload = { ...record, runDirectory };
|
|
@@ -153,10 +136,16 @@ async function readRoleRunStateDisk(runDirectory) {
|
|
|
153
136
|
: runDirectory;
|
|
154
137
|
const runDir = runDirectory;
|
|
155
138
|
// Principal wire stays uninterpreted — authority owns legacy sessionFile fallback.
|
|
139
|
+
// #1199: leg-local session/ moves with the run-prefix rewrite.
|
|
140
|
+
const principalCoords = {
|
|
141
|
+
sessionDirectory: record.sessionDirectory,
|
|
142
|
+
...(typeof record.sessionFile === "string" ? { sessionFile: record.sessionFile } : {}),
|
|
143
|
+
};
|
|
144
|
+
rewritePrincipalSessionPaths(principalCoords, storedRunDirectory, runDirectory);
|
|
156
145
|
const principalWire = {
|
|
157
|
-
sessionDirectory:
|
|
158
|
-
...(typeof
|
|
159
|
-
? { sessionFile:
|
|
146
|
+
sessionDirectory: principalCoords.sessionDirectory,
|
|
147
|
+
...(typeof principalCoords.sessionFile === "string"
|
|
148
|
+
? { sessionFile: principalCoords.sessionFile }
|
|
160
149
|
: {}),
|
|
161
150
|
};
|
|
162
151
|
const phase = record.phase === "plan" || record.phase === "apply"
|
|
@@ -51,6 +51,9 @@ export function projectRoleTurnRequest(admitted, roleDetails, options) {
|
|
|
51
51
|
...(options.deliveryRequestLimit === undefined
|
|
52
52
|
? {}
|
|
53
53
|
: { deliveryRequestLimit: options.deliveryRequestLimit }),
|
|
54
|
+
...(options.host === undefined || options.host.trim() === ""
|
|
55
|
+
? {}
|
|
56
|
+
: { host: options.host.trim() }),
|
|
54
57
|
};
|
|
55
58
|
}
|
|
56
59
|
/**
|
|
@@ -351,13 +351,9 @@ async function summonGateOfficer(options) {
|
|
|
351
351
|
home = homeFromRunDirectory(options.sourceRunDirectory);
|
|
352
352
|
}
|
|
353
353
|
let gateReviewInstruction;
|
|
354
|
-
if (options.reask === void 0 && options.submission !== void 0) {
|
|
355
|
-
const {
|
|
356
|
-
|
|
357
|
-
if (!blindTicketCourt) {
|
|
358
|
-
const { readableGateItem } = await import("./readable-gate-item.js");
|
|
359
|
-
gateReviewInstruction = readableGateItem(options.submission);
|
|
360
|
-
}
|
|
354
|
+
if (options.reask === void 0 && options.submission !== void 0 && options.officer !== "notary") {
|
|
355
|
+
const { readableGateItem } = await import("./readable-gate-item.js");
|
|
356
|
+
gateReviewInstruction = readableGateItem(options.submission);
|
|
361
357
|
}
|
|
362
358
|
const { runIdFromRunDirectory } = await import("./run-terminal-artifacts.js");
|
|
363
359
|
const parentRunId = runIdFromRunDirectory(options.sourceRunDirectory);
|
|
@@ -408,7 +404,14 @@ async function summonGateOfficer(options) {
|
|
|
408
404
|
const parentTicket = await readBoardTicketNumber(options.sourceRunDirectory);
|
|
409
405
|
const submittedTicket = isRecord(options.submission) ? options.submission.ticketNumber : void 0;
|
|
410
406
|
const courtTicket = isSafePositiveTicketNumber(submittedTicket) ? submittedTicket : parentTicket;
|
|
411
|
-
const
|
|
407
|
+
const { resolveReviewSeatDialogueBody } = await import("./public-cli/instruction-seat-run.js");
|
|
408
|
+
const instruction = await resolveReviewSeatDialogueBody({
|
|
409
|
+
role: options.officer,
|
|
410
|
+
...options.reask === void 0 ? {} : { reviewReask: options.reask },
|
|
411
|
+
...gateReviewInstruction === void 0 ? {} : { gateReviewInstruction },
|
|
412
|
+
projectRoot: options.cwd,
|
|
413
|
+
home
|
|
414
|
+
}) ?? "";
|
|
412
415
|
return summonPublicRole({
|
|
413
416
|
role: options.officer,
|
|
414
417
|
argv: ["--project", options.cwd, "--", instruction],
|
|
@@ -102,6 +102,7 @@ export async function reportTicketFromHostContext(context, rawTicketNumber, auth
|
|
|
102
102
|
if (process.env.AK_ROLE_RUN_DIR === runDirectory) {
|
|
103
103
|
process.env.AK_ROLE_RUN_DIR = nextDirectory;
|
|
104
104
|
}
|
|
105
|
+
// Leg-local session/: rewrite the open handle under the renamed run prefix.
|
|
105
106
|
const projectedSessionFile = typeof priorSessionFile === "string" && priorSessionFile.trim() !== ""
|
|
106
107
|
? rewriteRunDirectoryPathValue(priorSessionFile, runDirectory, nextDirectory)
|
|
107
108
|
: sessionFileOf(nextDirectory);
|
|
@@ -109,9 +110,8 @@ export async function reportTicketFromHostContext(context, rawTicketNumber, auth
|
|
|
109
110
|
context.sessionManager.setSessionFile?.(projectedSessionFile);
|
|
110
111
|
}
|
|
111
112
|
};
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
: await relocateAdmittedRunToTicket(admitted, authority, { relocate: applyLiveHandles });
|
|
113
|
+
// Always enter relocate: unbound→rename+publish; already-on-ticket→publish leftover staging.
|
|
114
|
+
const relocation = await relocateAdmittedRunToTicket(admitted, authority, alreadyPlaced ? undefined : { relocate: applyLiveHandles });
|
|
115
115
|
const nextDirectory = relocation?.newRunDirectory ?? admitted.runDirectory;
|
|
116
116
|
if (relocation === undefined)
|
|
117
117
|
applyLiveHandles(nextDirectory);
|
|
@@ -14,10 +14,20 @@ function parseRunLeaf(name) {
|
|
|
14
14
|
if (at <= 0 || at === name.length - 1) return void 0;
|
|
15
15
|
return { runId: name.slice(0, at), role: name.slice(at + 1) };
|
|
16
16
|
}
|
|
17
|
+
const ROLE_RUN_SESSION_FILENAME = "session.jsonl";
|
|
18
|
+
function subjectDirectoryOfRun(runDirectory) {
|
|
19
|
+
const runsParent = dirname(runDirectory);
|
|
20
|
+
if (basename(runsParent) !== "runs") return void 0;
|
|
21
|
+
const subjectDirectory = dirname(runsParent);
|
|
22
|
+
const subjectName = basename(subjectDirectory);
|
|
23
|
+
if (subjectName === "unbound" || /^[1-9]\d*$/.test(subjectName)) {
|
|
24
|
+
return subjectDirectory;
|
|
25
|
+
}
|
|
26
|
+
return void 0;
|
|
27
|
+
}
|
|
17
28
|
function sessionDirectoryOf(runDirectory) {
|
|
18
29
|
return join(runDirectory, "session");
|
|
19
30
|
}
|
|
20
|
-
const ROLE_RUN_SESSION_FILENAME = "session.jsonl";
|
|
21
31
|
function sessionFileIn(sessionDirectory) {
|
|
22
32
|
return join(sessionDirectory, ROLE_RUN_SESSION_FILENAME);
|
|
23
33
|
}
|
|
@@ -107,6 +117,7 @@ function ensureRoleRunDirectory(ledgerHome, directory) {
|
|
|
107
117
|
return ensureRealDirectoryTree(ledgerHome, directory);
|
|
108
118
|
}
|
|
109
119
|
function ensureRoleRunPlacement(ledgerHome, placement) {
|
|
120
|
+
ensureRoleRunDirectory(ledgerHome, placement.runDirectory);
|
|
110
121
|
ensureRoleRunDirectory(ledgerHome, placement.sessionDirectory);
|
|
111
122
|
}
|
|
112
123
|
export {
|
|
@@ -124,5 +135,6 @@ export {
|
|
|
124
135
|
runDirectoryOfSessionFile,
|
|
125
136
|
sessionDirectoryOf,
|
|
126
137
|
sessionFileIn,
|
|
127
|
-
sessionFileOf
|
|
138
|
+
sessionFileOf,
|
|
139
|
+
subjectDirectoryOfRun
|
|
128
140
|
};
|
|
@@ -12,7 +12,7 @@ import { dirname, join } from "node:path";
|
|
|
12
12
|
import { activationBookDirectory, physicalPathIdentity } from "./activation-ledger-topology.js";
|
|
13
13
|
import { AUDITOR_PARENT_ATTEMPT_BINDING_ENTRY_TYPE } from "./compliance-transport.js";
|
|
14
14
|
import { readRoleRunIdentity } from "./public-cli/run-lifecycle.js";
|
|
15
|
-
import { roleRunPlacement } from "./role-run-placement.js";
|
|
15
|
+
import { roleRunPlacement, sessionDirectoryOf } from "./role-run-placement.js";
|
|
16
16
|
import { INVOCATION_PAGE_PATH_FIELDS, PRINCIPAL_SESSION_PATH_FIELDS, RUN_STATE_PAGE_PATH_FIELDS, projectTurnRequestLiveRunDirectory, rewriteAdmittedRoleRunPage, rewritePrincipalSessionPaths, rewriteRunDirectoryPathFields, rewriteRunDirectoryPathFieldsAgainstRewrites, rewriteRunDirectoryPathValue, rewriteRunDirectoryPathValueAgainstRewrites, rewriteSummonsMaterials, } from "./role-run-path-rewrite.js";
|
|
17
17
|
import { readPageSync, updateSectionSync } from "./run-dossier.js";
|
|
18
18
|
import { isEnoent, isRecord } from "./unknown-value.js";
|
|
@@ -215,7 +215,7 @@ async function rewriteSessionTranscriptBindings(path, rewrites) {
|
|
|
215
215
|
* session transcript typed parent bindings. Never walks caller file paths.
|
|
216
216
|
*/
|
|
217
217
|
async function rewriteNestedMachinePathPages(pagesDirectory, rewrites) {
|
|
218
|
-
const sessionRoot =
|
|
218
|
+
const sessionRoot = sessionDirectoryOf(pagesDirectory);
|
|
219
219
|
async function walk(directory) {
|
|
220
220
|
let entries;
|
|
221
221
|
try {
|
package/dist/run-dossier.js
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
import { randomUUID } from "node:crypto";
|
|
20
20
|
import { readFileSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
21
21
|
import { basename, join } from "node:path";
|
|
22
|
-
import { sessionFileOf } from "./role-run-placement.js";
|
|
22
|
+
import { sessionDirectoryOf, sessionFileOf } from "./role-run-placement.js";
|
|
23
23
|
import { projectRenderedPagePaths } from "./role-run-path-rewrite.js";
|
|
24
24
|
import { RUN_CURRENT_FILE, RUN_HISTORY_FILE, RUN_LOG_FILE, RUN_STATE_FILE, OFFICER_POINTER_RECORD_KIND } from "./run-dossier-files.js";
|
|
25
25
|
import { appendSitianRecord } from "./sitian-appender.js";
|
|
@@ -181,9 +181,10 @@ function render(runDirectory, history, state, log, unreadable) {
|
|
|
181
181
|
}
|
|
182
182
|
}
|
|
183
183
|
// The copy row keeps the absolute path it was written to; a run that was filed under its ticket
|
|
184
|
-
// since lives elsewhere. The original is projected from where this run
|
|
185
|
-
if (typeof original === "string")
|
|
186
|
-
original = join(runDirectory,
|
|
184
|
+
// since lives elsewhere. The original is projected from where this run's session lands now.
|
|
185
|
+
if (typeof original === "string") {
|
|
186
|
+
original = join(sessionDirectoryOf(runDirectory), basename(original));
|
|
187
|
+
}
|
|
187
188
|
whole.host = { sessions, ...(original === undefined ? {} : { original }) };
|
|
188
189
|
whole.submission = latest === undefined ? {} : { latest };
|
|
189
190
|
if (Object.keys(unreadable).length > 0)
|
|
@@ -99,10 +99,3 @@ export function runIdFromRunDirectory(runDirectory) {
|
|
|
99
99
|
export function roleFromRunDirectory(runDirectory) {
|
|
100
100
|
return parseRunLeaf(basename(runDirectory))?.role;
|
|
101
101
|
}
|
|
102
|
-
/**
|
|
103
|
-
* #1195 ticket-court blind review: notary source is a countersign run.
|
|
104
|
-
* Identity still binds; countersign body is not preloaded into dialogue.
|
|
105
|
-
*/
|
|
106
|
-
export function isTicketCourtCountersignSource(runDirectory) {
|
|
107
|
-
return roleFromRunDirectory(runDirectory) === "countersign";
|
|
108
|
-
}
|
package/dist/session-identity.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { join } from "node:path";
|
|
2
2
|
import { DEFAULT_ROLE_TURN_HOST, lookupHeadlessHostDescription, lookupHostDescription, } from "./host-descriptions.js";
|
|
3
|
+
import { runDirectoryFromSessionDirectory } from "./role-run-placement.js";
|
|
3
4
|
import { renderCurrentSync, RUN_STATE_FILE } from "./run-dossier.js";
|
|
4
5
|
import { readSitianRecords, reportRunRecord } from "./sitian-facade.js";
|
|
5
6
|
import { errorText, isRecord } from "./unknown-value.js";
|
|
@@ -14,7 +15,7 @@ export const HOST_SESSION_ID_RECORD_KIND = "host-session-id";
|
|
|
14
15
|
* host/session failure (facts stay in state.jsonl; settlement still renders).
|
|
15
16
|
*/
|
|
16
17
|
export function createSessionIdentityAuthority(authority, hostName) {
|
|
17
|
-
const runDirectoryOf = (principal) =>
|
|
18
|
+
const runDirectoryOf = (principal) => runDirectoryFromSessionDirectory(authority.decode(principal).sessionDirectory);
|
|
18
19
|
return {
|
|
19
20
|
principalAuthority: authority,
|
|
20
21
|
resolveSessionFile(principal) {
|
package/dist/sitian-appender.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { appendFileSync } from "node:fs";
|
|
3
3
|
import { basename, dirname, join } from "node:path";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
parseRunLeaf,
|
|
6
|
+
sessionDirectoryOf
|
|
7
|
+
} from "./role-run-placement.js";
|
|
5
8
|
import { RUN_HISTORY_FILE, RUN_HISTORY_KINDS, RUN_LOG_FILE, RUN_STATE_FILE, RUN_STATE_KINDS } from "./run-dossier-files.js";
|
|
6
9
|
import { ticketNumberFromSitianSubject } from "./run-ticket-number.js";
|
|
7
10
|
import { resolveBookKeyFromGit } from "./activation-ledger-git.js";
|
|
@@ -33,6 +36,12 @@ function appendSitianRecordBlock(input, block) {
|
|
|
33
36
|
function resolveSitianVolumeCategory(kind) {
|
|
34
37
|
return kind;
|
|
35
38
|
}
|
|
39
|
+
function runDirectoryOwningSessionParent(sessionParentDir) {
|
|
40
|
+
if (basename(sessionParentDir) !== "session") return void 0;
|
|
41
|
+
const runDirectory = dirname(sessionParentDir);
|
|
42
|
+
if (parseRunLeaf(basename(runDirectory)) === void 0) return void 0;
|
|
43
|
+
return runDirectory;
|
|
44
|
+
}
|
|
36
45
|
const SITIAN_RECORDS_LEAF = "records.jsonl";
|
|
37
46
|
function sitianVolumeDirectory(sessionDirectory, category) {
|
|
38
47
|
return join(sessionDirectory, category);
|
|
@@ -68,8 +77,8 @@ function resolveSitianRecordPathInLedger(input, ledgerHome) {
|
|
|
68
77
|
throw new Error("Sitian record ownership requires a parent session inside the ledger home");
|
|
69
78
|
}
|
|
70
79
|
const sessionParentDir = dirname(input.sessionParent);
|
|
71
|
-
const runDirectory =
|
|
72
|
-
if (
|
|
80
|
+
const runDirectory = runDirectoryOwningSessionParent(sessionParentDir);
|
|
81
|
+
if (runDirectory !== void 0) {
|
|
73
82
|
sessionDir = runDirectory;
|
|
74
83
|
recordFile = join(runDirectory, RUN_HISTORY_KINDS.has(input.kind) ? RUN_HISTORY_FILE : RUN_STATE_KINDS.has(input.kind) ? RUN_STATE_FILE : RUN_LOG_FILE);
|
|
75
84
|
} else {
|
|
@@ -9,6 +9,7 @@ import { failOnInfrastructureFailureDeclaration, infrastructureFailureDiagnostic
|
|
|
9
9
|
import { reportTicketFromHostContext } from "./report-ticket-tool.js";
|
|
10
10
|
import { REVIEW_SUBMISSION_OUTPUT_TOOL_NAME } from "./review-submission.js";
|
|
11
11
|
import { readDeclaredTicketNumber } from "./run-ticket-number.js";
|
|
12
|
+
import { captureWorktreeHead, landTicketProgressForSealedSubmission, } from "./ticket-progress.js";
|
|
12
13
|
import { isRecord, errorText } from "./unknown-value.js";
|
|
13
14
|
/**
|
|
14
15
|
* Admitted run identity for the ledger subject.
|
|
@@ -294,6 +295,8 @@ export async function sealAcceptedSubmission(options) {
|
|
|
294
295
|
const attemptId = attemptIdentity(options.context, runId);
|
|
295
296
|
const sessionParent = sessionParentFromHostContext(options.context);
|
|
296
297
|
const home = homeFromHostContext(options.context, options.home);
|
|
298
|
+
// #1199: same seal-time HEAD + progress landing as the terminating-tool wrap.
|
|
299
|
+
const sealHead = captureWorktreeHead(options.context.cwd);
|
|
297
300
|
sitianReport({
|
|
298
301
|
level: "event",
|
|
299
302
|
kind: "sealed",
|
|
@@ -310,6 +313,12 @@ export async function sealAcceptedSubmission(options) {
|
|
|
310
313
|
...(home !== undefined ? { home } : {}),
|
|
311
314
|
...(sessionParent === undefined ? {} : { sessionParent }),
|
|
312
315
|
});
|
|
316
|
+
landTicketProgressForSealedSubmission({
|
|
317
|
+
context: options.context,
|
|
318
|
+
role: options.role,
|
|
319
|
+
accepted: options.accepted,
|
|
320
|
+
sealHead,
|
|
321
|
+
});
|
|
313
322
|
}
|
|
314
323
|
/**
|
|
315
324
|
* Submission ledger host — record only (#836).
|
|
@@ -457,6 +466,9 @@ export function createSubmissionLedgerHost(host, outputTools, failInfrastructure
|
|
|
457
466
|
kind: "accepted",
|
|
458
467
|
accepted: params,
|
|
459
468
|
};
|
|
469
|
+
// #1199: seal-time HEAD + ticket progress before projectClosure.
|
|
470
|
+
// One seal → one row; post-turn history guessing is not used.
|
|
471
|
+
const sealHead = captureWorktreeHead(context.cwd);
|
|
460
472
|
append({
|
|
461
473
|
type: "sealed",
|
|
462
474
|
attemptId,
|
|
@@ -464,6 +476,18 @@ export function createSubmissionLedgerHost(host, outputTools, failInfrastructure
|
|
|
464
476
|
role,
|
|
465
477
|
accepted: params,
|
|
466
478
|
});
|
|
479
|
+
const rawLens = typeof host.getFlag === "function"
|
|
480
|
+
? host.getFlag("ak-review-lens")
|
|
481
|
+
: undefined;
|
|
482
|
+
landTicketProgressForSealedSubmission({
|
|
483
|
+
context,
|
|
484
|
+
role,
|
|
485
|
+
accepted: params,
|
|
486
|
+
sealHead,
|
|
487
|
+
...(rawLens === "completeness" || rawLens === "correctness"
|
|
488
|
+
? { lens: rawLens }
|
|
489
|
+
: {}),
|
|
490
|
+
});
|
|
467
491
|
await projectClosure(closed, context);
|
|
468
492
|
return result;
|
|
469
493
|
},
|