@akagilnc/pi-workflow-roles 0.1.4062 → 0.1.4196

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/dist/acp-host/production-host.js +2075 -1088
  2. package/dist/archivist-record-entry.js +204 -20
  3. package/dist/archivist-record-topology.js +36 -16
  4. package/dist/auditor-dossier-tool.js +2 -1
  5. package/dist/diarist-contracts.js +96 -0
  6. package/dist/doctor-evidence.js +3 -2
  7. package/dist/headless-host/production-host.js +2215 -1228
  8. package/dist/migrate-book-topology.js +278917 -0
  9. package/dist/navigator-public-session.js +22 -25
  10. package/dist/notary-source-run.js +7 -4
  11. package/dist/pi/durable-principal.js +9 -6
  12. package/dist/public-cli/auto-resume.js +2 -5
  13. package/dist/public-cli/diarist-run.js +27 -25
  14. package/dist/public-cli/instruction-seat-run.js +8 -11
  15. package/dist/public-cli/invocation.js +127 -63
  16. package/dist/public-cli/main.js +1507 -645
  17. package/dist/public-cli/option-definitions.js +2 -2
  18. package/dist/public-cli/post-admission.js +47 -12
  19. package/dist/public-cli/run-lifecycle.js +206 -58
  20. package/dist/public-cli/seat-ticket-binding.js +3 -6
  21. package/dist/public-cli/settlement.js +5 -3
  22. package/dist/role-run-placement.js +84 -0
  23. package/dist/role-run-relocation.js +358 -0
  24. package/dist/run-terminal-artifacts.js +2 -1
  25. package/dist/run-ticket-number.js +51 -32
  26. package/dist/sitian-appender.js +11 -26
  27. package/dist/submission-ledger.js +78 -19
  28. package/dist/ticket-provenance.js +3 -1
  29. package/package.json +3 -2
  30. package/scripts/build-package.mjs +34 -2
  31. package/souls/countersign.md +2 -2
  32. package/souls/fixer.md +3 -2
  33. package/src/analyst-ledger.ts +14 -15
  34. package/src/archivist-record-entry.ts +285 -38
  35. package/src/archivist-record-topology.ts +43 -18
  36. package/src/auditor-dossier-tool.ts +2 -1
  37. package/src/book-topology-migration-placement.ts +493 -0
  38. package/src/book-topology-migration.ts +220 -0
  39. package/src/book-topology-migrators-t11.ts +856 -0
  40. package/src/book-topology-mixed-volume-migrators.ts +470 -0
  41. package/src/book-topology-partition-migrators.ts +25 -0
  42. package/src/book-topology-record-class-migrators.ts +779 -0
  43. package/src/book-topology-runs-migrator.ts +244 -0
  44. package/src/diarist-contracts.ts +116 -0
  45. package/src/diarist-role.ts +6 -0
  46. package/src/diarist.ts +2 -0
  47. package/src/doctor-evidence.ts +4 -1
  48. package/src/doctor-role.ts +1 -1
  49. package/src/navigator-public-session.ts +33 -30
  50. package/src/notary-source-run.ts +9 -4
  51. package/src/pi/durable-principal.ts +9 -13
  52. package/src/public-cli/auto-resume.ts +2 -6
  53. package/src/public-cli/countersign-run.ts +182 -32
  54. package/src/public-cli/diarist-run.ts +34 -26
  55. package/src/public-cli/instruction-seat-run.ts +7 -11
  56. package/src/public-cli/invocation.ts +192 -58
  57. package/src/public-cli/option-definitions.ts +2 -2
  58. package/src/public-cli/post-admission.ts +73 -13
  59. package/src/public-cli/run-lifecycle.ts +255 -65
  60. package/src/public-cli/seat-ticket-binding.ts +3 -6
  61. package/src/public-cli/settlement.ts +6 -4
  62. package/src/role-run-placement.ts +128 -0
  63. package/src/role-run-relocation.ts +491 -0
  64. package/src/role-runtime.ts +11 -5
  65. package/src/run-terminal-artifacts.ts +3 -1
  66. package/src/run-ticket-number.ts +80 -20
  67. package/src/sitian-appender.ts +25 -28
  68. package/src/submission-ledger.ts +102 -19
  69. package/src/ticket-provenance.ts +4 -1
  70. package/src/ticket-trajectory.ts +22 -35
  71. package/src/worker-role.ts +4 -4
  72. package/src/worker-submission-gates.ts +6 -6
@@ -7,41 +7,38 @@ import {
7
7
  parseNavigatorModelSetting,
8
8
  resolveNavigatorSeatSelection
9
9
  } from "./navigator-session-contracts.js";
10
+ import { runDirectoryFromHostContext } from "./host-contracts.js";
11
+ async function resolveNavigatorLedgerHome(context) {
12
+ const { tryHomeFromAkRolesPath } = await import("./activation-ledger-topology.js");
13
+ const runDirectory = runDirectoryFromHostContext(context);
14
+ if (runDirectory !== void 0) {
15
+ const fromRun = tryHomeFromAkRolesPath(runDirectory);
16
+ if (fromRun !== void 0 && fromRun.length > 0) return fromRun;
17
+ }
18
+ const parentFile = context.sessionManager?.getSessionFile?.();
19
+ if (typeof parentFile === "string" && parentFile.trim() !== "") {
20
+ const fromParent = tryHomeFromAkRolesPath(parentFile);
21
+ if (fromParent !== void 0 && fromParent.length > 0) return fromParent;
22
+ }
23
+ return void 0;
24
+ }
10
25
  function createNativeNavigatorSessionFactory() {
11
26
  return async ({ context, subject, tool }) => {
12
27
  const resolved = await resolveNavigatorSeatSelection(context);
13
28
  let thinkingLevel = resolved.thinkingLevel;
14
- const { createRecordSession } = await import("./archivist-record-entry.js");
29
+ const { createRecordSession, NAVIGATOR_RECORD_KIND } = await import("./archivist-record-entry.js");
30
+ const home = await resolveNavigatorLedgerHome(context);
15
31
  const sessionManager = createRecordSession({
16
32
  cwd: context.cwd,
17
- kind: "navigator",
33
+ kind: NAVIGATOR_RECORD_KIND,
18
34
  subject,
19
- parent: context.sessionManager
35
+ ...context.sessionManager !== void 0 ? { parent: context.sessionManager } : {},
36
+ ...home !== void 0 ? { home } : {}
20
37
  });
21
38
  let providerFailure;
22
39
  let noReceipt;
23
40
  let disposed = false;
24
41
  let inFlightPrompt;
25
- const resolveHome = async () => {
26
- const parentFile = context.sessionManager?.getSessionFile?.();
27
- if (typeof parentFile === "string" && parentFile.trim() !== "") {
28
- try {
29
- const { tryHomeFromAkRolesPath, homeFromRunDirectory } = await import("./activation-ledger-topology.js");
30
- const fromParent = tryHomeFromAkRolesPath(parentFile);
31
- if (fromParent !== void 0 && fromParent.length > 0) return fromParent;
32
- const runDir = parentFile.replace(/\/session\/session\.jsonl$/, "");
33
- if (runDir !== parentFile) {
34
- try {
35
- return homeFromRunDirectory(runDir);
36
- } catch {
37
- }
38
- }
39
- } catch {
40
- }
41
- }
42
- const envHome = process.env.HOME;
43
- return typeof envHome === "string" && envHome.trim() !== "" ? envHome : void 0;
44
- };
45
42
  return {
46
43
  prompt: async (text) => {
47
44
  if (disposed) {
@@ -52,12 +49,12 @@ function createNativeNavigatorSessionFactory() {
52
49
  const run = (async () => {
53
50
  try {
54
51
  const { summonPublicRole } = await import("./public-role-summons.js");
55
- const home = await resolveHome();
52
+ const summonHome = await resolveNavigatorLedgerHome(context);
56
53
  const summoned = await summonPublicRole({
57
54
  role: "navigator",
58
55
  argv: [text],
59
56
  cwd: context.cwd,
60
- ...home === void 0 ? {} : { home }
57
+ ...summonHome === void 0 ? {} : { home: summonHome }
61
58
  });
62
59
  const outcome = summoned.terminal?.roleOutcome;
63
60
  if (outcome === void 0) {
@@ -7,7 +7,7 @@ import { dirname, isAbsolute, join, resolve, basename } from "node:path";
7
7
  import { lstat, realpath } from "node:fs/promises";
8
8
  import { resolveBookKeyFromGit } from "./activation-ledger-git.js";
9
9
  import { activationBookDirectory, physicalPathIdentity, resolveActivationLedgerHome, } from "./activation-ledger-topology.js";
10
- import { readRoleRunIdentity } from "./public-cli/run-lifecycle.js";
10
+ import { findRunDirectoryById, readRoleRunIdentity } from "./public-cli/run-lifecycle.js";
11
11
  // Run directory leaf: <runId>@<role>. Production uses uuidv7 runIds; offline tracers
12
12
  // may use deterministic non-uuid leaves. Role token stays identifier-shaped.
13
13
  const RUN_DIR_NAME = /^([A-Za-z0-9][A-Za-z0-9._-]*)@([A-Za-z][A-Za-z0-9_-]*)$/;
@@ -67,16 +67,19 @@ export async function resolveNotarySourceRunLocator(options) {
67
67
  let candidate;
68
68
  const bare = parseRunDirectoryName(raw);
69
69
  if (bare !== undefined && !raw.includes("/") && !raw.includes("\\")) {
70
- candidate = join(bookRunsRoot, `${bare.runId}@${bare.role}`);
70
+ candidate = (await findRunDirectoryById(options.home, bare.runId, bookKey, bare.role))
71
+ ?? join(bookRunsRoot, `${bare.runId}@${bare.role}`);
71
72
  }
72
73
  else {
73
74
  candidate = isAbsolute(raw) ? raw : resolve(options.projectRoot, raw);
74
75
  }
75
76
  const real = await requireRunDirectory(candidate, raw);
76
77
  const identity = parseRunDirectoryName(basename(real));
77
- const runsRootIdentity = physicalPathIdentity(bookRunsRoot);
78
+ const bookIdentity = physicalPathIdentity(activationBookDirectory(ledgerHome, bookKey));
78
79
  const parentIdentity = physicalPathIdentity(dirname(real));
79
- if (parentIdentity !== runsRootIdentity) {
80
+ const subjectBookIdentity = physicalPathIdentity(dirname(dirname(dirname(real))));
81
+ if (parentIdentity !== physicalPathIdentity(bookRunsRoot) &&
82
+ !(basename(dirname(real)) === "runs" && subjectBookIdentity === bookIdentity)) {
80
83
  throw new NotarySourceRunError("notary --source-run must resolve to a retained run under the project machine-ledger book");
81
84
  }
82
85
  // Authoritative retained record only — legal role/state via shared reader (DRY #14).
@@ -1,21 +1,24 @@
1
1
  import { lstat } from "node:fs/promises";
2
2
  import { join } from "node:path";
3
3
  import { resolveBookKeyFromGit } from "../activation-ledger-git.js";
4
- import { activationBookDirectory, resolveActivationLedgerHome, } from "../activation-ledger-topology.js";
4
+ import { resolveActivationLedgerHome } from "../activation-ledger-topology.js";
5
+ import { roleRunPlacement } from "../role-run-placement.js";
5
6
  function encode(coordinates) {
6
7
  return coordinates;
7
8
  }
8
9
  export function issuePiDurablePrincipalCoordinates(request) {
9
10
  const ledgerHome = resolveActivationLedgerHome(request.home);
10
11
  const bookKey = resolveBookKeyFromGit(request.cwd);
11
- const runDirectory = join(activationBookDirectory(ledgerHome, bookKey), "runs", `${request.runId}@${request.role}`);
12
- const sessionDirectory = join(runDirectory, "session");
12
+ const placement = roleRunPlacement(ledgerHome, {
13
+ bookKey,
14
+ subject: { unbound: true },
15
+ runId: request.runId,
16
+ role: request.role,
17
+ });
13
18
  return {
14
19
  ledgerHome,
15
20
  bookKey,
16
- runDirectory,
17
- sessionDirectory,
18
- sessionFile: join(sessionDirectory, "session.jsonl"),
21
+ ...placement,
19
22
  };
20
23
  }
21
24
  /** Pi's durable-principal codec and availability authority. */
@@ -15,6 +15,7 @@ import { constants as fsConstants } from "node:fs";
15
15
  import { randomUUID } from "node:crypto";
16
16
  import { lstat, mkdir, open } from "node:fs/promises";
17
17
  import { join } from "node:path";
18
+ import { roleRunArtifactsDirectory } from "../role-run-placement.js";
18
19
  import { AUTO_RESUME_LIMIT, describeErrorIdentity, acquireRunWriterLease, markRunResumable, markRunTerminal, RunWriterLeaseHeldError, } from "./run-lifecycle.js";
19
20
  import { parseAutoResumeLimit } from "./config.js";
20
21
  import { isLawfulTypedTerminalOutcome, formatTerminalResult } from "./terminal.js";
@@ -87,10 +88,6 @@ export class TurnDispatchedFailure extends Error {
87
88
  }
88
89
  /** Session custom-entry type carrying the pointer to one dispatch error file. */
89
90
  export const DISPATCH_ERROR_RETENTION_ENTRY_TYPE = "ak_run_dispatch_error_retention";
90
- /** Artifacts subdirectory of a run directory (established run-artifacts location). */
91
- function runArtifactsDirectory(runDirectory) {
92
- return join(runDirectory, "artifacts");
93
- }
94
91
  /**
95
92
  * #182-A hardened path identity, mirrored from settlement.ts's
96
93
  * ensureAuditEvidenceDirectory: a planted symlink at the run directory or the
@@ -106,7 +103,7 @@ export async function ensureRealArtifactsDirectory(runDirectory) {
106
103
  if (runStat.isSymbolicLink() || !runStat.isDirectory()) {
107
104
  throw new Error("run artifact retention: run directory is not a real directory");
108
105
  }
109
- const artifactsDir = runArtifactsDirectory(runDirectory);
106
+ const artifactsDir = roleRunArtifactsDirectory(runDirectory);
110
107
  try {
111
108
  const existing = await lstat(artifactsDir);
112
109
  if (existing.isSymbolicLink() || !existing.isDirectory()) {
@@ -1,20 +1,41 @@
1
1
  import { engineSessionMaterialFromOptions, pickEngineAxis } from "../package-resources/engine-material.js";
2
2
  import { CliUsageError } from "./cli-errors.js";
3
- import { admitDiaristInvocation, bindAdmittedTicketNumber, buildInstructionTransportPrompt, } from "./invocation.js";
3
+ import { admitDiaristInvocation, bindAdmittedTicketNumber, buildInstructionTransportPrompt, relocateAdmittedRunToTicket, } from "./invocation.js";
4
4
  import { prepareSummonsResumeMaterials, runPostAdmissionOneShot, runPostAdmissionSeatResume, resumeTurnRequestProjectionOptions, } from "./post-admission.js";
5
5
  import { loadResumableDiaristRun, markRunAdmitted, } from "./run-lifecycle.js";
6
6
  import { tryResumeSameTicketSeatRun } from "./seat-ticket-binding.js";
7
7
  import { presentStructuralRejection, trySettleDiaristTerminalResult, } from "./settlement.js";
8
8
  import { projectRoleTurnRequest, } from "./turn-request.js";
9
- import { readRunTicketNumber } from "../run-ticket-number.js";
9
+ import { readBoardTicketNumber } from "../run-ticket-number.js";
10
10
  /** Project admitted invocation onto the host-neutral turn request. */
11
11
  export function buildDiaristTurnRequest(admitted, options) {
12
12
  return projectRoleTurnRequest(admitted, { activation: { role: "diarist" } }, options);
13
13
  }
14
- function diaristAdapters() {
14
+ /**
15
+ * Board-bound ticket on pages → memory bind + unbound→ticket relocate under lease.
16
+ * Shared by resume (interrupted board-bound unbound) and post-turn first assert.
17
+ */
18
+ async function bindAndRelocateDiaristIfBoardBound(admitted, authority, lease) {
19
+ const boardTicket = await readBoardTicketNumber(admitted.runDirectory);
20
+ if (boardTicket === undefined)
21
+ return;
22
+ if (admitted.ticketNumber === undefined) {
23
+ await bindAdmittedTicketNumber(admitted, boardTicket);
24
+ }
25
+ await relocateAdmittedRunToTicket(admitted, authority, lease);
26
+ }
27
+ function diaristAdapters(env) {
15
28
  return {
16
29
  trySettle: (admitted, authority, scope) => trySettleDiaristTerminalResult(admitted, authority, scope),
17
30
  shouldPresentSettled: () => true,
31
+ // Resume interrupted state: board ticket already on pages, run still under unbound/.
32
+ beforeDispatch: async (admitted, lease) => {
33
+ await bindAndRelocateDiaristIfBoardBound(admitted, env.principalAuthority, lease);
34
+ },
35
+ // First post-turn assert: accept hook wrote board pages; relocate before lease release.
36
+ afterDispatch: async (admitted, lease) => {
37
+ await bindAndRelocateDiaristIfBoardBound(admitted, env.principalAuthority, lease);
38
+ },
18
39
  };
19
40
  }
20
41
  export async function runPublicDiarist(argv, env, io, parseDiaristArgv) {
@@ -67,6 +88,7 @@ export async function runPublicDiarist(argv, env, io, parseDiaristArgv) {
67
88
  ...(env.createRunId === undefined ? {} : { createRunId: env.createRunId }),
68
89
  ...(env.model === undefined ? {} : { model: env.model }),
69
90
  ...(env.correlationId === undefined ? {} : { correlationId: env.correlationId }),
91
+ ...(handoffTicket === undefined ? {} : { assertedTicketNumber: handoffTicket }),
70
92
  });
71
93
  }
72
94
  catch (error) {
@@ -77,12 +99,6 @@ export async function runPublicDiarist(argv, env, io, parseDiaristArgv) {
77
99
  throw error;
78
100
  }
79
101
  await markRunAdmitted(admitted, env.principalAuthority);
80
- // Typed handoff: bind before the turn so identity is on durable pages.
81
- if (typeof handoffTicket === "number" &&
82
- Number.isSafeInteger(handoffTicket) &&
83
- handoffTicket >= 1) {
84
- await bindAdmittedTicketNumber(admitted, handoffTicket);
85
- }
86
102
  const turnProjection = {
87
103
  packageRoot: env.packageRoot,
88
104
  home: env.home,
@@ -107,22 +123,8 @@ export async function runPublicDiarist(argv, env, io, parseDiaristArgv) {
107
123
  env,
108
124
  io,
109
125
  request: turnRequest,
110
- adapters: diaristAdapters(),
126
+ adapters: diaristAdapters(env),
111
127
  ...(env.engine === undefined ? {} : { effectiveEngine: env.engine }),
112
- }).then(async (result) => {
113
- // Accept hook binds ticket onto durable pages (#771). Mirror that page fact
114
- // onto the caller-visible admitted object — never pick a ticketNumber out of
115
- // the payload sequence (#881 sole-collapse ban on ticket/escalate).
116
- if (admitted.ticketNumber === undefined && result.admitted !== undefined) {
117
- const fromPages = await readRunTicketNumber(admitted.runDirectory);
118
- if (fromPages !== undefined) {
119
- await bindAdmittedTicketNumber(admitted, fromPages);
120
- if (result.admitted.ticketNumber === undefined) {
121
- result.admitted.ticketNumber = fromPages;
122
- }
123
- }
124
- }
125
- return result;
126
128
  });
127
129
  }
128
130
  /**
@@ -139,7 +141,7 @@ export async function runPublicDiaristResume(request, env, io) {
139
141
  const summonsPrepared = await prepareSummonsResumeMaterials(admitted.runDirectory, effective.summons);
140
142
  return buildDiaristTurnRequest(admitted, resumeTurnRequestProjectionOptions(admitted, effective, env, summonsPrepared));
141
143
  },
142
- adapters: diaristAdapters(),
144
+ adapters: diaristAdapters(env),
143
145
  ...(env.engine === undefined ? {} : { effectiveEngine: env.engine }),
144
146
  });
145
147
  }
@@ -1,7 +1,7 @@
1
1
  import { engineSessionMaterialFromOptions, pickEngineAxis } from "../package-resources/engine-material.js";
2
- import { readRunTicketNumber } from "../run-ticket-number.js";
2
+ import { readBoardTicketNumber } from "../run-ticket-number.js";
3
3
  import { CliUsageError } from "./cli-errors.js";
4
- import { admitAuditorInvocation, admitGatekeeperInvocation, admitNavigatorInvocation, bindAdmittedTicketNumber, buildInstructionTransportPrompt, persistAdmittedSourceRunPath, } from "./invocation.js";
4
+ import { admitAuditorInvocation, admitGatekeeperInvocation, admitNavigatorInvocation, buildInstructionTransportPrompt, persistAdmittedSourceRunPath, } from "./invocation.js";
5
5
  import { prepareSummonsResumeMaterials, runPostAdmissionOneShot, runPostAdmissionSeatResume, resumeTurnRequestProjectionOptions, } from "./post-admission.js";
6
6
  import { loadResumableInstructionSeatRun, markRunAdmitted, } from "./run-lifecycle.js";
7
7
  import { tryResumeSameTicketSeatRun } from "./seat-ticket-binding.js";
@@ -145,7 +145,8 @@ export async function runPublicInstructionSeat(argv, env, io, role, parseArgv) {
145
145
  home: env.home,
146
146
  });
147
147
  auditorSourceRun = resolved.runDirectory;
148
- auditorSourceTicket = await readRunTicketNumber(resolved.runDirectory);
148
+ // Auditor inherits board identity only — migration-derived is display, not admission.
149
+ auditorSourceTicket = await readBoardTicketNumber(resolved.runDirectory);
149
150
  }
150
151
  catch (error) {
151
152
  presentStructuralRejection(new CliUsageError(error instanceof Error ? error.message : String(error)), io);
@@ -195,6 +196,9 @@ export async function runPublicInstructionSeat(argv, env, io, role, parseArgv) {
195
196
  ...(env.createRunId === undefined ? {} : { createRunId: env.createRunId }),
196
197
  ...(env.model === undefined ? {} : { model: env.model }),
197
198
  ...(env.correlationId === undefined ? {} : { correlationId: env.correlationId }),
199
+ ...(auditorSourceTicket === undefined
200
+ ? {}
201
+ : { assertedTicketNumber: auditorSourceTicket }),
198
202
  });
199
203
  }
200
204
  catch (error) {
@@ -239,14 +243,7 @@ export async function runPublicInstructionSeat(argv, env, io, role, parseArgv) {
239
243
  env,
240
244
  io,
241
245
  request: turnRequest,
242
- adapters: instructionSeatAdapters({
243
- beforeDispatch: async (admittedSeat) => {
244
- // Auditor inherits source-run ticket (notary face) — typed, not prose match.
245
- if (auditorSourceTicket !== undefined) {
246
- await bindAdmittedTicketNumber(admittedSeat, auditorSourceTicket);
247
- }
248
- },
249
- }),
246
+ adapters: instructionSeatAdapters(),
250
247
  ...(env.engine === undefined ? {} : { effectiveEngine: env.engine }),
251
248
  });
252
249
  },