@akagilnc/pi-workflow-roles 0.1.3652 → 0.1.3663

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.
@@ -1116,8 +1116,8 @@ var init_durable_principal = __esm({
1116
1116
  async isAvailable(principal) {
1117
1117
  const { sessionFile } = this.decode(principal);
1118
1118
  try {
1119
- const stat2 = await lstat(sessionFile);
1120
- return stat2.isFile() && !stat2.isSymbolicLink();
1119
+ const stat3 = await lstat(sessionFile);
1120
+ return stat3.isFile() && !stat3.isSymbolicLink();
1121
1121
  } catch {
1122
1122
  return false;
1123
1123
  }
@@ -4102,6 +4102,13 @@ function instructResumeHandbookRead(prompt, engineMaterial) {
4102
4102
  return line2;
4103
4103
  }).join("\n");
4104
4104
  }
4105
+ function appendResumeMaterialReread(prompt, materialPath) {
4106
+ const instruction = resumeRereadInstruction(materialPath, false);
4107
+ const lines = prompt.split("\n");
4108
+ if (lines.includes(instruction)) return prompt;
4109
+ return prompt.length === 0 ? instruction : `${prompt}
4110
+ ${instruction}`;
4111
+ }
4105
4112
  function selectResumeContinuationPrompt(message, engineMaterial) {
4106
4113
  const base = message !== void 0 ? message : RESUME_TRANSPORT_ENVELOPE;
4107
4114
  return instructResumeHandbookRead(
@@ -4636,21 +4643,38 @@ async function findLatestRunIdForSeatTicket(input) {
4636
4643
  }
4637
4644
  return best;
4638
4645
  }
4646
+ async function collectBookRunTicketNumbers(input) {
4647
+ const ledgerHome = resolveActivationLedgerHome(input.home);
4648
+ const runsDir = join11(
4649
+ activationBookDirectory(ledgerHome, input.bookKey),
4650
+ "runs"
4651
+ );
4652
+ let entries;
4653
+ try {
4654
+ entries = await readdir2(runsDir);
4655
+ } catch (error) {
4656
+ if (errorCodeOf2(error) === "ENOENT") return /* @__PURE__ */ new Set();
4657
+ throw error;
4658
+ }
4659
+ const known = /* @__PURE__ */ new Set();
4660
+ for (const entry of entries) {
4661
+ const ticketNumber = await readRunTicketNumber(join11(runsDir, entry));
4662
+ if (ticketNumber !== void 0) known.add(ticketNumber);
4663
+ }
4664
+ return known;
4665
+ }
4639
4666
  function parsePersistedTicketIdentity(record4) {
4640
4667
  const correlationId = typeof record4.correlationId === "string" && record4.correlationId.trim() !== "" ? record4.correlationId : void 0;
4641
4668
  const ticketNumber = typeof record4.ticketNumber === "number" && Number.isSafeInteger(record4.ticketNumber) && record4.ticketNumber >= 1 ? record4.ticketNumber : void 0;
4642
- const ticketResolution = record4.ticketResolution === "true-unbound" ? "true-unbound" : void 0;
4643
4669
  return {
4644
4670
  ...correlationId === void 0 ? {} : { correlationId },
4645
- ...ticketNumber === void 0 ? {} : { ticketNumber },
4646
- ...ticketResolution === void 0 ? {} : { ticketResolution }
4671
+ ...ticketNumber === void 0 ? {} : { ticketNumber }
4647
4672
  };
4648
4673
  }
4649
4674
  function restoredTicketFields(fields) {
4650
4675
  return {
4651
4676
  ...fields.correlationId === void 0 ? {} : { correlationId: fields.correlationId },
4652
- ...fields.ticketNumber === void 0 ? {} : { ticketNumber: fields.ticketNumber },
4653
- ...fields.ticketResolution === void 0 ? {} : { ticketResolution: fields.ticketResolution }
4677
+ ...fields.ticketNumber === void 0 ? {} : { ticketNumber: fields.ticketNumber }
4654
4678
  };
4655
4679
  }
4656
4680
  async function loadResumableRunRecord(home, runId, authority) {
@@ -4686,7 +4710,6 @@ async function loadResumableRunRecord(home, runId, authority) {
4686
4710
  let derived;
4687
4711
  let correlationId;
4688
4712
  let ticketNumber;
4689
- let ticketResolution;
4690
4713
  let prNumber;
4691
4714
  let repository;
4692
4715
  let repositoryDisplay;
@@ -4800,7 +4823,6 @@ async function loadResumableRunRecord(home, runId, authority) {
4800
4823
  const fromAdmitted = parsePersistedTicketIdentity(record4);
4801
4824
  correlationId = fromAdmitted.correlationId;
4802
4825
  ticketNumber = fromAdmitted.ticketNumber;
4803
- ticketResolution = fromAdmitted.ticketResolution;
4804
4826
  }
4805
4827
  } catch (error) {
4806
4828
  if (error instanceof CliUsageError) throw error;
@@ -4823,13 +4845,10 @@ async function loadResumableRunRecord(home, runId, authority) {
4823
4845
  ...typeof rec.thinking === "string" ? { thinking: rec.thinking } : {}
4824
4846
  };
4825
4847
  }
4826
- if (correlationId === void 0 || ticketNumber === void 0 || ticketResolution === void 0) {
4848
+ if (correlationId === void 0 || ticketNumber === void 0) {
4827
4849
  const fromInvocation = parsePersistedTicketIdentity(rec);
4828
4850
  if (correlationId === void 0) correlationId = fromInvocation.correlationId;
4829
4851
  if (ticketNumber === void 0) ticketNumber = fromInvocation.ticketNumber;
4830
- if (ticketResolution === void 0) {
4831
- ticketResolution = fromInvocation.ticketResolution;
4832
- }
4833
4852
  }
4834
4853
  }
4835
4854
  } catch (error) {
@@ -4859,7 +4878,6 @@ async function loadResumableRunRecord(home, runId, authority) {
4859
4878
  ...derived === void 0 ? {} : { derived },
4860
4879
  ...correlationId === void 0 ? {} : { correlationId },
4861
4880
  ...ticketNumber === void 0 ? {} : { ticketNumber },
4862
- ...ticketResolution === void 0 ? {} : { ticketResolution },
4863
4881
  ...prNumber === void 0 ? {} : { prNumber },
4864
4882
  ...repository === void 0 ? {} : { repository },
4865
4883
  ...repositoryDisplay === void 0 ? {} : { repositoryDisplay },
@@ -5031,16 +5049,16 @@ async function requireRunDirectory(candidate, display) {
5031
5049
  { cause: error }
5032
5050
  );
5033
5051
  }
5034
- let stat2;
5052
+ let stat3;
5035
5053
  try {
5036
- stat2 = await lstat2(real);
5054
+ stat3 = await lstat2(real);
5037
5055
  } catch (error) {
5038
5056
  throw new NotarySourceRunError(
5039
5057
  `notary --source-run is not a readable run directory: ${display}`,
5040
5058
  { cause: error }
5041
5059
  );
5042
5060
  }
5043
- if (!stat2.isDirectory()) {
5061
+ if (!stat3.isDirectory()) {
5044
5062
  throw new NotarySourceRunError(
5045
5063
  `notary --source-run must be a run directory: ${display}`
5046
5064
  );
@@ -6182,7 +6200,6 @@ __export(invocation_exports, {
6182
6200
  recordEffectiveInvocationModel: () => recordEffectiveInvocationModel,
6183
6201
  recordLaunchedPiIdentity: () => recordLaunchedPiIdentity,
6184
6202
  recordLaunchedRolePackageIdentity: () => recordLaunchedRolePackageIdentity,
6185
- recordTrueUnboundTicketResolution: () => recordTrueUnboundTicketResolution,
6186
6203
  requireAuthorityRef: () => requireAuthorityRef,
6187
6204
  resolveDoctorCaseRunsPath: () => resolveDoctorCaseRunsPath,
6188
6205
  resolveGitHubRemoteRepository: () => resolveGitHubRemoteRepository
@@ -6317,11 +6334,6 @@ async function bindAdmittedTicketNumber(admitted, ticketNumber) {
6317
6334
  if (!Number.isSafeInteger(ticketNumber) || ticketNumber < 1) {
6318
6335
  throw new Error(`bindAdmittedTicketNumber requires a safe positive integer, got ${String(ticketNumber)}`);
6319
6336
  }
6320
- if (admitted.ticketResolution === "true-unbound") {
6321
- throw new Error(
6322
- "bindAdmittedTicketNumber refuses to replace durable true-unbound ticket resolution"
6323
- );
6324
- }
6325
6337
  if (admitted.ticketNumber !== void 0) {
6326
6338
  if (admitted.ticketNumber === ticketNumber) return;
6327
6339
  throw new Error(
@@ -6339,26 +6351,6 @@ async function bindAdmittedTicketNumber(admitted, ticketNumber) {
6339
6351
  "utf8"
6340
6352
  );
6341
6353
  }
6342
- async function recordTrueUnboundTicketResolution(admitted) {
6343
- if (admitted.ticketNumber !== void 0) {
6344
- throw new Error(
6345
- `recordTrueUnboundTicketResolution refuses to overwrite ticket #${admitted.ticketNumber}`
6346
- );
6347
- }
6348
- if (admitted.ticketResolution === "true-unbound") return;
6349
- admitted.ticketResolution = "true-unbound";
6350
- await mergeInvocationIdentityPage(admitted.runDirectory, {
6351
- ticketResolution: "true-unbound"
6352
- });
6353
- const admittedPath = admitted.admittedRequestPath;
6354
- const current = JSON.parse(await readFile9(admittedPath, "utf8"));
6355
- await writeFile4(
6356
- admittedPath,
6357
- `${JSON.stringify({ ...current, ticketResolution: "true-unbound" }, null, 2)}
6358
- `,
6359
- "utf8"
6360
- );
6361
- }
6362
6354
  async function recordLaunchedPiIdentity(runDirectory, identity) {
6363
6355
  await mergeInvocationIdentityPage(runDirectory, {
6364
6356
  piExecutable: identity.executable,
@@ -9270,859 +9262,253 @@ var init_config = __esm({
9270
9262
  }
9271
9263
  });
9272
9264
 
9273
- // src/diarist-ticket-resolution.ts
9274
- import { existsSync as existsSync5, readFileSync as readFileSync2 } from "node:fs";
9275
- import { join as join16 } from "node:path";
9276
- import { fileURLToPath } from "node:url";
9277
- function resolveDiaristResolveTicketMethodPath(packageRoot = fileURLToPath(new URL("..", import.meta.url))) {
9278
- return join16(packageRoot, DIARIST_RESOLVE_TICKET_METHOD_RELATIVE);
9279
- }
9280
- function instructionContainsTicketNumber(instruction, ticketNumber) {
9281
- if (!Number.isSafeInteger(ticketNumber) || ticketNumber < 1) return false;
9282
- return new RegExp(`(?<!\\d)${String(ticketNumber)}(?!\\d)`).test(instruction);
9283
- }
9284
- function parseDiaristTicketResolverStdout(stdout) {
9285
- const trimmed = stdout.trim();
9286
- if (trimmed.length === 0) {
9287
- throw new DiaristTicketResolutionError(
9288
- "empty-stdout",
9289
- "diarist ticket resolver stdout is empty"
9290
- );
9291
- }
9292
- let parsed;
9293
- try {
9294
- parsed = JSON.parse(trimmed);
9295
- } catch (error) {
9296
- throw new DiaristTicketResolutionError(
9297
- "unparseable-json",
9298
- "diarist ticket resolver stdout is not JSON",
9299
- { cause: error }
9300
- );
9301
- }
9302
- if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
9303
- throw new DiaristTicketResolutionError(
9304
- "not-object",
9305
- "diarist ticket resolver stdout must be one JSON object"
9306
- );
9307
- }
9308
- const record4 = parsed;
9309
- if (!Object.prototype.hasOwnProperty.call(record4, "assertion")) {
9310
- throw new DiaristTicketResolutionError(
9311
- "assertion-missing",
9312
- "diarist ticket resolver stdout missing assertion"
9313
- );
9265
+ // src/ticket-provenance-contracts.ts
9266
+ function isRecord11(value) {
9267
+ return typeof value === "object" && value !== null && !Array.isArray(value);
9268
+ }
9269
+ function projectTicketProvenanceDiagnostic(value) {
9270
+ if (!isRecord11(value)) return void 0;
9271
+ if (value.recordClass !== TICKET_PROVENANCE_RECORD_CLASS_DIAGNOSTIC) {
9272
+ return void 0;
9314
9273
  }
9315
- if (record4.assertion === "true-unbound") return { kind: "true-unbound" };
9316
- const n = record4.ticketNumber;
9317
- if (record4.assertion === "ticket" && typeof n === "number" && Number.isSafeInteger(n) && n >= 1) {
9318
- return { kind: "ticket", ticketNumber: n };
9274
+ if (typeof value.diagnosticKind !== "string" || !DIAGNOSTIC_KINDS.has(value.diagnosticKind)) {
9275
+ return void 0;
9319
9276
  }
9320
- throw new DiaristTicketResolutionError(
9321
- "assertion-uninterpretable",
9322
- "diarist ticket resolver assertion is not ticket|true-unbound with safe ticketNumber"
9323
- );
9324
- }
9325
- function createHermesDiaristTicketResolver(options = {}) {
9326
- const methodPath = resolveDiaristResolveTicketMethodPath(options.packageRoot);
9327
- if (!existsSync5(methodPath)) {
9328
- throw new Error(`diarist resolve-ticket method material missing (${methodPath})`);
9277
+ if (typeof value.cause !== "string" || value.cause.length === 0) {
9278
+ return void 0;
9329
9279
  }
9330
- const method = readFileSync2(methodPath, "utf8");
9331
- if (method.trim().length === 0) {
9332
- throw new Error(`diarist resolve-ticket method material is empty (${methodPath})`);
9280
+ if (typeof value.recordedAt !== "string" || value.recordedAt.length === 0) {
9281
+ return void 0;
9333
9282
  }
9334
- const executable = options.executable ?? "hermes";
9335
- return async (input) => {
9336
- const argv = [
9337
- executable,
9338
- "chat",
9339
- "--query-file",
9340
- ENGINE_DETOUR_STAGED_PROMPT_TOKEN,
9341
- "-Q",
9342
- "--no-restore-cwd",
9343
- "--ignore-rules",
9344
- "-t",
9345
- HERMES_RESOLVER_TOOLSET
9346
- ];
9347
- let result;
9348
- try {
9349
- result = await runEngineDetourOnce({
9350
- argv,
9351
- stagedPrompt: JSON.stringify({ method, instruction: input.instruction }),
9352
- cwd: options.cwd ?? process.cwd(),
9353
- ...options.env === void 0 ? {} : { env: options.env },
9354
- ...input.signal === void 0 ? {} : { signal: input.signal }
9355
- });
9356
- } catch (error) {
9357
- throw new DiaristTicketResolutionError(
9358
- "engine-failed",
9359
- "diarist ticket resolver engine failed to launch",
9360
- { cause: error }
9361
- );
9362
- }
9363
- if (result.code !== 0) {
9364
- throw new DiaristTicketResolutionError(
9365
- "engine-failed",
9366
- `diarist ticket resolver engine exited ${result.code}: ${result.stderr.slice(0, 500)}`
9367
- );
9368
- }
9369
- return parseDiaristTicketResolverStdout(result.stdout);
9370
- };
9371
- }
9372
- function createGhTicketExistenceChecker(options) {
9373
- const runner = options?.runner ?? createGhApiRunner();
9374
- return async (input) => {
9375
- const projected = await projectGhIssueBody(runner, {
9376
- owner: input.owner,
9377
- repo: input.repo,
9378
- ticketNumber: input.ticketNumber,
9379
- ...input.signal === void 0 ? {} : { signal: input.signal }
9380
- });
9381
- if (projected.status === "available") return true;
9382
- if (projected.status === "unavailable" && projected.reason === "http-non-2xx" && projected.httpStatus === 404) {
9383
- return false;
9384
- }
9385
- if (projected.status === "unavailable" && projected.reason === "pull-request") {
9386
- throw new DiaristTicketResolutionError(
9387
- "ticket-is-pull-request",
9388
- `ticket #${input.ticketNumber} resolves to a pull request, not an issue`,
9389
- { cause: projected }
9390
- );
9391
- }
9392
- if (projected.status === "unavailable") {
9393
- throw new DiaristTicketResolutionError(
9394
- "ticket-unavailable",
9395
- `ticket verification unavailable for ${input.owner}/${input.repo}#${input.ticketNumber}`,
9396
- { cause: projected }
9397
- );
9398
- }
9399
- throw new DiaristTicketResolutionError(
9400
- "ticket-invalid",
9401
- `ticket verification returned an invalid issue payload for ${input.owner}/${input.repo}#${input.ticketNumber}`,
9402
- { cause: projected }
9403
- );
9283
+ return {
9284
+ recordClass: TICKET_PROVENANCE_RECORD_CLASS_DIAGNOSTIC,
9285
+ diagnosticKind: value.diagnosticKind,
9286
+ cause: value.cause,
9287
+ recordedAt: value.recordedAt,
9288
+ ...typeof value.reason === "string" ? { reason: value.reason } : {}
9404
9289
  };
9405
9290
  }
9406
- async function verifyDiaristTicketAssertion(input) {
9407
- if (input.assertion.kind === "true-unbound") return input.assertion;
9408
- const n = input.assertion.ticketNumber;
9409
- if (!instructionContainsTicketNumber(input.instruction, n)) {
9410
- throw new DiaristTicketResolutionError(
9411
- "number-not-in-instruction",
9412
- `diarist ticket assertion #${n} complete decimal number does not appear in accepted instruction`
9413
- );
9414
- }
9415
- if (input.origin === void 0) {
9416
- throw new DiaristTicketResolutionError(
9417
- "origin-unresolved",
9418
- `diarist ticket assertion #${n} requires a resolvable github.com origin remote`
9419
- );
9291
+ function projectTicketProvenanceEntry(value) {
9292
+ if (!isRecord11(value)) return void 0;
9293
+ if (value.recordClass === TICKET_PROVENANCE_RECORD_CLASS_DIAGNOSTIC) {
9294
+ return void 0;
9420
9295
  }
9421
- let exists;
9422
- try {
9423
- exists = await input.checkExistence({
9424
- owner: input.origin.owner,
9425
- repo: input.origin.repo,
9426
- ticketNumber: n,
9427
- ...input.signal === void 0 ? {} : { signal: input.signal }
9428
- });
9429
- } catch (error) {
9430
- if (error instanceof DiaristTicketResolutionError) throw error;
9431
- throw new DiaristTicketResolutionError(
9432
- "ticket-unavailable",
9433
- `diarist ticket assertion #${n} live verification failed`,
9434
- { cause: error }
9435
- );
9296
+ if (!isRecord11(value.basis)) return void 0;
9297
+ if (typeof value.basis.method !== "string" || !BASIS_METHODS.has(value.basis.method)) {
9298
+ return void 0;
9436
9299
  }
9437
- if (!exists) {
9438
- throw new DiaristTicketResolutionError(
9439
- "ticket-missing",
9440
- `diarist ticket assertion #${n} does not exist as a live issue on ${input.origin.owner}/${input.origin.repo}`
9441
- );
9300
+ if (typeof value.sourceKind !== "string" || !SOURCE_KINDS.has(value.sourceKind)) {
9301
+ return void 0;
9442
9302
  }
9443
- return input.assertion;
9444
- }
9445
- async function resolveDiaristTicketFromInstruction(input) {
9446
- const assertion = await input.resolver({
9447
- instruction: input.instruction,
9448
- ...input.signal === void 0 ? {} : { signal: input.signal }
9449
- });
9450
- return verifyDiaristTicketAssertion({
9451
- assertion,
9452
- instruction: input.instruction,
9453
- origin: input.origin,
9454
- checkExistence: input.checkExistence,
9455
- ...input.signal === void 0 ? {} : { signal: input.signal }
9456
- });
9457
- }
9458
- var DIARIST_RESOLVE_TICKET_METHOD_RELATIVE, DiaristTicketResolutionError, HERMES_RESOLVER_TOOLSET;
9459
- var init_diarist_ticket_resolution = __esm({
9460
- "src/diarist-ticket-resolution.ts"() {
9461
- "use strict";
9462
- init_collector_github();
9463
- init_engine_detour();
9464
- DIARIST_RESOLVE_TICKET_METHOD_RELATIVE = "resources/diarist-resolve-ticket.md";
9465
- DiaristTicketResolutionError = class extends Error {
9466
- code = "diarist-ticket-resolution";
9467
- reason;
9468
- constructor(reason, message, options) {
9469
- super(message, options);
9470
- this.name = "DiaristTicketResolutionError";
9471
- this.reason = reason;
9472
- }
9473
- };
9474
- HERMES_RESOLVER_TOOLSET = "context_engine";
9303
+ if (!isRecord11(value.sourceRef)) return void 0;
9304
+ if (typeof value.transcript !== "string" || value.transcript.length === 0) {
9305
+ return void 0;
9475
9306
  }
9476
- });
9477
-
9478
- // src/adr-path-refs.ts
9479
- function extractReferencedAdrPaths(text) {
9480
- const seen = /* @__PURE__ */ new Set();
9481
- const paths = [];
9482
- for (const match of text.matchAll(ADR_PATH_IN_BODY)) {
9483
- const path = match[0];
9484
- if (seen.has(path)) continue;
9485
- seen.add(path);
9486
- paths.push(path);
9307
+ if (typeof value.timestamp !== "string" || value.timestamp.length === 0) {
9308
+ return void 0;
9487
9309
  }
9488
- return Object.freeze(paths);
9310
+ const basis = {
9311
+ method: value.basis.method,
9312
+ ...Array.isArray(value.basis.anchors) ? {
9313
+ anchors: value.basis.anchors.filter(
9314
+ (item) => typeof item === "string"
9315
+ )
9316
+ } : {},
9317
+ ...typeof value.basis.note === "string" ? { note: value.basis.note } : {}
9318
+ };
9319
+ const sourceRef = {
9320
+ ...typeof value.sourceRef.sessionFile === "string" ? { sessionFile: value.sourceRef.sessionFile } : {},
9321
+ ...typeof value.sourceRef.entryId === "string" || typeof value.sourceRef.entryId === "number" ? { entryId: value.sourceRef.entryId } : {},
9322
+ ...typeof value.sourceRef.path === "string" ? { path: value.sourceRef.path } : {},
9323
+ ...typeof value.sourceRef.url === "string" ? { url: value.sourceRef.url } : {}
9324
+ };
9325
+ return {
9326
+ basis,
9327
+ sourceKind: value.sourceKind,
9328
+ sourceRef,
9329
+ transcript: value.transcript,
9330
+ timestamp: value.timestamp
9331
+ };
9489
9332
  }
9490
- var ADR_PATH_IN_BODY;
9491
- var init_adr_path_refs = __esm({
9492
- "src/adr-path-refs.ts"() {
9333
+ var TICKET_PROVENANCE_KIND, TICKET_PROVENANCE_HUMAN_VIEW, TICKET_PROVENANCE_OFFERED_WATERMARK, TICKET_PROVENANCE_RECORD_CLASS_DIAGNOSTIC, SOURCE_KINDS, BASIS_METHODS, DIAGNOSTIC_KINDS;
9334
+ var init_ticket_provenance_contracts = __esm({
9335
+ "src/ticket-provenance-contracts.ts"() {
9493
9336
  "use strict";
9494
- ADR_PATH_IN_BODY = /docs\/adr\/(?:[A-Za-z0-9][A-Za-z0-9._-]*\/)*[A-Za-z0-9][A-Za-z0-9._-]*\.md/g;
9337
+ TICKET_PROVENANCE_KIND = "ticket-provenance";
9338
+ TICKET_PROVENANCE_HUMAN_VIEW = "\u8D77\u5C45\u5F55.md";
9339
+ TICKET_PROVENANCE_OFFERED_WATERMARK = "offered-identities.jsonl";
9340
+ TICKET_PROVENANCE_RECORD_CLASS_DIAGNOSTIC = "diagnostic";
9341
+ SOURCE_KINDS = /* @__PURE__ */ new Set([
9342
+ "cc-session",
9343
+ "issue-body-comment",
9344
+ "adr-decision-key",
9345
+ "ticket-decree-block"
9346
+ ]);
9347
+ BASIS_METHODS = /* @__PURE__ */ new Set(["llm-semantic"]);
9348
+ DIAGNOSTIC_KINDS = /* @__PURE__ */ new Set([
9349
+ "collector-failed",
9350
+ "issue-source-failed",
9351
+ "quote-verify-failed"
9352
+ ]);
9495
9353
  }
9496
9354
  });
9497
9355
 
9498
- // src/diarist-mechanical.ts
9499
- function extractCornerQuotes(text, minLength = DEFAULT_QUOTE_MIN) {
9500
- const out = [];
9501
- const re = /「([^」]+)」/g;
9502
- let match;
9503
- while ((match = re.exec(text)) !== null) {
9504
- const q = match[1].trim();
9505
- if (q.length >= minLength) out.push(q);
9356
+ // src/ticket-provenance.ts
9357
+ import { createHash as createHash5 } from "node:crypto";
9358
+ import { appendFileSync as appendFileSync2, existsSync as existsSync5, mkdirSync as mkdirSync3, readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "node:fs";
9359
+ import { join as join16 } from "node:path";
9360
+ function ticketProvenanceSubject(ticketNumber) {
9361
+ if (!Number.isSafeInteger(ticketNumber) || ticketNumber < 1) {
9362
+ throw new Error(`ticket-provenance subject requires a positive ticket number, got ${String(ticketNumber)}`);
9506
9363
  }
9507
- return out;
9364
+ return String(ticketNumber);
9508
9365
  }
9509
- function buildDiaristAnchors(input) {
9510
- const fromBody = input.ticketBody === void 0 ? [] : extractCornerQuotes(input.ticketBody);
9511
- const quotes = [...fromBody, ...input.extraQuotes ?? []];
9512
- const seen = /* @__PURE__ */ new Set();
9513
- const uniqueQuotes = [];
9514
- for (const q of quotes) {
9515
- if (seen.has(q)) continue;
9516
- seen.add(q);
9517
- uniqueQuotes.push(q);
9518
- }
9519
- return {
9366
+ function ticketProvenanceEntryIdentity(input) {
9367
+ const ref = input.sourceRef;
9368
+ const refKey = [
9369
+ ref.sessionFile ?? "",
9370
+ ref.entryId === void 0 ? "" : String(ref.entryId),
9371
+ ref.path ?? "",
9372
+ ref.url ?? ""
9373
+ ].join("");
9374
+ const material = [
9375
+ String(input.ticketNumber),
9376
+ input.sourceKind,
9377
+ refKey,
9378
+ input.transcript
9379
+ ].join("\0");
9380
+ return createHash5("sha256").update(material, "utf8").digest("hex");
9381
+ }
9382
+ function appendTicketProvenanceEntry(input) {
9383
+ const subject = ticketProvenanceSubject(input.ticketNumber);
9384
+ const identity = ticketProvenanceEntryIdentity({
9520
9385
  ticketNumber: input.ticketNumber,
9521
- quotes: uniqueQuotes
9522
- };
9386
+ sourceKind: input.entry.sourceKind,
9387
+ sourceRef: input.entry.sourceRef,
9388
+ transcript: input.entry.transcript
9389
+ });
9390
+ return sitianReport({
9391
+ level: "event",
9392
+ kind: TICKET_PROVENANCE_KIND,
9393
+ identity,
9394
+ subject,
9395
+ cwd: input.cwd,
9396
+ ...input.home === void 0 ? {} : { home: input.home },
9397
+ host: input.host ?? "diarist",
9398
+ source: input.source ?? "diarist",
9399
+ payload: input.entry,
9400
+ raw: input.entry.sourceRef.sessionFile !== void 0 && input.entry.sourceRef.entryId !== void 0 ? {
9401
+ sessionFile: input.entry.sourceRef.sessionFile,
9402
+ entryId: input.entry.sourceRef.entryId
9403
+ } : void 0
9404
+ });
9523
9405
  }
9524
- function verifyQuotesVerbatim(sourceText, quotes) {
9525
- const failed2 = [];
9526
- for (const q of quotes) {
9527
- if (q.length === 0) continue;
9528
- if (!sourceText.includes(q)) failed2.push(q);
9529
- }
9530
- if (failed2.length === 0) return { ok: true };
9531
- return { ok: false, failedQuotes: failed2 };
9532
- }
9533
- function blockToLlmEntry(block, input) {
9534
- const verify = verifyQuotesVerbatim(block.transcript, input.quotes);
9535
- if (!verify.ok) {
9536
- return {
9537
- ok: false,
9538
- failedQuotes: verify.failedQuotes,
9539
- cause: `verbatim verify failed: ${verify.failedQuotes.join(" | ")}`
9540
- };
9541
- }
9542
- const anchorNotes = [`#${input.anchors.ticketNumber}`];
9543
- const seen = new Set(anchorNotes);
9544
- for (const q of [...input.anchors.quotes, ...input.quotes]) {
9545
- if (seen.has(q)) continue;
9546
- seen.add(q);
9547
- anchorNotes.push(q);
9548
- if (anchorNotes.length >= 12) break;
9549
- }
9406
+ function resolveTicketProvenanceVolume(ticketNumber, cwd, home) {
9407
+ const path = resolveSitianRecordPath({
9408
+ level: "event",
9409
+ kind: TICKET_PROVENANCE_KIND,
9410
+ subject: ticketProvenanceSubject(ticketNumber),
9411
+ cwd,
9412
+ ...home === void 0 ? {} : { home }
9413
+ });
9550
9414
  return {
9551
- ok: true,
9552
- entry: {
9553
- basis: {
9554
- method: "llm-semantic",
9555
- anchors: anchorNotes,
9556
- ...input.note === void 0 ? {} : { note: input.note }
9557
- },
9558
- sourceKind: block.sourceKind,
9559
- sourceRef: block.sourceRef,
9560
- transcript: block.transcript,
9561
- timestamp: block.timestamp
9562
- }
9415
+ recordFile: path.recordFile,
9416
+ volumeDir: path.sessionDir,
9417
+ humanViewFile: join16(path.sessionDir, TICKET_PROVENANCE_HUMAN_VIEW),
9418
+ offeredWatermarkFile: join16(path.sessionDir, TICKET_PROVENANCE_OFFERED_WATERMARK)
9563
9419
  };
9564
9420
  }
9565
- var DEFAULT_QUOTE_MIN;
9566
- var init_diarist_mechanical = __esm({
9567
- "src/diarist-mechanical.ts"() {
9568
- "use strict";
9569
- init_activation_ledger_topology();
9570
- DEFAULT_QUOTE_MIN = 6;
9421
+ function readOfferedIdentities(ticketNumber, cwd, home) {
9422
+ const { offeredWatermarkFile } = resolveTicketProvenanceVolume(ticketNumber, cwd, home);
9423
+ if (!existsSync5(offeredWatermarkFile)) return /* @__PURE__ */ new Set();
9424
+ let text;
9425
+ try {
9426
+ text = readFileSync2(offeredWatermarkFile, "utf8");
9427
+ } catch (error) {
9428
+ throw new TicketProvenanceWatermarkError(
9429
+ "unreadable",
9430
+ `ticket-provenance offered watermark unreadable (${offeredWatermarkFile})`,
9431
+ { cause: error }
9432
+ );
9571
9433
  }
9572
- });
9573
-
9574
- // src/reviewer-git-snapshot.ts
9575
- function parseReviewerRefSnapshot(raw) {
9576
- const refs = {};
9577
- for (const line2 of raw.split("\n")) {
9578
- if (!line2) continue;
9579
- const fields = line2.split("\0");
9580
- if (fields.length !== 5 || !fields[0] || !fields[1] || !fields[3]) {
9581
- throw new Error(`Malformed Git ref snapshot line: ${line2}`);
9434
+ const seen = /* @__PURE__ */ new Set();
9435
+ const lines = text.split("\n");
9436
+ for (let index = 0; index < lines.length; index += 1) {
9437
+ const trimmed = lines[index].trim();
9438
+ if (!trimmed) continue;
9439
+ let parsed;
9440
+ try {
9441
+ parsed = JSON.parse(trimmed);
9442
+ } catch (error) {
9443
+ throw new TicketProvenanceWatermarkError(
9444
+ "malformed-json",
9445
+ `ticket-provenance offered watermark malformed JSON at line ${index + 1} (${offeredWatermarkFile})`,
9446
+ { cause: error }
9447
+ );
9582
9448
  }
9583
- const peeledCommitId = fields[3] === "commit" ? fields[1] : fields[4] === "commit" && fields[2] ? fields[2] : null;
9584
- refs[fields[0]] = Object.freeze({
9585
- objectId: fields[1],
9586
- peeledCommitId
9587
- });
9449
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed) || typeof parsed.identity !== "string" || parsed.identity.length === 0) {
9450
+ throw new TicketProvenanceWatermarkError(
9451
+ "bad-shape",
9452
+ `ticket-provenance offered watermark bad shape at line ${index + 1} (${offeredWatermarkFile})`
9453
+ );
9454
+ }
9455
+ seen.add(parsed.identity);
9588
9456
  }
9589
- return refs;
9590
- }
9591
- function reviewerRefSnapshotArgs() {
9592
- return ["for-each-ref", "--format=%(refname)%00%(objectname)%00%(*objectname)%00%(objecttype)%00%(*objecttype)", ...REVIEW_REF_PREFIXES];
9593
- }
9594
- function immutableReviewerRefs(refs) {
9595
- return Object.freeze(Object.fromEntries(Object.entries(refs).sort(([a], [b]) => a.localeCompare(b)).map(([name, entry]) => [name, Object.freeze({ objectId: entry.objectId, peeledCommitId: entry.peeledCommitId })])));
9596
- }
9597
- function sameReviewerPinnedTarget(actual, expected) {
9598
- return actual.repositoryRoot === expected.repositoryRoot && actual.objectFormat === expected.objectFormat && actual.targetHead === expected.targetHead;
9457
+ return seen;
9599
9458
  }
9600
- var REVIEW_REF_PREFIXES;
9601
- var init_reviewer_git_snapshot = __esm({
9602
- "src/reviewer-git-snapshot.ts"() {
9603
- "use strict";
9604
- REVIEW_REF_PREFIXES = ["refs/heads", "refs/tags", "refs/remotes"];
9605
- }
9606
- });
9607
-
9608
- // src/reviewer-preflight-error.ts
9609
- var ReviewerCorrectablePreflightError;
9610
- var init_reviewer_preflight_error = __esm({
9611
- "src/reviewer-preflight-error.ts"() {
9612
- "use strict";
9613
- ReviewerCorrectablePreflightError = class extends Error {
9614
- constructor(code, diagnostic = `${code} constraint failed`, options) {
9615
- super(`${code}: ${diagnostic}`, options);
9616
- this.code = code;
9617
- this.diagnostic = diagnostic;
9618
- this.name = "ReviewerCorrectablePreflightError";
9619
- }
9620
- code;
9621
- diagnostic;
9622
- };
9623
- }
9624
- });
9625
-
9626
- // src/reviewer-pinned-git.ts
9627
- import { execFile as execFile3 } from "node:child_process";
9628
- import { access as access2, realpath as realpath6 } from "node:fs/promises";
9629
- import { promisify as promisify3 } from "node:util";
9630
- async function execGit(args, options) {
9631
- try {
9632
- return await execFileAsync3("git", args, {
9633
- ...options,
9634
- env: { ...process.env, LC_ALL: "C" }
9635
- });
9636
- } catch (error) {
9637
- const source = error;
9638
- const wrapped = new Error("git process failed", { cause: error });
9639
- Object.assign(wrapped, { code: source.code ?? null, signal: source.signal ?? null, timedOut: source.killed === true && source.signal === "SIGTERM", aborted: source.name === "AbortError", stderr: String(source.stderr ?? ""), stdout: String(source.stdout ?? "") });
9640
- throw wrapped;
9459
+ function recordOfferedIdentities(input) {
9460
+ if (input.identities.length === 0) return;
9461
+ const { volumeDir, offeredWatermarkFile } = resolveTicketProvenanceVolume(
9462
+ input.ticketNumber,
9463
+ input.cwd,
9464
+ input.home
9465
+ );
9466
+ const already = new Set(readOfferedIdentities(input.ticketNumber, input.cwd, input.home));
9467
+ const rows = [];
9468
+ for (const identity of input.identities) {
9469
+ if (identity.length === 0 || already.has(identity)) continue;
9470
+ rows.push(`${JSON.stringify({ identity })}
9471
+ `);
9472
+ already.add(identity);
9641
9473
  }
9474
+ if (rows.length === 0) return;
9475
+ mkdirSync3(volumeDir, { recursive: true });
9476
+ appendFileSync2(offeredWatermarkFile, rows.join(""), "utf8");
9642
9477
  }
9643
- function exitCode(error) {
9644
- const code = typeof error === "object" && error !== null ? error.code : void 0;
9645
- return typeof code === "number" ? code : void 0;
9646
- }
9647
- function gitStderr(error) {
9648
- if (typeof error !== "object" || error === null) return "";
9649
- const stderr = error.stderr;
9650
- return typeof stderr === "string" ? stderr : "";
9651
- }
9652
- function isConfirmedMissingOriginRemote(error) {
9653
- return /No such remote ['"]origin['"]/.test(gitStderr(error));
9654
- }
9655
- function isConfirmedPinnedPathAbsent(error, path) {
9656
- const stderr = gitStderr(error);
9657
- const quoted = `'${path}'`;
9658
- return stderr.includes(`path ${quoted} does not exist in `) || stderr.includes(`path ${quoted} exists on disk, but not in `);
9659
- }
9660
- async function repositoryIsAvailable(root) {
9661
- try {
9662
- await access2(`${root}/.git`);
9663
- return { available: true };
9664
- } catch (cause) {
9665
- return { available: false, cause };
9478
+ async function readTicketProvenance(ticketNumber, cwd, home) {
9479
+ const { recordFile } = resolveTicketProvenanceVolume(ticketNumber, cwd, home);
9480
+ const { records: records2 } = await readSitianRecords(recordFile);
9481
+ const entries = [];
9482
+ const diagnostics = [];
9483
+ let skipped = 0;
9484
+ for (const record4 of records2) {
9485
+ if (record4.kind !== TICKET_PROVENANCE_KIND) {
9486
+ skipped += 1;
9487
+ continue;
9488
+ }
9489
+ const diagnostic = projectTicketProvenanceDiagnostic(record4.payload);
9490
+ if (diagnostic !== void 0) {
9491
+ diagnostics.push(diagnostic);
9492
+ continue;
9493
+ }
9494
+ const entry = projectTicketProvenanceEntry(record4.payload);
9495
+ if (entry === void 0) {
9496
+ skipped += 1;
9497
+ continue;
9498
+ }
9499
+ entries.push(entry);
9666
9500
  }
9501
+ return { entries, diagnostics, records: records2, recordFile, skipped };
9667
9502
  }
9668
- function shortNameFromPinnedRef(refName) {
9669
- const short = refName.startsWith("refs/heads/") ? refName.slice("refs/heads/".length) : refName.startsWith("refs/tags/") ? refName.slice("refs/tags/".length) : refName.startsWith("refs/remotes/") ? refName.slice("refs/remotes/".length).replace(/^[^/]+\//, "") : refName;
9670
- const trimmed = short.trim();
9671
- return trimmed === "" ? void 0 : trimmed;
9672
- }
9673
- function branchNamesAtPinnedHead(pin) {
9674
- const names = /* @__PURE__ */ new Set();
9675
- for (const [refName, entry] of Object.entries(pin.refs)) {
9676
- if (entry.peeledCommitId !== pin.targetHead) continue;
9677
- if (!refName.startsWith("refs/heads/") && !refName.startsWith("refs/remotes/")) continue;
9678
- const short = shortNameFromPinnedRef(refName);
9679
- if (short !== void 0) names.add(short);
9503
+ function markdownFenceFor(text) {
9504
+ let longest = 0;
9505
+ const runs = text.match(/`+/g);
9506
+ if (runs !== null) {
9507
+ for (const run of runs) {
9508
+ if (run.length > longest) longest = run.length;
9509
+ }
9680
9510
  }
9681
- return Object.freeze([...names]);
9682
- }
9683
- async function gitText(root, args) {
9684
- const { stdout } = await execGit(["-C", root, ...args], { encoding: "utf8" });
9685
- return stdout.trim();
9686
- }
9687
- async function createReviewerPinnedGitReader(root = process.cwd()) {
9688
- const discoveredRoot = await gitText(root, ["rev-parse", "--show-toplevel"]);
9689
- const repositoryRoot = await realpath6(discoveredRoot);
9690
- const objectFormat = await gitText(repositoryRoot, ["rev-parse", "--show-object-format"]);
9691
- if (objectFormat !== "sha1" && objectFormat !== "sha256") throw new Error("Unsupported Git object format");
9692
- const oidWidth = objectFormat === "sha1" ? 40 : 64;
9693
- const targetHead = await gitText(repositoryRoot, ["rev-parse", "HEAD^{commit}"]);
9694
- const reachableCommitIds = Object.freeze((await gitText(repositoryRoot, ["rev-list", targetHead])).split("\n").filter(Boolean));
9695
- const refs = parseReviewerRefSnapshot(await gitText(repositoryRoot, reviewerRefSnapshotArgs()));
9696
- const pin = immutableReviewerPin({ repositoryRoot, objectFormat, targetHead, refs });
9697
- const invalid = (code, diagnostic, cause) => {
9698
- throw new ReviewerCorrectablePreflightError(code, diagnostic, cause === void 0 ? void 0 : { cause });
9699
- };
9700
- const symbolic = (base) => {
9701
- const selected = Object.hasOwn(refs, base) ? base : (() => {
9702
- const candidates = [`refs/heads/${base}`, `refs/tags/${base}`, `refs/remotes/${base}`].filter((name) => Object.hasOwn(refs, name));
9703
- if (candidates.length > 1) invalid("base-invalid", "base revision is ambiguous across pinned refs");
9704
- return candidates[0];
9705
- })();
9706
- if (selected === void 0) return void 0;
9707
- const commit = refs[selected]?.peeledCommitId;
9708
- if (commit === null) invalid("base-invalid", "base revision ref must resolve to a commit");
9709
- return commit ?? void 0;
9710
- };
9711
- return Object.freeze({
9712
- pin,
9713
- async snapshot() {
9714
- const liveObjectFormat = await gitText(repositoryRoot, ["rev-parse", "--show-object-format"]);
9715
- if (liveObjectFormat !== "sha1" && liveObjectFormat !== "sha256") throw new Error("Unsupported Git object format");
9716
- return immutableReviewerPin({ repositoryRoot, objectFormat: liveObjectFormat, targetHead: await gitText(repositoryRoot, ["rev-parse", "HEAD^{commit}"]), refs: parseReviewerRefSnapshot(await gitText(repositoryRoot, reviewerRefSnapshotArgs())) });
9717
- },
9718
- async resolve(base) {
9719
- if (!/^[A-Za-z0-9._/~^+-]+$/.test(base) || base.startsWith("-") || base.includes("..") || base.includes("@{")) {
9720
- invalid("base-invalid", "base revision syntax is invalid or uses a forbidden revision form");
9721
- }
9722
- let commit;
9723
- const headExpression = /^HEAD((?:~[0-9]+|\^[0-9]+)*)$/.exec(base);
9724
- if (headExpression) {
9725
- try {
9726
- commit = await gitText(repositoryRoot, ["rev-parse", "--verify", `${targetHead}${headExpression[1]}^{commit}`]);
9727
- } catch (error) {
9728
- if (exitCode(error) === 128) {
9729
- const repository = await repositoryIsAvailable(repositoryRoot);
9730
- if (repository.available) invalid("base-invalid", "base revision HEAD ancestry expression must resolve to a reachable commit", error);
9731
- }
9732
- throw error;
9733
- }
9734
- } else if (new RegExp(`^[0-9a-f]{${oidWidth}}$`).test(base)) commit = base;
9735
- else if (new RegExp(`^[0-9a-f]{4,${oidWidth - 1}}$`).test(base) && !(objectFormat === "sha256" && base.length === 40)) {
9736
- const matches = reachableCommitIds.filter((candidate) => candidate.startsWith(base));
9737
- if (matches.length !== 1) invalid("base-invalid", "base revision abbreviation must identify exactly one reachable commit");
9738
- commit = matches[0];
9739
- } else commit = symbolic(base);
9740
- if (commit === void 0) invalid("base-invalid", "base revision must name an existing pinned ref or reachable commit");
9741
- try {
9742
- commit = await gitText(repositoryRoot, ["rev-parse", "--verify", `${commit}^{commit}`]);
9743
- } catch (error) {
9744
- if (exitCode(error) === 128) {
9745
- const repository = await repositoryIsAvailable(repositoryRoot);
9746
- if (repository.available) invalid("base-invalid", "base revision must resolve to an existing commit", error);
9747
- }
9748
- throw error;
9749
- }
9750
- try {
9751
- await gitText(repositoryRoot, ["merge-base", "--is-ancestor", commit, targetHead]);
9752
- } catch (error) {
9753
- if (exitCode(error) === 1) invalid("base-invalid", "base revision must be an ancestor of the pinned target", error);
9754
- throw error;
9755
- }
9756
- return commit;
9757
- },
9758
- async range(base) {
9759
- let mergeBase;
9760
- try {
9761
- mergeBase = await gitText(repositoryRoot, ["merge-base", base, targetHead]);
9762
- } catch (error) {
9763
- if (exitCode(error) === 1) {
9764
- invalid("range-invalid", "review range requires a common ancestor for base and pinned target", error);
9765
- }
9766
- throw error;
9767
- }
9768
- if (!mergeBase) invalid("range-invalid", "review range requires a common ancestor for base and pinned target");
9769
- const diffCommand = `git diff ${mergeBase}...${targetHead}`;
9770
- const [{ stdout: diff }, commitsText] = await Promise.all([
9771
- execGit(["-C", repositoryRoot, "diff", `${mergeBase}...${targetHead}`], { encoding: "buffer", maxBuffer: 64 * 1024 * 1024 }),
9772
- gitText(repositoryRoot, ["rev-list", "--reverse", `${mergeBase}..${targetHead}`])
9773
- ]);
9774
- if (diff.length === 0) invalid("range-invalid", "review range must contain a non-empty diff between base and pinned target");
9775
- return Object.freeze({ base: mergeBase, target: targetHead, diffCommand, diffSha256: sha256Hex(Uint8Array.from(diff)), commits: Object.freeze(commitsText ? commitsText.split("\n") : []) });
9776
- },
9777
- async featureTokens() {
9778
- const names = /* @__PURE__ */ new Set();
9779
- for (const [refName, entry] of Object.entries(pin.refs)) {
9780
- if (entry.peeledCommitId !== targetHead) continue;
9781
- const short = shortNameFromPinnedRef(refName);
9782
- if (short !== void 0) names.add(short);
9783
- }
9784
- return Object.freeze([...names]);
9785
- },
9786
- async listSpecCandidatePaths() {
9787
- const roots = ["docs", "specs", ".scratch"];
9788
- const text = await gitText(repositoryRoot, [
9789
- "ls-tree",
9790
- "-r",
9791
- "--name-only",
9792
- targetHead,
9793
- "--",
9794
- ...roots
9795
- ]);
9796
- return Object.freeze(text === "" ? [] : text.split("\n").filter((line2) => line2.length > 0));
9797
- },
9798
- async originRepository() {
9799
- let remoteUrl;
9800
- try {
9801
- remoteUrl = await gitText(repositoryRoot, ["remote", "get-url", "origin"]);
9802
- } catch (error) {
9803
- if (isConfirmedMissingOriginRemote(error)) return void 0;
9804
- throw error;
9805
- }
9806
- return parseGitHubOriginRemote(remoteUrl);
9807
- },
9808
- async commitMessagesNewestFirst(base) {
9809
- const text = await gitText(repositoryRoot, [
9810
- "log",
9811
- "--format=%s",
9812
- `${base}..${targetHead}`
9813
- ]);
9814
- return Object.freeze(text === "" ? [] : text.split("\n"));
9815
- },
9816
- async readPinnedText(path) {
9817
- if (path.length === 0 || path.startsWith("/") || path.includes("\0") || path.split("/").some((part) => part === ".." || part === "")) {
9818
- return void 0;
9819
- }
9820
- try {
9821
- const { stdout } = await execGit(
9822
- ["-C", repositoryRoot, "show", `${targetHead}:${path}`],
9823
- { encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }
9824
- );
9825
- return stdout;
9826
- } catch (error) {
9827
- if (isConfirmedPinnedPathAbsent(error, path)) return void 0;
9828
- throw error;
9829
- }
9830
- }
9831
- });
9832
- }
9833
- function parseGitHubOriginRemote(remoteUrl) {
9834
- const trimmed = remoteUrl.trim();
9835
- if (trimmed.length === 0) return void 0;
9836
- const scp = /^git@github\.com:([^/\s]+)\/([^/\s]+?)(?:\.git)?$/i.exec(trimmed);
9837
- if (scp) return normalizeOrigin(scp[1], scp[2]);
9838
- const ssh = /^ssh:\/\/git@github\.com\/([^/\s]+)\/([^/\s]+?)(?:\.git)?\/?$/i.exec(trimmed);
9839
- if (ssh) return normalizeOrigin(ssh[1], ssh[2]);
9840
- let parsed;
9841
- try {
9842
- parsed = new URL(trimmed);
9843
- } catch {
9844
- return void 0;
9845
- }
9846
- if (!/^github\.com$/i.test(parsed.hostname)) return void 0;
9847
- if (parsed.search !== "" || parsed.hash !== "") return void 0;
9848
- const parts = parsed.pathname.split("/").filter((p) => p.length > 0);
9849
- if (parts.length !== 2) return void 0;
9850
- return normalizeOrigin(parts[0], parts[1]);
9851
- }
9852
- function normalizeOrigin(ownerRaw, repoRaw) {
9853
- const owner = ownerRaw.trim();
9854
- const repo = stripGitSuffix2(repoRaw.trim());
9855
- if (owner.length === 0 || repo.length === 0) return void 0;
9856
- if (/[/?#@\\]/.test(owner) || /[/?#@\\]/.test(repo)) return void 0;
9857
- return Object.freeze({ owner, repo });
9858
- }
9859
- function stripGitSuffix2(name) {
9860
- return name.toLowerCase().endsWith(".git") ? name.slice(0, -4) : name;
9861
- }
9862
- var execFileAsync3, immutableReviewerPin;
9863
- var init_reviewer_pinned_git = __esm({
9864
- "src/reviewer-pinned-git.ts"() {
9865
- "use strict";
9866
- init_reviewer_git_snapshot();
9867
- init_sha256();
9868
- init_reviewer_preflight_error();
9869
- execFileAsync3 = promisify3(execFile3);
9870
- immutableReviewerPin = (pin) => Object.freeze({
9871
- repositoryRoot: pin.repositoryRoot,
9872
- objectFormat: pin.objectFormat,
9873
- targetHead: pin.targetHead,
9874
- refs: immutableReviewerRefs(pin.refs)
9875
- });
9876
- }
9877
- });
9878
-
9879
- // src/ticket-provenance-contracts.ts
9880
- function isRecord11(value) {
9881
- return typeof value === "object" && value !== null && !Array.isArray(value);
9882
- }
9883
- function projectTicketProvenanceDiagnostic(value) {
9884
- if (!isRecord11(value)) return void 0;
9885
- if (value.recordClass !== TICKET_PROVENANCE_RECORD_CLASS_DIAGNOSTIC) {
9886
- return void 0;
9887
- }
9888
- if (typeof value.diagnosticKind !== "string" || !DIAGNOSTIC_KINDS.has(value.diagnosticKind)) {
9889
- return void 0;
9890
- }
9891
- if (typeof value.cause !== "string" || value.cause.length === 0) {
9892
- return void 0;
9893
- }
9894
- if (typeof value.recordedAt !== "string" || value.recordedAt.length === 0) {
9895
- return void 0;
9896
- }
9897
- return {
9898
- recordClass: TICKET_PROVENANCE_RECORD_CLASS_DIAGNOSTIC,
9899
- diagnosticKind: value.diagnosticKind,
9900
- cause: value.cause,
9901
- recordedAt: value.recordedAt,
9902
- ...typeof value.reason === "string" ? { reason: value.reason } : {}
9903
- };
9904
- }
9905
- function projectTicketProvenanceEntry(value) {
9906
- if (!isRecord11(value)) return void 0;
9907
- if (value.recordClass === TICKET_PROVENANCE_RECORD_CLASS_DIAGNOSTIC) {
9908
- return void 0;
9909
- }
9910
- if (!isRecord11(value.basis)) return void 0;
9911
- if (typeof value.basis.method !== "string" || !BASIS_METHODS.has(value.basis.method)) {
9912
- return void 0;
9913
- }
9914
- if (typeof value.sourceKind !== "string" || !SOURCE_KINDS.has(value.sourceKind)) {
9915
- return void 0;
9916
- }
9917
- if (!isRecord11(value.sourceRef)) return void 0;
9918
- if (typeof value.transcript !== "string" || value.transcript.length === 0) {
9919
- return void 0;
9920
- }
9921
- if (typeof value.timestamp !== "string" || value.timestamp.length === 0) {
9922
- return void 0;
9923
- }
9924
- const basis = {
9925
- method: value.basis.method,
9926
- ...Array.isArray(value.basis.anchors) ? {
9927
- anchors: value.basis.anchors.filter(
9928
- (item) => typeof item === "string"
9929
- )
9930
- } : {},
9931
- ...typeof value.basis.note === "string" ? { note: value.basis.note } : {}
9932
- };
9933
- const sourceRef = {
9934
- ...typeof value.sourceRef.sessionFile === "string" ? { sessionFile: value.sourceRef.sessionFile } : {},
9935
- ...typeof value.sourceRef.entryId === "string" || typeof value.sourceRef.entryId === "number" ? { entryId: value.sourceRef.entryId } : {},
9936
- ...typeof value.sourceRef.path === "string" ? { path: value.sourceRef.path } : {},
9937
- ...typeof value.sourceRef.url === "string" ? { url: value.sourceRef.url } : {}
9938
- };
9939
- return {
9940
- basis,
9941
- sourceKind: value.sourceKind,
9942
- sourceRef,
9943
- transcript: value.transcript,
9944
- timestamp: value.timestamp
9945
- };
9946
- }
9947
- var TICKET_PROVENANCE_KIND, TICKET_PROVENANCE_HUMAN_VIEW, TICKET_PROVENANCE_OFFERED_WATERMARK, TICKET_PROVENANCE_RECORD_CLASS_DIAGNOSTIC, SOURCE_KINDS, BASIS_METHODS, DIAGNOSTIC_KINDS;
9948
- var init_ticket_provenance_contracts = __esm({
9949
- "src/ticket-provenance-contracts.ts"() {
9950
- "use strict";
9951
- TICKET_PROVENANCE_KIND = "ticket-provenance";
9952
- TICKET_PROVENANCE_HUMAN_VIEW = "\u8D77\u5C45\u5F55.md";
9953
- TICKET_PROVENANCE_OFFERED_WATERMARK = "offered-identities.jsonl";
9954
- TICKET_PROVENANCE_RECORD_CLASS_DIAGNOSTIC = "diagnostic";
9955
- SOURCE_KINDS = /* @__PURE__ */ new Set([
9956
- "cc-session",
9957
- "issue-body-comment",
9958
- "adr-decision-key",
9959
- "ticket-decree-block"
9960
- ]);
9961
- BASIS_METHODS = /* @__PURE__ */ new Set(["llm-semantic"]);
9962
- DIAGNOSTIC_KINDS = /* @__PURE__ */ new Set([
9963
- "collector-failed",
9964
- "issue-source-failed",
9965
- "quote-verify-failed"
9966
- ]);
9967
- }
9968
- });
9969
-
9970
- // src/ticket-provenance.ts
9971
- import { createHash as createHash5 } from "node:crypto";
9972
- import { appendFileSync as appendFileSync2, existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "node:fs";
9973
- import { join as join17 } from "node:path";
9974
- function ticketProvenanceSubject(ticketNumber) {
9975
- if (!Number.isSafeInteger(ticketNumber) || ticketNumber < 1) {
9976
- throw new Error(`ticket-provenance subject requires a positive ticket number, got ${String(ticketNumber)}`);
9977
- }
9978
- return String(ticketNumber);
9979
- }
9980
- function ticketProvenanceEntryIdentity(input) {
9981
- const ref = input.sourceRef;
9982
- const refKey = [
9983
- ref.sessionFile ?? "",
9984
- ref.entryId === void 0 ? "" : String(ref.entryId),
9985
- ref.path ?? "",
9986
- ref.url ?? ""
9987
- ].join("");
9988
- const material = [
9989
- String(input.ticketNumber),
9990
- input.sourceKind,
9991
- refKey,
9992
- input.transcript
9993
- ].join("\0");
9994
- return createHash5("sha256").update(material, "utf8").digest("hex");
9995
- }
9996
- function appendTicketProvenanceEntry(input) {
9997
- const subject = ticketProvenanceSubject(input.ticketNumber);
9998
- const identity = ticketProvenanceEntryIdentity({
9999
- ticketNumber: input.ticketNumber,
10000
- sourceKind: input.entry.sourceKind,
10001
- sourceRef: input.entry.sourceRef,
10002
- transcript: input.entry.transcript
10003
- });
10004
- return sitianReport({
10005
- level: "event",
10006
- kind: TICKET_PROVENANCE_KIND,
10007
- identity,
10008
- subject,
10009
- cwd: input.cwd,
10010
- ...input.home === void 0 ? {} : { home: input.home },
10011
- host: input.host ?? "diarist",
10012
- source: input.source ?? "diarist",
10013
- payload: input.entry,
10014
- raw: input.entry.sourceRef.sessionFile !== void 0 && input.entry.sourceRef.entryId !== void 0 ? {
10015
- sessionFile: input.entry.sourceRef.sessionFile,
10016
- entryId: input.entry.sourceRef.entryId
10017
- } : void 0
10018
- });
10019
- }
10020
- function resolveTicketProvenanceVolume(ticketNumber, cwd, home) {
10021
- const path = resolveSitianRecordPath({
10022
- level: "event",
10023
- kind: TICKET_PROVENANCE_KIND,
10024
- subject: ticketProvenanceSubject(ticketNumber),
10025
- cwd,
10026
- ...home === void 0 ? {} : { home }
10027
- });
10028
- return {
10029
- recordFile: path.recordFile,
10030
- volumeDir: path.sessionDir,
10031
- humanViewFile: join17(path.sessionDir, TICKET_PROVENANCE_HUMAN_VIEW),
10032
- offeredWatermarkFile: join17(path.sessionDir, TICKET_PROVENANCE_OFFERED_WATERMARK)
10033
- };
10034
- }
10035
- function readOfferedIdentities(ticketNumber, cwd, home) {
10036
- const { offeredWatermarkFile } = resolveTicketProvenanceVolume(ticketNumber, cwd, home);
10037
- if (!existsSync6(offeredWatermarkFile)) return /* @__PURE__ */ new Set();
10038
- let text;
10039
- try {
10040
- text = readFileSync3(offeredWatermarkFile, "utf8");
10041
- } catch (error) {
10042
- throw new TicketProvenanceWatermarkError(
10043
- "unreadable",
10044
- `ticket-provenance offered watermark unreadable (${offeredWatermarkFile})`,
10045
- { cause: error }
10046
- );
10047
- }
10048
- const seen = /* @__PURE__ */ new Set();
10049
- const lines = text.split("\n");
10050
- for (let index = 0; index < lines.length; index += 1) {
10051
- const trimmed = lines[index].trim();
10052
- if (!trimmed) continue;
10053
- let parsed;
10054
- try {
10055
- parsed = JSON.parse(trimmed);
10056
- } catch (error) {
10057
- throw new TicketProvenanceWatermarkError(
10058
- "malformed-json",
10059
- `ticket-provenance offered watermark malformed JSON at line ${index + 1} (${offeredWatermarkFile})`,
10060
- { cause: error }
10061
- );
10062
- }
10063
- if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed) || typeof parsed.identity !== "string" || parsed.identity.length === 0) {
10064
- throw new TicketProvenanceWatermarkError(
10065
- "bad-shape",
10066
- `ticket-provenance offered watermark bad shape at line ${index + 1} (${offeredWatermarkFile})`
10067
- );
10068
- }
10069
- seen.add(parsed.identity);
10070
- }
10071
- return seen;
10072
- }
10073
- function recordOfferedIdentities(input) {
10074
- if (input.identities.length === 0) return;
10075
- const { volumeDir, offeredWatermarkFile } = resolveTicketProvenanceVolume(
10076
- input.ticketNumber,
10077
- input.cwd,
10078
- input.home
10079
- );
10080
- const already = new Set(readOfferedIdentities(input.ticketNumber, input.cwd, input.home));
10081
- const rows = [];
10082
- for (const identity of input.identities) {
10083
- if (identity.length === 0 || already.has(identity)) continue;
10084
- rows.push(`${JSON.stringify({ identity })}
10085
- `);
10086
- already.add(identity);
10087
- }
10088
- if (rows.length === 0) return;
10089
- mkdirSync3(volumeDir, { recursive: true });
10090
- appendFileSync2(offeredWatermarkFile, rows.join(""), "utf8");
10091
- }
10092
- async function readTicketProvenance(ticketNumber, cwd, home) {
10093
- const { recordFile } = resolveTicketProvenanceVolume(ticketNumber, cwd, home);
10094
- const { records: records2 } = await readSitianRecords(recordFile);
10095
- const entries = [];
10096
- const diagnostics = [];
10097
- let skipped = 0;
10098
- for (const record4 of records2) {
10099
- if (record4.kind !== TICKET_PROVENANCE_KIND) {
10100
- skipped += 1;
10101
- continue;
10102
- }
10103
- const diagnostic = projectTicketProvenanceDiagnostic(record4.payload);
10104
- if (diagnostic !== void 0) {
10105
- diagnostics.push(diagnostic);
10106
- continue;
10107
- }
10108
- const entry = projectTicketProvenanceEntry(record4.payload);
10109
- if (entry === void 0) {
10110
- skipped += 1;
10111
- continue;
10112
- }
10113
- entries.push(entry);
10114
- }
10115
- return { entries, diagnostics, records: records2, recordFile, skipped };
10116
- }
10117
- function markdownFenceFor(text) {
10118
- let longest = 0;
10119
- const runs = text.match(/`+/g);
10120
- if (runs !== null) {
10121
- for (const run of runs) {
10122
- if (run.length > longest) longest = run.length;
10123
- }
10124
- }
10125
- return "`".repeat(Math.max(3, longest + 1));
9511
+ return "`".repeat(Math.max(3, longest + 1));
10126
9512
  }
10127
9513
  function renderTicketProvenanceMarkdown(input) {
10128
9514
  const lines = [
@@ -10224,203 +9610,86 @@ function writeTicketProvenanceHumanView(input) {
10224
9610
  ticketNumber: input.ticketNumber,
10225
9611
  entries: input.entries
10226
9612
  });
10227
- writeFileSync3(volume.humanViewFile, md, "utf8");
10228
- return volume.humanViewFile;
10229
- }
10230
- var TicketProvenanceWatermarkError;
10231
- var init_ticket_provenance = __esm({
10232
- "src/ticket-provenance.ts"() {
10233
- "use strict";
10234
- init_sitian_facade();
10235
- init_ticket_provenance_contracts();
10236
- TicketProvenanceWatermarkError = class extends Error {
10237
- code = "ticket-provenance-watermark";
10238
- reason;
10239
- constructor(reason, message, options) {
10240
- super(message, options);
10241
- this.name = "TicketProvenanceWatermarkError";
10242
- this.reason = reason;
10243
- }
10244
- };
10245
- }
10246
- });
10247
-
10248
- // src/diarist.ts
10249
- import { readFileSync as readFileSync4 } from "node:fs";
10250
- import { execFileSync as execFileSync3 } from "node:child_process";
10251
- function resolveDiaristGithubOrigin(projectRoot) {
10252
- let remoteUrl;
10253
- try {
10254
- remoteUrl = execFileSync3("git", ["remote", "get-url", "origin"], {
10255
- cwd: projectRoot,
10256
- encoding: "utf8",
10257
- stdio: ["ignore", "pipe", "pipe"]
10258
- }).trim();
10259
- } catch {
10260
- return void 0;
10261
- }
10262
- if (remoteUrl.length === 0) return void 0;
10263
- return parseGitHubOriginRemote(remoteUrl);
10264
- }
10265
- function blockEntryIdentity(ticketNumber, block) {
10266
- return ticketProvenanceEntryIdentity({
10267
- ticketNumber,
10268
- sourceKind: block.sourceKind,
10269
- sourceRef: block.sourceRef,
10270
- transcript: block.transcript
10271
- });
10272
- }
10273
- function loadDiaristSourceCatalog(path) {
10274
- const parsed = JSON.parse(readFileSync4(path, "utf8"));
10275
- if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
10276
- throw new Error(`diarist source catalog is not an object (${path})`);
10277
- }
10278
- const record4 = parsed;
10279
- if (typeof record4.ticketNumber !== "number" || typeof record4.cwd !== "string") {
10280
- throw new Error(`diarist source catalog is missing ticket coordinates (${path})`);
10281
- }
10282
- if (!Array.isArray(record4.candidates)) {
10283
- throw new Error(`diarist source catalog is missing candidates (${path})`);
10284
- }
10285
- return parsed;
10286
- }
10287
- async function commitDiaristSelections(input) {
10288
- const { ticketNumber, cwd } = input.catalog;
10289
- const homeOpt = input.catalog.home === void 0 ? {} : { home: input.catalog.home };
10290
- const volumePaths = ensureTicketProvenanceVolume(ticketNumber, cwd, input.catalog.home);
10291
- const anchors = buildDiaristAnchors({ ticketNumber });
10292
- const before = await readTicketProvenance(ticketNumber, cwd, input.catalog.home);
10293
- let acceptedRows = 0;
10294
- let rejectedQuotes = 0;
10295
- let unknownCandidate = false;
10296
- for (const selection of input.selections) {
10297
- const block = input.catalog.candidates[selection.candidateIndex];
10298
- if (block === void 0) {
10299
- unknownCandidate = true;
10300
- continue;
10301
- }
10302
- const projected = blockToLlmEntry(block, {
10303
- anchors,
10304
- quotes: selection.quotes,
10305
- ...selection.note === void 0 ? {} : { note: selection.note }
10306
- });
10307
- if (!projected.ok) {
10308
- rejectedQuotes += 1;
10309
- appendQuoteVerifyFailureDiagnostic({
10310
- ticketNumber,
10311
- cwd,
10312
- ...homeOpt,
10313
- cause: projected.cause
10314
- });
10315
- continue;
10316
- }
10317
- appendTicketProvenanceEntry({
10318
- ticketNumber,
10319
- cwd,
10320
- ...homeOpt,
10321
- entry: projected.entry,
10322
- source: "diarist"
10323
- });
10324
- acceptedRows += 1;
10325
- }
10326
- const identities = input.catalog.candidates.map(
10327
- (block) => blockEntryIdentity(ticketNumber, block)
10328
- );
10329
- const alreadyWatermarked = readOfferedIdentities(ticketNumber, cwd, input.catalog.home);
10330
- const watermarked = identities.filter((identity) => !alreadyWatermarked.has(identity)).length;
10331
- recordOfferedIdentities({ ticketNumber, cwd, ...homeOpt, identities });
10332
- const volume = await readTicketProvenance(ticketNumber, cwd, input.catalog.home);
10333
- const humanViewFile = writeTicketProvenanceHumanView({
10334
- ticketNumber,
10335
- cwd,
10336
- ...homeOpt,
10337
- entries: volume.entries
10338
- });
10339
- return {
10340
- ticketNumber,
10341
- offered: input.catalog.candidates.length,
10342
- appended: volume.entries.length - before.entries.length,
10343
- rejectedQuotes,
10344
- watermarked,
10345
- volumeRecordFile: volumePaths.recordFile,
10346
- humanViewFile,
10347
- collectorStatus: input.catalog.candidates.length === 0 ? "skipped-no-fresh" : acceptedRows > 0 ? "ok" : input.selections.length === 0 ? "empty-selection" : "nothing-appended",
10348
- failureCauses: [
10349
- ...unknownCandidate ? ["unknown-candidate"] : [],
10350
- ...rejectedQuotes > 0 ? ["quote-verify-rejected"] : []
10351
- ]
10352
- };
9613
+ writeFileSync3(volume.humanViewFile, md, "utf8");
9614
+ return volume.humanViewFile;
10353
9615
  }
10354
- var init_diarist = __esm({
10355
- "src/diarist.ts"() {
9616
+ var TicketProvenanceWatermarkError;
9617
+ var init_ticket_provenance = __esm({
9618
+ "src/ticket-provenance.ts"() {
10356
9619
  "use strict";
10357
- init_adr_path_refs();
10358
- init_collector_github();
10359
- init_diarist_mechanical();
10360
- init_reviewer_pinned_git();
10361
- init_ticket_provenance();
10362
9620
  init_sitian_facade();
9621
+ init_ticket_provenance_contracts();
9622
+ TicketProvenanceWatermarkError = class extends Error {
9623
+ code = "ticket-provenance-watermark";
9624
+ reason;
9625
+ constructor(reason, message, options) {
9626
+ super(message, options);
9627
+ this.name = "TicketProvenanceWatermarkError";
9628
+ this.reason = reason;
9629
+ }
9630
+ };
10363
9631
  }
10364
9632
  });
10365
9633
 
10366
9634
  // src/public-cli/seat-ticket-binding.ts
10367
- async function resolveInstructionTicket(instruction, projectRoot, env = {}) {
10368
- const resolver = createHermesDiaristTicketResolver({
10369
- ...env.packageRoot === void 0 ? {} : { packageRoot: env.packageRoot },
10370
- cwd: projectRoot
10371
- });
10372
- const checkExistence = createGhTicketExistenceChecker();
10373
- const origin = resolveDiaristGithubOrigin(projectRoot);
10374
- return resolveDiaristTicketFromInstruction({
10375
- instruction,
10376
- origin,
10377
- resolver,
10378
- checkExistence
10379
- });
10380
- }
10381
- async function probeInstructionTicket(instruction, projectRoot, env = {}) {
10382
- try {
10383
- const resolution = await resolveInstructionTicket(
10384
- instruction,
10385
- projectRoot,
10386
- env
9635
+ import { existsSync as existsSync6 } from "node:fs";
9636
+ function instructionTicketTokens(instruction) {
9637
+ const tokens = /* @__PURE__ */ new Set();
9638
+ for (const run of instruction.match(/\d+/g) ?? []) {
9639
+ if (run.startsWith("0")) continue;
9640
+ const parsed = Number(run);
9641
+ if (!Number.isSafeInteger(parsed) || parsed < 1) continue;
9642
+ tokens.add(parsed);
9643
+ }
9644
+ return [...tokens];
9645
+ }
9646
+ async function resolveKnownTicketNumber(input) {
9647
+ const tokens = instructionTicketTokens(input.instruction);
9648
+ if (tokens.length === 0) return void 0;
9649
+ const known = [];
9650
+ let runTickets;
9651
+ for (const token of tokens) {
9652
+ const volume = resolveTicketProvenanceVolume(
9653
+ token,
9654
+ input.projectRoot,
9655
+ input.home
10387
9656
  );
10388
- return { kind: "resolved", resolution };
10389
- } catch (error) {
10390
- if (error instanceof DiaristTicketResolutionError) {
10391
- return { kind: "failed", error };
9657
+ if (existsSync6(volume.volumeDir)) {
9658
+ known.push(token);
9659
+ continue;
10392
9660
  }
10393
- throw error;
9661
+ if (runTickets === void 0) {
9662
+ runTickets = await readBookRunTickets(input);
9663
+ }
9664
+ if (runTickets.has(token)) known.push(token);
10394
9665
  }
9666
+ return known.length === 1 ? known[0] : void 0;
10395
9667
  }
10396
- function ticketNumberFromProbe(probe) {
10397
- if (probe.kind !== "resolved") return void 0;
10398
- if (probe.resolution.kind !== "ticket") return void 0;
10399
- return probe.resolution.ticketNumber;
10400
- }
10401
- async function applyTicketResolution(admitted, resolution) {
10402
- if (resolution.kind === "ticket") {
10403
- await bindAdmittedTicketNumber(admitted, resolution.ticketNumber);
10404
- } else {
10405
- await recordTrueUnboundTicketResolution(admitted);
9668
+ async function readBookRunTickets(input) {
9669
+ let bookKey;
9670
+ try {
9671
+ bookKey = input.bookKey ?? resolveBookKeyFromGit(input.projectRoot);
9672
+ } catch (error) {
9673
+ if (error instanceof ActivationGitRepositoryRequiredError) return /* @__PURE__ */ new Set();
9674
+ throw error;
10406
9675
  }
9676
+ return await collectBookRunTicketNumbers({ home: input.home, bookKey });
10407
9677
  }
10408
- async function applyInstructionTicketProbe(admitted, probe) {
10409
- if (probe.kind === "failed") throw probe.error;
10410
- await applyTicketResolution(admitted, probe.resolution);
9678
+ async function bindReusedTicketNumber(admitted, ticketNumber) {
9679
+ if (ticketNumber === void 0) return;
9680
+ if (admitted.ticketNumber !== void 0) return;
9681
+ await bindAdmittedTicketNumber(admitted, ticketNumber);
10411
9682
  }
10412
- async function resolveSeatTicketBinding(admitted, env = {}) {
10413
- if (admitted.ticketNumber !== void 0) return void 0;
10414
- if (admitted.ticketResolution === "true-unbound") {
10415
- return { kind: "true-unbound" };
10416
- }
10417
- const resolution = await resolveInstructionTicket(
10418
- admitted.instruction,
10419
- admitted.projectRoot,
10420
- env
10421
- );
10422
- await applyTicketResolution(admitted, resolution);
10423
- return resolution;
9683
+ async function resolveSeatTicketBinding(admitted, env) {
9684
+ if (admitted.ticketNumber !== void 0) return admitted.ticketNumber;
9685
+ const ticketNumber = await resolveKnownTicketNumber({
9686
+ instruction: admitted.instruction,
9687
+ projectRoot: admitted.projectRoot,
9688
+ home: env.home,
9689
+ bookKey: admitted.bookKey
9690
+ });
9691
+ await bindReusedTicketNumber(admitted, ticketNumber);
9692
+ return ticketNumber;
10424
9693
  }
10425
9694
  async function tryResumeSameTicketSeatRun(input) {
10426
9695
  if (input.freshSummons === true) return void 0;
@@ -10441,22 +9710,58 @@ var init_seat_ticket_binding = __esm({
10441
9710
  "src/public-cli/seat-ticket-binding.ts"() {
10442
9711
  "use strict";
10443
9712
  init_activation_ledger_git();
10444
- init_diarist_ticket_resolution();
10445
- init_diarist();
9713
+ init_ticket_provenance();
10446
9714
  init_invocation();
10447
9715
  init_run_lifecycle();
10448
9716
  }
10449
9717
  });
10450
9718
 
9719
+ // src/public-cli/case-dossier-delivery.ts
9720
+ import { stat as stat2 } from "node:fs/promises";
9721
+ async function describeDossierFile(path) {
9722
+ try {
9723
+ const stats = await stat2(path);
9724
+ if (!stats.isFile()) return `\u4E0D\u53EF\u8BFB\uFF08\u975E\u666E\u901A\u6587\u4EF6\uFF09\uFF1A${path}`;
9725
+ return path;
9726
+ } catch (error) {
9727
+ const code = error.code;
9728
+ if (code === "ENOENT") return `\u5C1A\u672A\u751F\u6210\uFF1A${path}`;
9729
+ return `\u4E0D\u53EF\u8BFB\uFF08${code ?? "\u672A\u77E5\u9519\u8BEF"}\uFF09\uFF1A${path}`;
9730
+ }
9731
+ }
9732
+ async function projectCaseDossierPointerSection(input) {
9733
+ if (input.ticketNumber === void 0) return void 0;
9734
+ const volume = resolveTicketProvenanceVolume(
9735
+ input.ticketNumber,
9736
+ input.projectRoot,
9737
+ input.home
9738
+ );
9739
+ return [
9740
+ CASE_DOSSIER_SECTION_HEADING,
9741
+ "",
9742
+ `\u7968\u53F7\uFF1A#${input.ticketNumber}`,
9743
+ `\u4EBA\u8BFB\u89C6\u56FE\uFF1A${await describeDossierFile(volume.humanViewFile)}`,
9744
+ `\u8BB0\u5F55\u5377\u5B97\uFF1A${await describeDossierFile(volume.recordFile)}`
9745
+ ].join("\n");
9746
+ }
9747
+ var CASE_DOSSIER_SECTION_HEADING;
9748
+ var init_case_dossier_delivery = __esm({
9749
+ "src/public-cli/case-dossier-delivery.ts"() {
9750
+ "use strict";
9751
+ init_ticket_provenance();
9752
+ CASE_DOSSIER_SECTION_HEADING = "## \u672C\u7968\u8D77\u5C45\u5F55\uFF08\u7CFB\u7EDF\u968F\u6848\u63D0\u4F9B\uFF09";
9753
+ }
9754
+ });
9755
+
10451
9756
  // src/host-transition-prior-native.ts
10452
- import { access as access3, readdir as readdir3 } from "node:fs/promises";
10453
- import { dirname as dirname9, join as join18 } from "node:path";
9757
+ import { access as access2, readdir as readdir3 } from "node:fs/promises";
9758
+ import { dirname as dirname9, join as join17 } from "node:path";
10454
9759
  function isEnoent2(error) {
10455
9760
  return typeof error === "object" && error !== null && error.code === "ENOENT";
10456
9761
  }
10457
9762
  async function listPiNativeRecordPaths(sessionFile) {
10458
9763
  try {
10459
- await access3(sessionFile);
9764
+ await access2(sessionFile);
10460
9765
  return [sessionFile];
10461
9766
  } catch (error) {
10462
9767
  if (isEnoent2(error)) return [];
@@ -10475,9 +9780,9 @@ async function listSitianRecordPaths(sessionParent) {
10475
9780
  const recordPaths = [];
10476
9781
  for (const entry of entries) {
10477
9782
  if (!entry.isDirectory()) continue;
10478
- const recordFile = join18(sessionRoot, entry.name, "records.jsonl");
9783
+ const recordFile = join17(sessionRoot, entry.name, "records.jsonl");
10479
9784
  try {
10480
- await access3(recordFile);
9785
+ await access2(recordFile);
10481
9786
  recordPaths.push(recordFile);
10482
9787
  } catch (error) {
10483
9788
  if (!isEnoent2(error)) throw error;
@@ -10737,7 +10042,7 @@ var init_gatekeeper_role = __esm({
10737
10042
  });
10738
10043
 
10739
10044
  // src/run-terminal-artifacts.ts
10740
- import { basename as basename6, dirname as dirname10, join as join19 } from "node:path";
10045
+ import { basename as basename6, dirname as dirname10, join as join18 } from "node:path";
10741
10046
  function runIdFromRunDirectory(runDirectory) {
10742
10047
  const name = basename6(runDirectory);
10743
10048
  const at = name.lastIndexOf("@");
@@ -11159,7 +10464,7 @@ var init_ledger_session_read = __esm({
11159
10464
 
11160
10465
  // src/analyst-gate-cycles-read.ts
11161
10466
  import { readdir as readdir4 } from "node:fs/promises";
11162
- import { join as join20 } from "node:path";
10467
+ import { join as join19 } from "node:path";
11163
10468
  function isRecord15(value) {
11164
10469
  return typeof value === "object" && value !== null && !Array.isArray(value);
11165
10470
  }
@@ -11420,7 +10725,7 @@ async function readAnalystGateCyclesFromAuditorRoles(auditorRolesDirectory, opti
11420
10725
  throw error;
11421
10726
  }
11422
10727
  for (const name of names) {
11423
- const path = join20(directory, name);
10728
+ const path = join19(directory, name);
11424
10729
  const sessionPath = name.endsWith(".pointer.json") ? await resolveOfficerSessionFromPointerFile(path) : path;
11425
10730
  if (sessionPath === void 0) continue;
11426
10731
  const classified = await classifyAuditorVolume(sessionPath);
@@ -11459,22 +10764,22 @@ var init_analyst_gate_cycles_read = __esm({
11459
10764
  // src/session-opening-materials.ts
11460
10765
  import { existsSync as existsSync7 } from "node:fs";
11461
10766
  import { readFile as readFile12 } from "node:fs/promises";
11462
- import { dirname as dirname11, join as join21 } from "node:path";
11463
- import { fileURLToPath as fileURLToPath2, pathToFileURL as pathToFileURL2 } from "node:url";
10767
+ import { dirname as dirname11, join as join20 } from "node:path";
10768
+ import { fileURLToPath, pathToFileURL as pathToFileURL2 } from "node:url";
11464
10769
  function resolvePackageRootDir(moduleUrl = import.meta.url) {
11465
- let dir = dirname11(fileURLToPath2(moduleUrl));
10770
+ let dir = dirname11(fileURLToPath(moduleUrl));
11466
10771
  for (let i = 0; i < 8; i += 1) {
11467
- if (existsSync7(join21(dir, "package.json")) && existsSync7(join21(dir, "souls"))) {
10772
+ if (existsSync7(join20(dir, "package.json")) && existsSync7(join20(dir, "souls"))) {
11468
10773
  return dir;
11469
10774
  }
11470
10775
  const parent = dirname11(dir);
11471
10776
  if (parent === dir) break;
11472
10777
  dir = parent;
11473
10778
  }
11474
- return fileURLToPath2(new URL("..", moduleUrl));
10779
+ return fileURLToPath(new URL("..", moduleUrl));
11475
10780
  }
11476
10781
  async function readPackageMaterial(relativePath) {
11477
- return readFile12(fileURLToPath2(new URL(relativePath, packageRootUrl)), "utf8");
10782
+ return readFile12(fileURLToPath(new URL(relativePath, packageRootUrl)), "utf8");
11478
10783
  }
11479
10784
  async function joinPackageMaterials(relativePaths) {
11480
10785
  const chunks = [];
@@ -11671,75 +10976,400 @@ function createPiJudgeAuditor() {
11671
10976
  });
11672
10977
  };
11673
10978
  }
11674
- var init_judge_auditor = __esm({
11675
- "src/judge-auditor.ts"() {
11676
- "use strict";
11677
- init_compliance_transport();
11678
- init_auditor_dossier_tool();
11679
- init_dossier_resolution();
10979
+ var init_judge_auditor = __esm({
10980
+ "src/judge-auditor.ts"() {
10981
+ "use strict";
10982
+ init_compliance_transport();
10983
+ init_auditor_dossier_tool();
10984
+ init_dossier_resolution();
10985
+ }
10986
+ });
10987
+
10988
+ // src/upstream-error-testimony.ts
10989
+ function isNonSuccessHttpStatus(status) {
10990
+ return typeof status === "number" && (status < 200 || status >= 300);
10991
+ }
10992
+ function hasUpstreamErrorTestimony(input) {
10993
+ if (isNonSuccessHttpStatus(input.httpStatus)) return true;
10994
+ return Array.isArray(input.diagnostics) && input.diagnostics.length > 0;
10995
+ }
10996
+ function projectConfirmedRemotePayload(input) {
10997
+ return {
10998
+ ...input.body === void 0 ? {} : { body: input.body },
10999
+ ...input.code === void 0 ? {} : { code: input.code },
11000
+ ...input.errno === void 0 ? {} : { errno: input.errno }
11001
+ };
11002
+ }
11003
+ var init_upstream_error_testimony = __esm({
11004
+ "src/upstream-error-testimony.ts"() {
11005
+ "use strict";
11006
+ }
11007
+ });
11008
+
11009
+ // src/pi/known-failure.ts
11010
+ function nonEmptyString(value) {
11011
+ return typeof value === "string" && value.trim() !== "" ? value : void 0;
11012
+ }
11013
+ function sessionStopDetails(input) {
11014
+ const details = {};
11015
+ const errorMessage = nonEmptyString(input.errorMessage);
11016
+ if (errorMessage !== void 0) details.errorMessage = errorMessage;
11017
+ const api = nonEmptyString(input.api);
11018
+ if (api !== void 0) details.api = api;
11019
+ const rawStopReason = nonEmptyString(input.rawStopReason);
11020
+ if (rawStopReason !== void 0) details.rawStopReason = rawStopReason;
11021
+ const testimony = hasUpstreamErrorTestimony(input);
11022
+ if (testimony) {
11023
+ const provider = nonEmptyString(input.provider);
11024
+ if (provider !== void 0) details.provider = provider;
11025
+ const model = nonEmptyString(input.model);
11026
+ if (model !== void 0) details.model = model;
11027
+ }
11028
+ if (typeof input.httpStatus === "number") details.httpStatus = input.httpStatus;
11029
+ if (input.diagnostics !== void 0) details.diagnostics = input.diagnostics;
11030
+ if (testimony) Object.assign(details, projectConfirmedRemotePayload(input));
11031
+ return details;
11032
+ }
11033
+ function knownFailureFromProviderStop(input) {
11034
+ if (input.stopReason !== "error" && input.stopReason !== "aborted") return void 0;
11035
+ const diagnostic = nonEmptyString(input.errorMessage);
11036
+ const details = sessionStopDetails(input);
11037
+ return {
11038
+ cause: hasUpstreamErrorTestimony(input) ? "provider" : "unrecognized",
11039
+ ...diagnostic === void 0 ? {} : { diagnostic },
11040
+ ...Object.keys(details).length === 0 ? {} : { details }
11041
+ };
11042
+ }
11043
+ var init_known_failure = __esm({
11044
+ "src/pi/known-failure.ts"() {
11045
+ "use strict";
11046
+ init_upstream_error_testimony();
11047
+ init_upstream_error_testimony();
11048
+ }
11049
+ });
11050
+
11051
+ // src/adr-path-refs.ts
11052
+ function extractReferencedAdrPaths(text) {
11053
+ const seen = /* @__PURE__ */ new Set();
11054
+ const paths = [];
11055
+ for (const match of text.matchAll(ADR_PATH_IN_BODY)) {
11056
+ const path = match[0];
11057
+ if (seen.has(path)) continue;
11058
+ seen.add(path);
11059
+ paths.push(path);
11060
+ }
11061
+ return Object.freeze(paths);
11062
+ }
11063
+ var ADR_PATH_IN_BODY;
11064
+ var init_adr_path_refs = __esm({
11065
+ "src/adr-path-refs.ts"() {
11066
+ "use strict";
11067
+ ADR_PATH_IN_BODY = /docs\/adr\/(?:[A-Za-z0-9][A-Za-z0-9._-]*\/)*[A-Za-z0-9][A-Za-z0-9._-]*\.md/g;
11068
+ }
11069
+ });
11070
+
11071
+ // src/reviewer-git-snapshot.ts
11072
+ function parseReviewerRefSnapshot(raw) {
11073
+ const refs = {};
11074
+ for (const line2 of raw.split("\n")) {
11075
+ if (!line2) continue;
11076
+ const fields = line2.split("\0");
11077
+ if (fields.length !== 5 || !fields[0] || !fields[1] || !fields[3]) {
11078
+ throw new Error(`Malformed Git ref snapshot line: ${line2}`);
11079
+ }
11080
+ const peeledCommitId = fields[3] === "commit" ? fields[1] : fields[4] === "commit" && fields[2] ? fields[2] : null;
11081
+ refs[fields[0]] = Object.freeze({
11082
+ objectId: fields[1],
11083
+ peeledCommitId
11084
+ });
11085
+ }
11086
+ return refs;
11087
+ }
11088
+ function reviewerRefSnapshotArgs() {
11089
+ return ["for-each-ref", "--format=%(refname)%00%(objectname)%00%(*objectname)%00%(objecttype)%00%(*objecttype)", ...REVIEW_REF_PREFIXES];
11090
+ }
11091
+ function immutableReviewerRefs(refs) {
11092
+ return Object.freeze(Object.fromEntries(Object.entries(refs).sort(([a], [b]) => a.localeCompare(b)).map(([name, entry]) => [name, Object.freeze({ objectId: entry.objectId, peeledCommitId: entry.peeledCommitId })])));
11093
+ }
11094
+ function sameReviewerPinnedTarget(actual, expected) {
11095
+ return actual.repositoryRoot === expected.repositoryRoot && actual.objectFormat === expected.objectFormat && actual.targetHead === expected.targetHead;
11096
+ }
11097
+ var REVIEW_REF_PREFIXES;
11098
+ var init_reviewer_git_snapshot = __esm({
11099
+ "src/reviewer-git-snapshot.ts"() {
11100
+ "use strict";
11101
+ REVIEW_REF_PREFIXES = ["refs/heads", "refs/tags", "refs/remotes"];
11102
+ }
11103
+ });
11104
+
11105
+ // src/reviewer-preflight-error.ts
11106
+ var ReviewerCorrectablePreflightError;
11107
+ var init_reviewer_preflight_error = __esm({
11108
+ "src/reviewer-preflight-error.ts"() {
11109
+ "use strict";
11110
+ ReviewerCorrectablePreflightError = class extends Error {
11111
+ constructor(code, diagnostic = `${code} constraint failed`, options) {
11112
+ super(`${code}: ${diagnostic}`, options);
11113
+ this.code = code;
11114
+ this.diagnostic = diagnostic;
11115
+ this.name = "ReviewerCorrectablePreflightError";
11116
+ }
11117
+ code;
11118
+ diagnostic;
11119
+ };
11120
+ }
11121
+ });
11122
+
11123
+ // src/reviewer-pinned-git.ts
11124
+ import { execFile as execFile3 } from "node:child_process";
11125
+ import { access as access3, realpath as realpath6 } from "node:fs/promises";
11126
+ import { promisify as promisify3 } from "node:util";
11127
+ async function execGit(args, options) {
11128
+ try {
11129
+ return await execFileAsync3("git", args, {
11130
+ ...options,
11131
+ env: { ...process.env, LC_ALL: "C" }
11132
+ });
11133
+ } catch (error) {
11134
+ const source = error;
11135
+ const wrapped = new Error("git process failed", { cause: error });
11136
+ Object.assign(wrapped, { code: source.code ?? null, signal: source.signal ?? null, timedOut: source.killed === true && source.signal === "SIGTERM", aborted: source.name === "AbortError", stderr: String(source.stderr ?? ""), stdout: String(source.stdout ?? "") });
11137
+ throw wrapped;
11138
+ }
11139
+ }
11140
+ function exitCode(error) {
11141
+ const code = typeof error === "object" && error !== null ? error.code : void 0;
11142
+ return typeof code === "number" ? code : void 0;
11143
+ }
11144
+ function gitStderr(error) {
11145
+ if (typeof error !== "object" || error === null) return "";
11146
+ const stderr = error.stderr;
11147
+ return typeof stderr === "string" ? stderr : "";
11148
+ }
11149
+ function isConfirmedMissingOriginRemote(error) {
11150
+ return /No such remote ['"]origin['"]/.test(gitStderr(error));
11151
+ }
11152
+ function isConfirmedPinnedPathAbsent(error, path) {
11153
+ const stderr = gitStderr(error);
11154
+ const quoted = `'${path}'`;
11155
+ return stderr.includes(`path ${quoted} does not exist in `) || stderr.includes(`path ${quoted} exists on disk, but not in `);
11156
+ }
11157
+ async function repositoryIsAvailable(root) {
11158
+ try {
11159
+ await access3(`${root}/.git`);
11160
+ return { available: true };
11161
+ } catch (cause) {
11162
+ return { available: false, cause };
11163
+ }
11164
+ }
11165
+ function shortNameFromPinnedRef(refName) {
11166
+ const short = refName.startsWith("refs/heads/") ? refName.slice("refs/heads/".length) : refName.startsWith("refs/tags/") ? refName.slice("refs/tags/".length) : refName.startsWith("refs/remotes/") ? refName.slice("refs/remotes/".length).replace(/^[^/]+\//, "") : refName;
11167
+ const trimmed = short.trim();
11168
+ return trimmed === "" ? void 0 : trimmed;
11169
+ }
11170
+ function branchNamesAtPinnedHead(pin) {
11171
+ const names = /* @__PURE__ */ new Set();
11172
+ for (const [refName, entry] of Object.entries(pin.refs)) {
11173
+ if (entry.peeledCommitId !== pin.targetHead) continue;
11174
+ if (!refName.startsWith("refs/heads/") && !refName.startsWith("refs/remotes/")) continue;
11175
+ const short = shortNameFromPinnedRef(refName);
11176
+ if (short !== void 0) names.add(short);
11680
11177
  }
11681
- });
11682
-
11683
- // src/upstream-error-testimony.ts
11684
- function isNonSuccessHttpStatus(status) {
11685
- return typeof status === "number" && (status < 200 || status >= 300);
11178
+ return Object.freeze([...names]);
11686
11179
  }
11687
- function hasUpstreamErrorTestimony(input) {
11688
- if (isNonSuccessHttpStatus(input.httpStatus)) return true;
11689
- return Array.isArray(input.diagnostics) && input.diagnostics.length > 0;
11180
+ async function gitText(root, args) {
11181
+ const { stdout } = await execGit(["-C", root, ...args], { encoding: "utf8" });
11182
+ return stdout.trim();
11690
11183
  }
11691
- function projectConfirmedRemotePayload(input) {
11692
- return {
11693
- ...input.body === void 0 ? {} : { body: input.body },
11694
- ...input.code === void 0 ? {} : { code: input.code },
11695
- ...input.errno === void 0 ? {} : { errno: input.errno }
11184
+ async function createReviewerPinnedGitReader(root = process.cwd()) {
11185
+ const discoveredRoot = await gitText(root, ["rev-parse", "--show-toplevel"]);
11186
+ const repositoryRoot = await realpath6(discoveredRoot);
11187
+ const objectFormat = await gitText(repositoryRoot, ["rev-parse", "--show-object-format"]);
11188
+ if (objectFormat !== "sha1" && objectFormat !== "sha256") throw new Error("Unsupported Git object format");
11189
+ const oidWidth = objectFormat === "sha1" ? 40 : 64;
11190
+ const targetHead = await gitText(repositoryRoot, ["rev-parse", "HEAD^{commit}"]);
11191
+ const reachableCommitIds = Object.freeze((await gitText(repositoryRoot, ["rev-list", targetHead])).split("\n").filter(Boolean));
11192
+ const refs = parseReviewerRefSnapshot(await gitText(repositoryRoot, reviewerRefSnapshotArgs()));
11193
+ const pin = immutableReviewerPin({ repositoryRoot, objectFormat, targetHead, refs });
11194
+ const invalid = (code, diagnostic, cause) => {
11195
+ throw new ReviewerCorrectablePreflightError(code, diagnostic, cause === void 0 ? void 0 : { cause });
11196
+ };
11197
+ const symbolic = (base) => {
11198
+ const selected = Object.hasOwn(refs, base) ? base : (() => {
11199
+ const candidates = [`refs/heads/${base}`, `refs/tags/${base}`, `refs/remotes/${base}`].filter((name) => Object.hasOwn(refs, name));
11200
+ if (candidates.length > 1) invalid("base-invalid", "base revision is ambiguous across pinned refs");
11201
+ return candidates[0];
11202
+ })();
11203
+ if (selected === void 0) return void 0;
11204
+ const commit = refs[selected]?.peeledCommitId;
11205
+ if (commit === null) invalid("base-invalid", "base revision ref must resolve to a commit");
11206
+ return commit ?? void 0;
11696
11207
  };
11208
+ return Object.freeze({
11209
+ pin,
11210
+ async snapshot() {
11211
+ const liveObjectFormat = await gitText(repositoryRoot, ["rev-parse", "--show-object-format"]);
11212
+ if (liveObjectFormat !== "sha1" && liveObjectFormat !== "sha256") throw new Error("Unsupported Git object format");
11213
+ return immutableReviewerPin({ repositoryRoot, objectFormat: liveObjectFormat, targetHead: await gitText(repositoryRoot, ["rev-parse", "HEAD^{commit}"]), refs: parseReviewerRefSnapshot(await gitText(repositoryRoot, reviewerRefSnapshotArgs())) });
11214
+ },
11215
+ async resolve(base) {
11216
+ if (!/^[A-Za-z0-9._/~^+-]+$/.test(base) || base.startsWith("-") || base.includes("..") || base.includes("@{")) {
11217
+ invalid("base-invalid", "base revision syntax is invalid or uses a forbidden revision form");
11218
+ }
11219
+ let commit;
11220
+ const headExpression = /^HEAD((?:~[0-9]+|\^[0-9]+)*)$/.exec(base);
11221
+ if (headExpression) {
11222
+ try {
11223
+ commit = await gitText(repositoryRoot, ["rev-parse", "--verify", `${targetHead}${headExpression[1]}^{commit}`]);
11224
+ } catch (error) {
11225
+ if (exitCode(error) === 128) {
11226
+ const repository = await repositoryIsAvailable(repositoryRoot);
11227
+ if (repository.available) invalid("base-invalid", "base revision HEAD ancestry expression must resolve to a reachable commit", error);
11228
+ }
11229
+ throw error;
11230
+ }
11231
+ } else if (new RegExp(`^[0-9a-f]{${oidWidth}}$`).test(base)) commit = base;
11232
+ else if (new RegExp(`^[0-9a-f]{4,${oidWidth - 1}}$`).test(base) && !(objectFormat === "sha256" && base.length === 40)) {
11233
+ const matches = reachableCommitIds.filter((candidate) => candidate.startsWith(base));
11234
+ if (matches.length !== 1) invalid("base-invalid", "base revision abbreviation must identify exactly one reachable commit");
11235
+ commit = matches[0];
11236
+ } else commit = symbolic(base);
11237
+ if (commit === void 0) invalid("base-invalid", "base revision must name an existing pinned ref or reachable commit");
11238
+ try {
11239
+ commit = await gitText(repositoryRoot, ["rev-parse", "--verify", `${commit}^{commit}`]);
11240
+ } catch (error) {
11241
+ if (exitCode(error) === 128) {
11242
+ const repository = await repositoryIsAvailable(repositoryRoot);
11243
+ if (repository.available) invalid("base-invalid", "base revision must resolve to an existing commit", error);
11244
+ }
11245
+ throw error;
11246
+ }
11247
+ try {
11248
+ await gitText(repositoryRoot, ["merge-base", "--is-ancestor", commit, targetHead]);
11249
+ } catch (error) {
11250
+ if (exitCode(error) === 1) invalid("base-invalid", "base revision must be an ancestor of the pinned target", error);
11251
+ throw error;
11252
+ }
11253
+ return commit;
11254
+ },
11255
+ async range(base) {
11256
+ let mergeBase;
11257
+ try {
11258
+ mergeBase = await gitText(repositoryRoot, ["merge-base", base, targetHead]);
11259
+ } catch (error) {
11260
+ if (exitCode(error) === 1) {
11261
+ invalid("range-invalid", "review range requires a common ancestor for base and pinned target", error);
11262
+ }
11263
+ throw error;
11264
+ }
11265
+ if (!mergeBase) invalid("range-invalid", "review range requires a common ancestor for base and pinned target");
11266
+ const diffCommand = `git diff ${mergeBase}...${targetHead}`;
11267
+ const [{ stdout: diff }, commitsText] = await Promise.all([
11268
+ execGit(["-C", repositoryRoot, "diff", `${mergeBase}...${targetHead}`], { encoding: "buffer", maxBuffer: 64 * 1024 * 1024 }),
11269
+ gitText(repositoryRoot, ["rev-list", "--reverse", `${mergeBase}..${targetHead}`])
11270
+ ]);
11271
+ if (diff.length === 0) invalid("range-invalid", "review range must contain a non-empty diff between base and pinned target");
11272
+ return Object.freeze({ base: mergeBase, target: targetHead, diffCommand, diffSha256: sha256Hex(Uint8Array.from(diff)), commits: Object.freeze(commitsText ? commitsText.split("\n") : []) });
11273
+ },
11274
+ async featureTokens() {
11275
+ const names = /* @__PURE__ */ new Set();
11276
+ for (const [refName, entry] of Object.entries(pin.refs)) {
11277
+ if (entry.peeledCommitId !== targetHead) continue;
11278
+ const short = shortNameFromPinnedRef(refName);
11279
+ if (short !== void 0) names.add(short);
11280
+ }
11281
+ return Object.freeze([...names]);
11282
+ },
11283
+ async listSpecCandidatePaths() {
11284
+ const roots = ["docs", "specs", ".scratch"];
11285
+ const text = await gitText(repositoryRoot, [
11286
+ "ls-tree",
11287
+ "-r",
11288
+ "--name-only",
11289
+ targetHead,
11290
+ "--",
11291
+ ...roots
11292
+ ]);
11293
+ return Object.freeze(text === "" ? [] : text.split("\n").filter((line2) => line2.length > 0));
11294
+ },
11295
+ async originRepository() {
11296
+ let remoteUrl;
11297
+ try {
11298
+ remoteUrl = await gitText(repositoryRoot, ["remote", "get-url", "origin"]);
11299
+ } catch (error) {
11300
+ if (isConfirmedMissingOriginRemote(error)) return void 0;
11301
+ throw error;
11302
+ }
11303
+ return parseGitHubOriginRemote(remoteUrl);
11304
+ },
11305
+ async commitMessagesNewestFirst(base) {
11306
+ const text = await gitText(repositoryRoot, [
11307
+ "log",
11308
+ "--format=%s",
11309
+ `${base}..${targetHead}`
11310
+ ]);
11311
+ return Object.freeze(text === "" ? [] : text.split("\n"));
11312
+ },
11313
+ async readPinnedText(path) {
11314
+ if (path.length === 0 || path.startsWith("/") || path.includes("\0") || path.split("/").some((part) => part === ".." || part === "")) {
11315
+ return void 0;
11316
+ }
11317
+ try {
11318
+ const { stdout } = await execGit(
11319
+ ["-C", repositoryRoot, "show", `${targetHead}:${path}`],
11320
+ { encoding: "utf8", maxBuffer: 8 * 1024 * 1024 }
11321
+ );
11322
+ return stdout;
11323
+ } catch (error) {
11324
+ if (isConfirmedPinnedPathAbsent(error, path)) return void 0;
11325
+ throw error;
11326
+ }
11327
+ }
11328
+ });
11697
11329
  }
11698
- var init_upstream_error_testimony = __esm({
11699
- "src/upstream-error-testimony.ts"() {
11700
- "use strict";
11330
+ function parseGitHubOriginRemote(remoteUrl) {
11331
+ const trimmed = remoteUrl.trim();
11332
+ if (trimmed.length === 0) return void 0;
11333
+ const scp = /^git@github\.com:([^/\s]+)\/([^/\s]+?)(?:\.git)?$/i.exec(trimmed);
11334
+ if (scp) return normalizeOrigin(scp[1], scp[2]);
11335
+ const ssh = /^ssh:\/\/git@github\.com\/([^/\s]+)\/([^/\s]+?)(?:\.git)?\/?$/i.exec(trimmed);
11336
+ if (ssh) return normalizeOrigin(ssh[1], ssh[2]);
11337
+ let parsed;
11338
+ try {
11339
+ parsed = new URL(trimmed);
11340
+ } catch {
11341
+ return void 0;
11701
11342
  }
11702
- });
11703
-
11704
- // src/pi/known-failure.ts
11705
- function nonEmptyString(value) {
11706
- return typeof value === "string" && value.trim() !== "" ? value : void 0;
11343
+ if (!/^github\.com$/i.test(parsed.hostname)) return void 0;
11344
+ if (parsed.search !== "" || parsed.hash !== "") return void 0;
11345
+ const parts = parsed.pathname.split("/").filter((p) => p.length > 0);
11346
+ if (parts.length !== 2) return void 0;
11347
+ return normalizeOrigin(parts[0], parts[1]);
11707
11348
  }
11708
- function sessionStopDetails(input) {
11709
- const details = {};
11710
- const errorMessage = nonEmptyString(input.errorMessage);
11711
- if (errorMessage !== void 0) details.errorMessage = errorMessage;
11712
- const api = nonEmptyString(input.api);
11713
- if (api !== void 0) details.api = api;
11714
- const rawStopReason = nonEmptyString(input.rawStopReason);
11715
- if (rawStopReason !== void 0) details.rawStopReason = rawStopReason;
11716
- const testimony = hasUpstreamErrorTestimony(input);
11717
- if (testimony) {
11718
- const provider = nonEmptyString(input.provider);
11719
- if (provider !== void 0) details.provider = provider;
11720
- const model = nonEmptyString(input.model);
11721
- if (model !== void 0) details.model = model;
11722
- }
11723
- if (typeof input.httpStatus === "number") details.httpStatus = input.httpStatus;
11724
- if (input.diagnostics !== void 0) details.diagnostics = input.diagnostics;
11725
- if (testimony) Object.assign(details, projectConfirmedRemotePayload(input));
11726
- return details;
11349
+ function normalizeOrigin(ownerRaw, repoRaw) {
11350
+ const owner = ownerRaw.trim();
11351
+ const repo = stripGitSuffix2(repoRaw.trim());
11352
+ if (owner.length === 0 || repo.length === 0) return void 0;
11353
+ if (/[/?#@\\]/.test(owner) || /[/?#@\\]/.test(repo)) return void 0;
11354
+ return Object.freeze({ owner, repo });
11727
11355
  }
11728
- function knownFailureFromProviderStop(input) {
11729
- if (input.stopReason !== "error" && input.stopReason !== "aborted") return void 0;
11730
- const diagnostic = nonEmptyString(input.errorMessage);
11731
- const details = sessionStopDetails(input);
11732
- return {
11733
- cause: hasUpstreamErrorTestimony(input) ? "provider" : "unrecognized",
11734
- ...diagnostic === void 0 ? {} : { diagnostic },
11735
- ...Object.keys(details).length === 0 ? {} : { details }
11736
- };
11356
+ function stripGitSuffix2(name) {
11357
+ return name.toLowerCase().endsWith(".git") ? name.slice(0, -4) : name;
11737
11358
  }
11738
- var init_known_failure = __esm({
11739
- "src/pi/known-failure.ts"() {
11359
+ var execFileAsync3, immutableReviewerPin;
11360
+ var init_reviewer_pinned_git = __esm({
11361
+ "src/reviewer-pinned-git.ts"() {
11740
11362
  "use strict";
11741
- init_upstream_error_testimony();
11742
- init_upstream_error_testimony();
11363
+ init_reviewer_git_snapshot();
11364
+ init_sha256();
11365
+ init_reviewer_preflight_error();
11366
+ execFileAsync3 = promisify3(execFile3);
11367
+ immutableReviewerPin = (pin) => Object.freeze({
11368
+ repositoryRoot: pin.repositoryRoot,
11369
+ objectFormat: pin.objectFormat,
11370
+ targetHead: pin.targetHead,
11371
+ refs: immutableReviewerRefs(pin.refs)
11372
+ });
11743
11373
  }
11744
11374
  });
11745
11375
 
@@ -12113,12 +11743,12 @@ var init_reviewer_dispatch = __esm({
12113
11743
  // src/public-cli/reviewer-dispatch-rejection.ts
12114
11744
  import { writeFileSync as writeFileSync4 } from "node:fs";
12115
11745
  import { readFile as readFile13, unlink as unlink3 } from "node:fs/promises";
12116
- import { join as join22 } from "node:path";
11746
+ import { join as join21 } from "node:path";
12117
11747
  function isReviewerPreflightViolation(value) {
12118
11748
  return typeof value === "string" && REVIEWER_PREFLIGHT_VIOLATIONS.includes(value);
12119
11749
  }
12120
11750
  function reviewerDispatchRejectionPath(runDirectory) {
12121
- return join22(runDirectory, REVIEWER_DISPATCH_REJECTION_FILE);
11751
+ return join21(runDirectory, REVIEWER_DISPATCH_REJECTION_FILE);
12122
11752
  }
12123
11753
  function recordReviewerDispatchRejectionSync(runDirectory, rejection) {
12124
11754
  writeFileSync4(
@@ -13284,7 +12914,7 @@ var init_collector_ledger = __esm({
13284
12914
  // src/package-resources/method-skill.ts
13285
12915
  import { createHash as createHash7 } from "node:crypto";
13286
12916
  import { readFile as readFile14, realpath as realpath7 } from "node:fs/promises";
13287
- import { join as join23 } from "node:path";
12917
+ import { join as join22 } from "node:path";
13288
12918
  function gitBlobOid(bytes) {
13289
12919
  const body = typeof bytes === "string" ? Buffer.from(bytes, "utf8") : Buffer.from(bytes);
13290
12920
  const header = Buffer.from(`blob ${body.byteLength}\0`, "utf8");
@@ -13301,10 +12931,10 @@ function packagedMethodSkillRelativeDirectory(name) {
13301
12931
  return `${METHOD_SKILL_RELATIVE_ROOT}/${name}`;
13302
12932
  }
13303
12933
  function resolvePackagedMethodSkillRoot(packageRoot, name) {
13304
- return join23(packageRoot, packagedMethodSkillRelativeDirectory(name));
12934
+ return join22(packageRoot, packagedMethodSkillRelativeDirectory(name));
13305
12935
  }
13306
12936
  function resolvePackagedMethodSkillPath(packageRoot, name) {
13307
- return join23(resolvePackagedMethodSkillRoot(packageRoot, name), "SKILL.md");
12937
+ return join22(resolvePackagedMethodSkillRoot(packageRoot, name), "SKILL.md");
13308
12938
  }
13309
12939
  function isRecord17(value) {
13310
12940
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -13398,8 +13028,8 @@ function parseProvenance(raw, expectedName) {
13398
13028
  }
13399
13029
  async function loadPackagedMethodSkillMaterial(packageRoot, name) {
13400
13030
  const rootDirectory = resolvePackagedMethodSkillRoot(packageRoot, name);
13401
- const skillPathConfigured = join23(rootDirectory, "SKILL.md");
13402
- const provenancePath = join23(rootDirectory, "provenance.json");
13031
+ const skillPathConfigured = join22(rootDirectory, "SKILL.md");
13032
+ const provenancePath = join22(rootDirectory, "provenance.json");
13403
13033
  let provenanceRaw;
13404
13034
  try {
13405
13035
  provenanceRaw = await readFile14(provenancePath, "utf8");
@@ -13416,7 +13046,7 @@ async function loadPackagedMethodSkillMaterial(packageRoot, name) {
13416
13046
  }
13417
13047
  const provenance = parseProvenance(provenanceJson, name);
13418
13048
  for (const [rel, expected] of Object.entries(provenance.files)) {
13419
- const absolute = join23(rootDirectory, rel);
13049
+ const absolute = join22(rootDirectory, rel);
13420
13050
  let bytes;
13421
13051
  try {
13422
13052
  bytes = await readFile14(absolute);
@@ -13932,7 +13562,7 @@ var init_terminal = __esm({
13932
13562
  // src/public-cli/settlement.ts
13933
13563
  import { randomUUID as randomUUID3 } from "node:crypto";
13934
13564
  import { appendFile as appendFile2, readFile as readFile15, readdir as readdir5, writeFile as writeFile6 } from "node:fs/promises";
13935
- import { dirname as dirname12, join as join24 } from "node:path";
13565
+ import { dirname as dirname12, join as join23 } from "node:path";
13936
13566
  function sealedLedgerHome(admitted) {
13937
13567
  return homeFromRunDirectory(admitted.runDirectory);
13938
13568
  }
@@ -14328,7 +13958,7 @@ async function readSessionProviderStop(sessionFile) {
14328
13958
  }
14329
13959
  }
14330
13960
  async function readBoundEvidenceChildKnownFailure(sessionFile) {
14331
- const childDirectory = join24(dirname12(sessionFile), "evidence-children");
13961
+ const childDirectory = join23(dirname12(sessionFile), "evidence-children");
14332
13962
  let names;
14333
13963
  try {
14334
13964
  names = await readdir5(childDirectory);
@@ -14339,7 +13969,7 @@ async function readBoundEvidenceChildKnownFailure(sessionFile) {
14339
13969
  for (const file of names.filter((name) => name.endsWith(".jsonl")).sort().reverse()) {
14340
13970
  let entries;
14341
13971
  try {
14342
- entries = await readBoundSessionEntries(join24(childDirectory, file));
13972
+ entries = await readBoundSessionEntries(join23(childDirectory, file));
14343
13973
  } catch (error) {
14344
13974
  throw sessionReadFailure(error, "failed to read discovered evidence-child session");
14345
13975
  }
@@ -14393,7 +14023,7 @@ async function loadBoundAuditorVolumes(sessionFile) {
14393
14023
  latestParentUserIndex = i;
14394
14024
  break;
14395
14025
  }
14396
- const childDirectories = [join24(dirname12(sessionFile), "auditor-roles")];
14026
+ const childDirectories = [join23(dirname12(sessionFile), "auditor-roles")];
14397
14027
  const valid = [];
14398
14028
  let sawAnyDirectory = false;
14399
14029
  for (const childDirectory of childDirectories) {
@@ -14408,7 +14038,7 @@ async function loadBoundAuditorVolumes(sessionFile) {
14408
14038
  for (const file of names.filter((name) => name.endsWith(".jsonl")).sort().reverse()) {
14409
14039
  let entries;
14410
14040
  try {
14411
- entries = await readBoundSessionEntries(join24(childDirectory, file));
14041
+ entries = await readBoundSessionEntries(join23(childDirectory, file));
14412
14042
  } catch (error) {
14413
14043
  throw sessionReadFailure(error, "failed to read discovered auditor session");
14414
14044
  }
@@ -14908,8 +14538,8 @@ function projectTerminalGateFact(rounds) {
14908
14538
  };
14909
14539
  }
14910
14540
  async function extractGateFactFromSessionDirectory(sessionDirectory, options = {}) {
14911
- const directories = [join24(sessionDirectory, "auditor-roles")];
14912
- const parentSessionFile = options.parentSessionFile ?? join24(sessionDirectory, "session.jsonl");
14541
+ const directories = [join23(sessionDirectory, "auditor-roles")];
14542
+ const parentSessionFile = options.parentSessionFile ?? join23(sessionDirectory, "session.jsonl");
14913
14543
  const rounds = await readAnalystGateCyclesFromAuditorRoles(directories, {
14914
14544
  parentSessionFile
14915
14545
  });
@@ -15007,8 +14637,8 @@ async function extractNavigatorFactFromAdmittedSession(sessionFile) {
15007
14637
  async function publishJudgeArtifacts(admitted, roleOutcome, coordinates) {
15008
14638
  await appendRunAttemptHistory({ role: admitted.role, runId: admitted.runId, sessionFile: coordinates.sessionFile }, roleOutcome);
15009
14639
  const artifactsDir = await ensureRunArtifactsDir(admitted.runDirectory);
15010
- const reportPath = join24(artifactsDir, "report.json");
15011
- const evidencePath = join24(artifactsDir, "evidence.json");
14640
+ const reportPath = join23(artifactsDir, "report.json");
14641
+ const evidencePath = join23(artifactsDir, "evidence.json");
15012
14642
  await writeFile6(
15013
14643
  reportPath,
15014
14644
  `${JSON.stringify(
@@ -15098,8 +14728,8 @@ async function trySettleJudgeTerminalResult(admitted, authority) {
15098
14728
  async function publishDoctorArtifacts(admitted, roleOutcome, coordinates, options = {}) {
15099
14729
  await appendRunAttemptHistory({ role: admitted.role, runId: admitted.runId, sessionFile: coordinates.sessionFile }, roleOutcome);
15100
14730
  const artifactsDir = await ensureRunArtifactsDir(admitted.runDirectory);
15101
- const reportPath = join24(artifactsDir, "report.json");
15102
- const evidencePath = join24(artifactsDir, "evidence.json");
14731
+ const reportPath = join23(artifactsDir, "report.json");
14732
+ const evidencePath = join23(artifactsDir, "evidence.json");
15103
14733
  await writeFile6(
15104
14734
  reportPath,
15105
14735
  `${JSON.stringify(
@@ -15332,7 +14962,7 @@ function uniqueFailureFallbackDirs(runDirectory, baseDir) {
15332
14962
  return dirs;
15333
14963
  }
15334
14964
  async function resolveFailureArtifactsBase(runDirectory) {
15335
- const artifactsDir = join24(runDirectory, "artifacts");
14965
+ const artifactsDir = join23(runDirectory, "artifacts");
15336
14966
  try {
15337
14967
  await ensureRunArtifactsDir(runDirectory);
15338
14968
  return { baseDir: artifactsDir };
@@ -15348,7 +14978,7 @@ async function writeFailureJsonRetainingCause(preferredCandidates, uniqueFallbac
15348
14978
  const candidates = [
15349
14979
  ...preferredCandidates,
15350
14980
  // One unique name per fallback dir — collisions on fixed names cannot exhaust this.
15351
- ...uniqueFallbackDirs.map((dir) => join24(dir, `${stem}.${randomUUID3()}.json`))
14981
+ ...uniqueFallbackDirs.map((dir) => join23(dir, `${stem}.${randomUUID3()}.json`))
15352
14982
  ];
15353
14983
  for (let i = 0; i < candidates.length; i += 1) {
15354
14984
  const path = candidates[i];
@@ -15393,26 +15023,26 @@ async function publishFailureArtifacts(admitted, failure2, authority) {
15393
15023
  } catch (error) {
15394
15024
  priorIssues.push(publicationAttemptFromError(sessionFile, error));
15395
15025
  }
15396
- const underArtifacts = baseDir === join24(admitted.runDirectory, "artifacts");
15026
+ const underArtifacts = baseDir === join23(admitted.runDirectory, "artifacts");
15397
15027
  const uniqueFallbackDirs = uniqueFailureFallbackDirs(
15398
15028
  admitted.runDirectory,
15399
15029
  baseDir
15400
15030
  );
15401
15031
  const errorCandidates = underArtifacts ? [
15402
- join24(baseDir, "error.json"),
15403
- join24(baseDir, "error.settlement.json"),
15404
- join24(admitted.runDirectory, "error.settlement.json")
15032
+ join23(baseDir, "error.json"),
15033
+ join23(baseDir, "error.settlement.json"),
15034
+ join23(admitted.runDirectory, "error.settlement.json")
15405
15035
  ] : [
15406
- join24(baseDir, "error.settlement.json"),
15407
- join24(baseDir, "error.json")
15036
+ join23(baseDir, "error.settlement.json"),
15037
+ join23(baseDir, "error.json")
15408
15038
  ];
15409
15039
  const evidenceCandidates = underArtifacts ? [
15410
- join24(baseDir, "evidence.json"),
15411
- join24(baseDir, "evidence.settlement.json"),
15412
- join24(admitted.runDirectory, "evidence.settlement.json")
15040
+ join23(baseDir, "evidence.json"),
15041
+ join23(baseDir, "evidence.settlement.json"),
15042
+ join23(admitted.runDirectory, "evidence.settlement.json")
15413
15043
  ] : [
15414
- join24(baseDir, "evidence.settlement.json"),
15415
- join24(baseDir, "evidence.json")
15044
+ join23(baseDir, "evidence.settlement.json"),
15045
+ join23(baseDir, "evidence.json")
15416
15046
  ];
15417
15047
  const errorPayloadBase = {
15418
15048
  kind: "error",
@@ -15683,7 +15313,7 @@ var init_settlement = __esm({
15683
15313
  import { constants as fsConstants } from "node:fs";
15684
15314
  import { randomUUID as randomUUID4 } from "node:crypto";
15685
15315
  import { lstat as lstat5, mkdir as mkdir4, open as open2 } from "node:fs/promises";
15686
- import { join as join25 } from "node:path";
15316
+ import { join as join24 } from "node:path";
15687
15317
  function presentTerminal(terminal, io) {
15688
15318
  if (terminal.roleOutcome.kind === "failure" || terminal.roleOutcome.kind === "no_receipt") {
15689
15319
  presentFailureTerminal(terminal, io);
@@ -15702,7 +15332,7 @@ async function finalizeExceptionRunBestEffort(runDirectory, io) {
15702
15332
  }
15703
15333
  }
15704
15334
  function runArtifactsDirectory(runDirectory) {
15705
- return join25(runDirectory, "artifacts");
15335
+ return join24(runDirectory, "artifacts");
15706
15336
  }
15707
15337
  async function ensureRealArtifactsDirectory(runDirectory) {
15708
15338
  const runStat = await lstat5(runDirectory);
@@ -15785,7 +15415,7 @@ function jsonSafeReplacer() {
15785
15415
  }
15786
15416
  async function retainDispatchError(admitted, principalAuthority, sessionAppender, attempt, error) {
15787
15417
  const artifactsDir = await ensureRealArtifactsDirectory(admitted.runDirectory);
15788
- const filePath = join25(
15418
+ const filePath = join24(
15789
15419
  artifactsDir,
15790
15420
  `dispatch-error-attempt-${attempt}-${randomUUID4()}.json`
15791
15421
  );
@@ -16034,10 +15664,16 @@ var init_auto_resume = __esm({
16034
15664
  // src/public-cli/post-admission.ts
16035
15665
  import { randomUUID as randomUUID5 } from "node:crypto";
16036
15666
  import { readFile as readFile16, writeFile as writeFile7 } from "node:fs/promises";
16037
- import { isAbsolute as isAbsolute7, join as join26, resolve as resolve12 } from "node:path";
15667
+ import { isAbsolute as isAbsolute7, join as join25, resolve as resolve12 } from "node:path";
15668
+ function appendContinuationSection(continuation, section) {
15669
+ const prompt = `${continuation.prompt}
15670
+
15671
+ ${section}`;
15672
+ return continuation.kind === "initial" ? { kind: "initial", prompt } : { kind: "resume", prompt };
15673
+ }
16038
15674
  async function readInvocationHost(runDirectory) {
16039
15675
  try {
16040
- const raw = JSON.parse(await readFile16(join26(runDirectory, "invocation.json"), "utf8"));
15676
+ const raw = JSON.parse(await readFile16(join25(runDirectory, "invocation.json"), "utf8"));
16041
15677
  return typeof raw.host === "string" && raw.host.trim() !== "" ? raw.host : void 0;
16042
15678
  } catch (error) {
16043
15679
  if (error.code === "ENOENT") return void 0;
@@ -16112,18 +15748,14 @@ async function dispatchPostAdmissionTurn(input) {
16112
15748
  let previousHost;
16113
15749
  const liveHost = env.host;
16114
15750
  const principalCoordinates = admitted.principal === void 0 ? void 0 : env.principalAuthority.decode(admitted.principal);
16115
- let turnRequest;
15751
+ let hostTransition;
16116
15752
  try {
16117
15753
  previousHost = await readInvocationHost(admitted.runDirectory);
16118
- const hostTransition = previousHost !== void 0 && liveHost !== void 0 && principalCoordinates !== void 0 ? await projectHostTransitionPriorNative({
15754
+ hostTransition = previousHost !== void 0 && liveHost !== void 0 && principalCoordinates !== void 0 ? await projectHostTransitionPriorNative({
16119
15755
  previousHost,
16120
15756
  liveHost,
16121
15757
  piSessionFile: principalCoordinates.sessionFile
16122
15758
  }) : void 0;
16123
- turnRequest = env.signal === void 0 ? request : { ...request, signal: env.signal };
16124
- if (hostTransition !== void 0) {
16125
- turnRequest = { ...turnRequest, hostTransition };
16126
- }
16127
15759
  } catch (error) {
16128
15760
  return await presentControlledFailure(
16129
15761
  admitted,
@@ -16158,6 +15790,24 @@ async function dispatchPostAdmissionTurn(input) {
16158
15790
  );
16159
15791
  }
16160
15792
  }
15793
+ let turnRequest = env.signal === void 0 ? request : { ...request, signal: env.signal };
15794
+ if (hostTransition !== void 0) {
15795
+ turnRequest = { ...turnRequest, hostTransition };
15796
+ }
15797
+ const dossierSection = await projectCaseDossierPointerSection({
15798
+ ticketNumber: admitted.ticketNumber,
15799
+ projectRoot: admitted.projectRoot,
15800
+ home: env.home
15801
+ });
15802
+ if (dossierSection !== void 0) {
15803
+ turnRequest = {
15804
+ ...turnRequest,
15805
+ continuation: appendContinuationSection(
15806
+ turnRequest.continuation,
15807
+ dossierSection
15808
+ )
15809
+ };
15810
+ }
16161
15811
  let result;
16162
15812
  try {
16163
15813
  result = await env.roleTurnHost.executeTurn(turnRequest);
@@ -16177,7 +15827,7 @@ async function dispatchPostAdmissionTurn(input) {
16177
15827
  }
16178
15828
  try {
16179
15829
  await writeFile7(
16180
- join26(admitted.runDirectory, "stderr.log"),
15830
+ join25(admitted.runDirectory, "stderr.log"),
16181
15831
  result.stderr,
16182
15832
  "utf8"
16183
15833
  );
@@ -16243,16 +15893,24 @@ async function dispatchPostAdmissionTurn(input) {
16243
15893
  }
16244
15894
  }
16245
15895
  function resumeTurnRequestProjectionOptions(admitted, request, env, summonsPrepared) {
15896
+ const engineMaterial = engineSessionMaterialFromOptions({
15897
+ ...env.engine === void 0 ? {} : { engine: env.engine },
15898
+ packageRoot: env.packageRoot
15899
+ });
16246
15900
  let prompt;
16247
15901
  if (request.message !== void 0) {
16248
- if (summonsPrepared !== void 0) {
16249
- prompt = buildInstructionTransportPrompt({
16250
- instruction: request.message,
16251
- instructionEmpty: false,
16252
- attachments: summonsPrepared.attachments
16253
- });
16254
- } else if (request.summons !== void 0) {
16255
- prompt = request.message;
15902
+ if (summonsPrepared !== void 0 && summonsPrepared.attachments.length > 0) {
15903
+ prompt = instructResumeHandbookRead(
15904
+ buildInstructionTransportPrompt(
15905
+ {
15906
+ instruction: request.message,
15907
+ instructionEmpty: false,
15908
+ attachments: summonsPrepared.attachments
15909
+ },
15910
+ engineMaterial
15911
+ ),
15912
+ engineMaterial
15913
+ );
16256
15914
  } else {
16257
15915
  prompt = buildResumeContinuationPrompt({
16258
15916
  packageRoot: env.packageRoot,
@@ -16261,9 +15919,10 @@ function resumeTurnRequestProjectionOptions(admitted, request, env, summonsPrepa
16261
15919
  });
16262
15920
  }
16263
15921
  } else if (summonsPrepared !== void 0) {
16264
- prompt = buildInstructionTransportPrompt(summonsPrepared);
16265
- } else if (request.summons !== void 0) {
16266
- prompt = RESUME_TRANSPORT_ENVELOPE;
15922
+ prompt = instructResumeHandbookRead(
15923
+ buildInstructionTransportPrompt(summonsPrepared, engineMaterial),
15924
+ engineMaterial
15925
+ );
16267
15926
  } else {
16268
15927
  prompt = buildResumeContinuationPrompt({
16269
15928
  packageRoot: env.packageRoot,
@@ -16286,7 +15945,7 @@ function resumeTurnRequestProjectionOptions(admitted, request, env, summonsPrepa
16286
15945
  }
16287
15946
  function isAlreadyFrozenSummonsAttachment(runDirectory, attachmentPath) {
16288
15947
  const absolute = isAbsolute7(attachmentPath) ? attachmentPath : resolve12(attachmentPath);
16289
- return pathContainedIn(join26(runDirectory, "attachments"), absolute);
15948
+ return pathContainedIn(join25(runDirectory, "attachments"), absolute);
16290
15949
  }
16291
15950
  async function prepareSummonsResumeMaterials(runDirectory, summons) {
16292
15951
  if (summons === void 0) return void 0;
@@ -16578,6 +16237,8 @@ var init_post_admission = __esm({
16578
16237
  init_cli_errors();
16579
16238
  init_invocation();
16580
16239
  init_activation_ledger_topology();
16240
+ init_engine_material();
16241
+ init_case_dossier_delivery();
16581
16242
  init_host_transition_prior_native();
16582
16243
  init_public_run_credentials();
16583
16244
  init_run_lifecycle();
@@ -16622,6 +16283,7 @@ __export(notary_run_exports, {
16622
16283
  runPublicNotary: () => runPublicNotary,
16623
16284
  runPublicNotaryResume: () => runPublicNotaryResume
16624
16285
  });
16286
+ import { existsSync as existsSync9 } from "node:fs";
16625
16287
  function buildNotaryTurnRequest(admitted, options) {
16626
16288
  return projectRoleTurnRequest(
16627
16289
  admitted,
@@ -16763,14 +16425,19 @@ async function runPublicNotaryResume(request, env, io) {
16763
16425
  }
16764
16426
  return loaded;
16765
16427
  },
16766
- buildTurnRequest: (admitted, effective) => (
16767
- // #755: review continuation is plain dialogue / resume envelope — no
16768
- //「重新读」candidate line, no engine handbook packaging.
16769
- buildNotaryTurnRequest(
16428
+ buildTurnRequest: (admitted, effective) => {
16429
+ const projection = resumeTurnRequestProjectionOptions(
16770
16430
  admitted,
16771
- resumeTurnRequestProjectionOptions(admitted, effective, env)
16772
- )
16773
- ),
16431
+ effective,
16432
+ env
16433
+ );
16434
+ const candidatePath = gateSubmissionCandidatePath(admitted.sourceRunPath);
16435
+ const prompt = existsSync9(candidatePath) ? appendResumeMaterialReread(projection.continuation.prompt, candidatePath) : projection.continuation.prompt;
16436
+ return buildNotaryTurnRequest(admitted, {
16437
+ ...projection,
16438
+ continuation: { kind: "resume", prompt }
16439
+ });
16440
+ },
16774
16441
  adapters: notaryAdapters(),
16775
16442
  ...env.engine === void 0 ? {} : { effectiveEngine: env.engine }
16776
16443
  });
@@ -16778,6 +16445,7 @@ async function runPublicNotaryResume(request, env, io) {
16778
16445
  var init_notary_run = __esm({
16779
16446
  "src/public-cli/notary-run.ts"() {
16780
16447
  "use strict";
16448
+ init_auditor_dossier_tool();
16781
16449
  init_notary_source_run();
16782
16450
  init_engine_material();
16783
16451
  init_cli_errors();
@@ -16820,11 +16488,11 @@ async function runPublicInspector(argv, env, io, parseInspectorArgv2) {
16820
16488
  throw error;
16821
16489
  }
16822
16490
  const projectRoot = parsed.project ?? env.cwd;
16823
- const ticketProbe = await probeInstructionTicket(
16824
- parsed.instruction,
16491
+ const reusedTicketNumber = await resolveKnownTicketNumber({
16492
+ instruction: parsed.instruction,
16825
16493
  projectRoot,
16826
- env
16827
- );
16494
+ home: env.home
16495
+ });
16828
16496
  const parentRunPath = parentRunPathFromGatePointerInstruction(parsed.instruction);
16829
16497
  if (parentRunPath !== void 0) {
16830
16498
  const summons = {
@@ -16892,7 +16560,7 @@ async function runPublicInspector(argv, env, io, parseInspectorArgv2) {
16892
16560
  request: turnRequest,
16893
16561
  adapters: inspectorAdapters({
16894
16562
  beforeDispatch: async (admittedSeat) => {
16895
- await applyInstructionTicketProbe(admittedSeat, ticketProbe);
16563
+ await bindReusedTicketNumber(admittedSeat, reusedTicketNumber);
16896
16564
  }
16897
16565
  }),
16898
16566
  ...env.engine === void 0 ? {} : { effectiveEngine: env.engine }
@@ -17075,7 +16743,7 @@ async function runPublicInstructionSeat(argv, env, io, role, parseArgv) {
17075
16743
  let auditorSubject;
17076
16744
  let auditorSourceRun;
17077
16745
  let auditorSourceTicket;
17078
- let ticketProbe;
16746
+ let reusedTicketNumber;
17079
16747
  const projectRoot = parsed.project ?? env.cwd;
17080
16748
  if (role === "auditor") {
17081
16749
  if (parsed.subject !== "judge" && parsed.subject !== "doctor") {
@@ -17111,11 +16779,11 @@ async function runPublicInstructionSeat(argv, env, io, role, parseArgv) {
17111
16779
  return { exitCode: 2 };
17112
16780
  }
17113
16781
  } else {
17114
- ticketProbe = await probeInstructionTicket(
17115
- parsed.instruction,
16782
+ reusedTicketNumber = await resolveKnownTicketNumber({
16783
+ instruction: parsed.instruction,
17116
16784
  projectRoot,
17117
- env
17118
- );
16785
+ home: env.home
16786
+ });
17119
16787
  }
17120
16788
  const summons = {
17121
16789
  instruction: parsed.instruction,
@@ -17141,24 +16809,21 @@ async function runPublicInstructionSeat(argv, env, io, role, parseArgv) {
17141
16809
  })
17142
16810
  });
17143
16811
  if (resumed !== void 0) return resumed;
17144
- } else {
17145
- const probedTicketNumber = ticketProbe === void 0 ? void 0 : ticketNumberFromProbe(ticketProbe);
17146
- if (probedTicketNumber !== void 0) {
17147
- const resumed = await tryResumeSameTicketSeatRun({
17148
- home: env.home,
17149
- projectRoot,
17150
- role,
17151
- ticketNumber: probedTicketNumber,
17152
- freshSummons: env.freshSummons,
17153
- summons,
17154
- resume: (runId, materials) => runPublicInstructionSeatResume(
17155
- { runId, ...materials === void 0 ? {} : { summons: materials } },
17156
- env,
17157
- io
17158
- )
17159
- });
17160
- if (resumed !== void 0) return resumed;
17161
- }
16812
+ } else if (reusedTicketNumber !== void 0) {
16813
+ const resumed = await tryResumeSameTicketSeatRun({
16814
+ home: env.home,
16815
+ projectRoot,
16816
+ role,
16817
+ ticketNumber: reusedTicketNumber,
16818
+ freshSummons: env.freshSummons,
16819
+ summons,
16820
+ resume: (runId, materials) => runPublicInstructionSeatResume(
16821
+ { runId, ...materials === void 0 ? {} : { summons: materials } },
16822
+ env,
16823
+ io
16824
+ )
16825
+ });
16826
+ if (resumed !== void 0) return resumed;
17162
16827
  }
17163
16828
  let admitted;
17164
16829
  try {
@@ -17216,8 +16881,8 @@ async function runPublicInstructionSeat(argv, env, io, role, parseArgv) {
17216
16881
  beforeDispatch: async (admittedSeat) => {
17217
16882
  if (auditorSourceTicket !== void 0) {
17218
16883
  await bindAdmittedTicketNumber(admittedSeat, auditorSourceTicket);
17219
- } else if (ticketProbe !== void 0) {
17220
- await applyInstructionTicketProbe(admittedSeat, ticketProbe);
16884
+ } else {
16885
+ await bindReusedTicketNumber(admittedSeat, reusedTicketNumber);
17221
16886
  }
17222
16887
  }
17223
16888
  }),
@@ -17470,8 +17135,8 @@ __export(public_role_summons_exports, {
17470
17135
  summonGateOfficer: () => summonGateOfficer,
17471
17136
  summonPublicRole: () => summonPublicRole
17472
17137
  });
17473
- import { existsSync as existsSync9 } from "node:fs";
17474
- import { join as join27 } from "node:path";
17138
+ import { existsSync as existsSync10 } from "node:fs";
17139
+ import { join as join26 } from "node:path";
17475
17140
  function createCapturingIo() {
17476
17141
  const chunks = [];
17477
17142
  return {
@@ -17494,7 +17159,7 @@ function parentDir(path) {
17494
17159
  function walkPackageRoot(start) {
17495
17160
  let dir = start;
17496
17161
  for (let i = 0; i < 12; i += 1) {
17497
- if (existsSync9(join27(dir, "package.json")) && existsSync9(join27(dir, "souls"))) {
17162
+ if (existsSync10(join26(dir, "package.json")) && existsSync10(join26(dir, "souls"))) {
17498
17163
  return dir;
17499
17164
  }
17500
17165
  const parent = parentDir(dir);
@@ -17610,7 +17275,7 @@ async function createSummonEnv(options) {
17610
17275
  async function summonPublicRole(options) {
17611
17276
  const packageRoot = resolveSummonsPackageRoot(options.packageRoot);
17612
17277
  const home = await resolveSummonHome(options);
17613
- const agentDir = options.agentDir ?? process.env.PI_CODING_AGENT_DIR ?? join27(home, ".pi", "agent");
17278
+ const agentDir = options.agentDir ?? process.env.PI_CODING_AGENT_DIR ?? join26(home, ".pi", "agent");
17614
17279
  const {
17615
17280
  loadCredentialProviders: loadCredentialProviders2,
17616
17281
  loadPublicCliConfig: loadPublicCliConfig2,
@@ -18076,11 +17741,11 @@ var init_navigator_session_contracts = __esm({
18076
17741
 
18077
17742
  // src/archivist-record-topology.ts
18078
17743
  import { createHash as createHash8 } from "node:crypto";
18079
- import { join as join28 } from "node:path";
17744
+ import { join as join27 } from "node:path";
18080
17745
  function subjectKeyedRecordDirectory(input) {
18081
17746
  const ledgerHome = input.parentSessionFile !== void 0 && input.parentSessionFile.length > 0 ? resolveActivationLedgerHomeForPath(input.parentSessionFile) : resolveActivationLedgerHome(input.home);
18082
17747
  const digest = createHash8("sha256").update(input.subject).digest("hex").slice(0, 32);
18083
- return join28(
17748
+ return join27(
18084
17749
  activationBookDirectory(ledgerHome, resolveBookKeyFromGit(input.cwd)),
18085
17750
  input.kind,
18086
17751
  digest
@@ -18104,13 +17769,13 @@ __export(archivist_record_entry_exports, {
18104
17769
  createRecordSessionOpen: () => createRecordSessionOpen,
18105
17770
  subjectKeyedRecordDirectory: () => subjectKeyedRecordDirectory
18106
17771
  });
18107
- import { existsSync as existsSync10, mkdirSync as mkdirSync4, readFileSync as readFileSync5, realpathSync as realpathSync2, writeFileSync as writeFileSync5 } from "node:fs";
18108
- import { dirname as dirname13, resolve as resolve13, join as join29 } from "node:path";
17772
+ import { existsSync as existsSync11, mkdirSync as mkdirSync4, readFileSync as readFileSync3, realpathSync as realpathSync2, writeFileSync as writeFileSync5 } from "node:fs";
17773
+ import { dirname as dirname13, resolve as resolve13, join as join28 } from "node:path";
18109
17774
  import { SessionManager } from "@earendil-works/pi-coding-agent";
18110
17775
  function readCurrentSession(sessionDir) {
18111
- const ledger = join29(sessionDir, CURRENT_SESSION_LEDGER);
17776
+ const ledger = join28(sessionDir, CURRENT_SESSION_LEDGER);
18112
17777
  try {
18113
- const value = JSON.parse(readFileSync5(ledger, "utf8"));
17778
+ const value = JSON.parse(readFileSync3(ledger, "utf8"));
18114
17779
  if (typeof value !== "object" || value === null || typeof value.sessionFile !== "string" || value.sessionFile.length === 0) {
18115
17780
  throw new Error("sessionFile is missing");
18116
17781
  }
@@ -18123,7 +17788,7 @@ function readCurrentSession(sessionDir) {
18123
17788
  }
18124
17789
  }
18125
17790
  function writeCurrentSession(sessionDir, sessionFile) {
18126
- const ledger = join29(sessionDir, CURRENT_SESSION_LEDGER);
17791
+ const ledger = join28(sessionDir, CURRENT_SESSION_LEDGER);
18127
17792
  try {
18128
17793
  writeFileSync5(ledger, `${JSON.stringify({ sessionFile })}
18129
17794
  `, { flag: "wx" });
@@ -18184,10 +17849,10 @@ function createRecordSessionOpen(options) {
18184
17849
  return { session: SessionManager.inMemory(cwd), resumed: false };
18185
17850
  } else {
18186
17851
  const parentResolved = resolve13(parentFile);
18187
- sessionDir = physicallyContainedIn(ledgerHome, parentResolved) ? join29(dirname13(parentResolved), options.kind) : join29(activationBookDirectory(ledgerHome, resolveBookKeyFromGit(cwd)), options.kind);
17852
+ sessionDir = physicallyContainedIn(ledgerHome, parentResolved) ? join28(dirname13(parentResolved), options.kind) : join28(activationBookDirectory(ledgerHome, resolveBookKeyFromGit(cwd)), options.kind);
18188
17853
  parentSession = parentFile;
18189
17854
  }
18190
- const nestAlreadyExists = existsSync10(sessionDir);
17855
+ const nestAlreadyExists = existsSync11(sessionDir);
18191
17856
  ensureRealDirectoryTree(ledgerHome, sessionDir);
18192
17857
  const mayResumeSameNest = options.subject !== void 0 || options.kind === WORKER_SUBMISSION_GATE_KIND;
18193
17858
  if (mayResumeSameNest && nestAlreadyExists) {
@@ -18205,7 +17870,7 @@ function createRecordSessionOpen(options) {
18205
17870
  );
18206
17871
  if (session.isPersisted()) {
18207
17872
  const file = session.getSessionFile();
18208
- if (file !== void 0 && !existsSync10(file)) {
17873
+ if (file !== void 0 && !existsSync11(file)) {
18209
17874
  const header = session.getHeader();
18210
17875
  if (header !== null && header.type === "session") {
18211
17876
  writeFileSync5(file, `${JSON.stringify(header)}
@@ -18223,7 +17888,7 @@ function createRecordSession(options) {
18223
17888
  return createRecordSessionOpen(options).session;
18224
17889
  }
18225
17890
  function bookDirectOfficerRunPointer(options) {
18226
- const nest = join29(dirname13(options.parentSessionFile), "auditor-roles");
17891
+ const nest = join28(dirname13(options.parentSessionFile), "auditor-roles");
18227
17892
  mkdirSync4(nest, { recursive: true });
18228
17893
  const pointer = {
18229
17894
  version: 1,
@@ -18233,7 +17898,7 @@ function bookDirectOfficerRunPointer(options) {
18233
17898
  ...options.runDirectory !== void 0 && options.runDirectory.trim() !== "" ? { runDirectory: options.runDirectory } : {}
18234
17899
  };
18235
17900
  writeFileSync5(
18236
- join29(nest, `${options.officer}-${Date.now().toString(36)}.pointer.json`),
17901
+ join28(nest, `${options.officer}-${Date.now().toString(36)}.pointer.json`),
18237
17902
  `${JSON.stringify(pointer)}
18238
17903
  `,
18239
17904
  "utf8"
@@ -20810,6 +20475,185 @@ var init_diarist_role = __esm({
20810
20475
  }
20811
20476
  });
20812
20477
 
20478
+ // src/diarist-mechanical.ts
20479
+ function extractCornerQuotes(text, minLength = DEFAULT_QUOTE_MIN) {
20480
+ const out = [];
20481
+ const re = /「([^」]+)」/g;
20482
+ let match;
20483
+ while ((match = re.exec(text)) !== null) {
20484
+ const q = match[1].trim();
20485
+ if (q.length >= minLength) out.push(q);
20486
+ }
20487
+ return out;
20488
+ }
20489
+ function buildDiaristAnchors(input) {
20490
+ const fromBody = input.ticketBody === void 0 ? [] : extractCornerQuotes(input.ticketBody);
20491
+ const quotes = [...fromBody, ...input.extraQuotes ?? []];
20492
+ const seen = /* @__PURE__ */ new Set();
20493
+ const uniqueQuotes = [];
20494
+ for (const q of quotes) {
20495
+ if (seen.has(q)) continue;
20496
+ seen.add(q);
20497
+ uniqueQuotes.push(q);
20498
+ }
20499
+ return {
20500
+ ticketNumber: input.ticketNumber,
20501
+ quotes: uniqueQuotes
20502
+ };
20503
+ }
20504
+ function verifyQuotesVerbatim(sourceText, quotes) {
20505
+ const failed2 = [];
20506
+ for (const q of quotes) {
20507
+ if (q.length === 0) continue;
20508
+ if (!sourceText.includes(q)) failed2.push(q);
20509
+ }
20510
+ if (failed2.length === 0) return { ok: true };
20511
+ return { ok: false, failedQuotes: failed2 };
20512
+ }
20513
+ function blockToLlmEntry(block, input) {
20514
+ const verify = verifyQuotesVerbatim(block.transcript, input.quotes);
20515
+ if (!verify.ok) {
20516
+ return {
20517
+ ok: false,
20518
+ failedQuotes: verify.failedQuotes,
20519
+ cause: `verbatim verify failed: ${verify.failedQuotes.join(" | ")}`
20520
+ };
20521
+ }
20522
+ const anchorNotes = [`#${input.anchors.ticketNumber}`];
20523
+ const seen = new Set(anchorNotes);
20524
+ for (const q of [...input.anchors.quotes, ...input.quotes]) {
20525
+ if (seen.has(q)) continue;
20526
+ seen.add(q);
20527
+ anchorNotes.push(q);
20528
+ if (anchorNotes.length >= 12) break;
20529
+ }
20530
+ return {
20531
+ ok: true,
20532
+ entry: {
20533
+ basis: {
20534
+ method: "llm-semantic",
20535
+ anchors: anchorNotes,
20536
+ ...input.note === void 0 ? {} : { note: input.note }
20537
+ },
20538
+ sourceKind: block.sourceKind,
20539
+ sourceRef: block.sourceRef,
20540
+ transcript: block.transcript,
20541
+ timestamp: block.timestamp
20542
+ }
20543
+ };
20544
+ }
20545
+ var DEFAULT_QUOTE_MIN;
20546
+ var init_diarist_mechanical = __esm({
20547
+ "src/diarist-mechanical.ts"() {
20548
+ "use strict";
20549
+ init_activation_ledger_topology();
20550
+ DEFAULT_QUOTE_MIN = 6;
20551
+ }
20552
+ });
20553
+
20554
+ // src/diarist.ts
20555
+ import { readFileSync as readFileSync4 } from "node:fs";
20556
+ function blockEntryIdentity(ticketNumber, block) {
20557
+ return ticketProvenanceEntryIdentity({
20558
+ ticketNumber,
20559
+ sourceKind: block.sourceKind,
20560
+ sourceRef: block.sourceRef,
20561
+ transcript: block.transcript
20562
+ });
20563
+ }
20564
+ function loadDiaristSourceCatalog(path) {
20565
+ const parsed = JSON.parse(readFileSync4(path, "utf8"));
20566
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
20567
+ throw new Error(`diarist source catalog is not an object (${path})`);
20568
+ }
20569
+ const record4 = parsed;
20570
+ if (typeof record4.ticketNumber !== "number" || typeof record4.cwd !== "string") {
20571
+ throw new Error(`diarist source catalog is missing ticket coordinates (${path})`);
20572
+ }
20573
+ if (!Array.isArray(record4.candidates)) {
20574
+ throw new Error(`diarist source catalog is missing candidates (${path})`);
20575
+ }
20576
+ return parsed;
20577
+ }
20578
+ async function commitDiaristSelections(input) {
20579
+ const { ticketNumber, cwd } = input.catalog;
20580
+ const homeOpt = input.catalog.home === void 0 ? {} : { home: input.catalog.home };
20581
+ const volumePaths = ensureTicketProvenanceVolume(ticketNumber, cwd, input.catalog.home);
20582
+ const anchors = buildDiaristAnchors({ ticketNumber });
20583
+ const before = await readTicketProvenance(ticketNumber, cwd, input.catalog.home);
20584
+ let acceptedRows = 0;
20585
+ let rejectedQuotes = 0;
20586
+ let unknownCandidate = false;
20587
+ for (const selection of input.selections) {
20588
+ const block = input.catalog.candidates[selection.candidateIndex];
20589
+ if (block === void 0) {
20590
+ unknownCandidate = true;
20591
+ continue;
20592
+ }
20593
+ const projected = blockToLlmEntry(block, {
20594
+ anchors,
20595
+ quotes: selection.quotes,
20596
+ ...selection.note === void 0 ? {} : { note: selection.note }
20597
+ });
20598
+ if (!projected.ok) {
20599
+ rejectedQuotes += 1;
20600
+ appendQuoteVerifyFailureDiagnostic({
20601
+ ticketNumber,
20602
+ cwd,
20603
+ ...homeOpt,
20604
+ cause: projected.cause
20605
+ });
20606
+ continue;
20607
+ }
20608
+ appendTicketProvenanceEntry({
20609
+ ticketNumber,
20610
+ cwd,
20611
+ ...homeOpt,
20612
+ entry: projected.entry,
20613
+ source: "diarist"
20614
+ });
20615
+ acceptedRows += 1;
20616
+ }
20617
+ const identities = input.catalog.candidates.map(
20618
+ (block) => blockEntryIdentity(ticketNumber, block)
20619
+ );
20620
+ const alreadyWatermarked = readOfferedIdentities(ticketNumber, cwd, input.catalog.home);
20621
+ const watermarked = identities.filter((identity) => !alreadyWatermarked.has(identity)).length;
20622
+ recordOfferedIdentities({ ticketNumber, cwd, ...homeOpt, identities });
20623
+ const volume = await readTicketProvenance(ticketNumber, cwd, input.catalog.home);
20624
+ const humanViewFile = writeTicketProvenanceHumanView({
20625
+ ticketNumber,
20626
+ cwd,
20627
+ ...homeOpt,
20628
+ entries: volume.entries
20629
+ });
20630
+ return {
20631
+ ticketNumber,
20632
+ offered: input.catalog.candidates.length,
20633
+ appended: volume.entries.length - before.entries.length,
20634
+ rejectedQuotes,
20635
+ watermarked,
20636
+ volumeRecordFile: volumePaths.recordFile,
20637
+ humanViewFile,
20638
+ collectorStatus: input.catalog.candidates.length === 0 ? "skipped-no-fresh" : acceptedRows > 0 ? "ok" : input.selections.length === 0 ? "empty-selection" : "nothing-appended",
20639
+ failureCauses: [
20640
+ ...unknownCandidate ? ["unknown-candidate"] : [],
20641
+ ...rejectedQuotes > 0 ? ["quote-verify-rejected"] : []
20642
+ ]
20643
+ };
20644
+ }
20645
+ var init_diarist = __esm({
20646
+ "src/diarist.ts"() {
20647
+ "use strict";
20648
+ init_adr_path_refs();
20649
+ init_collector_github();
20650
+ init_diarist_mechanical();
20651
+ init_reviewer_pinned_git();
20652
+ init_ticket_provenance();
20653
+ init_sitian_facade();
20654
+ }
20655
+ });
20656
+
20813
20657
  // src/navigator-role.ts
20814
20658
  var NAVIGATOR_TOOL_SPEC;
20815
20659
  var init_navigator_role = __esm({
@@ -21344,11 +21188,11 @@ var init_reviewer_role = __esm({
21344
21188
  });
21345
21189
 
21346
21190
  // src/worker-submission-gates.ts
21347
- import { execFileSync as execFileSync4 } from "node:child_process";
21348
- import { existsSync as existsSync11, lstatSync as lstatSync3, readdirSync as readdirSync2, readFileSync as readFileSync6, rmdirSync, rmSync } from "node:fs";
21191
+ import { execFileSync as execFileSync3 } from "node:child_process";
21192
+ import { existsSync as existsSync12, lstatSync as lstatSync3, readdirSync as readdirSync2, readFileSync as readFileSync5, rmdirSync, rmSync } from "node:fs";
21349
21193
  import { resolve as resolve18 } from "node:path";
21350
21194
  function git2(cwd, args) {
21351
- return execFileSync4("git", args, {
21195
+ return execFileSync3("git", args, {
21352
21196
  cwd,
21353
21197
  encoding: "utf8",
21354
21198
  stdio: ["ignore", "pipe", "pipe"],
@@ -21356,7 +21200,7 @@ function git2(cwd, args) {
21356
21200
  }).trim();
21357
21201
  }
21358
21202
  function gitFile(file, args) {
21359
- return execFileSync4("git", ["config", "--file", file, ...args], {
21203
+ return execFileSync3("git", ["config", "--file", file, ...args], {
21360
21204
  encoding: "utf8",
21361
21205
  stdio: ["ignore", "pipe", "pipe"],
21362
21206
  env: { ...process.env, GIT_DIR: void 0, GIT_WORK_TREE: void 0, GIT_COMMON_DIR: void 0 }
@@ -21366,7 +21210,7 @@ function statusOf(error) {
21366
21210
  return typeof error === "object" && error !== null && "status" in error ? error.status : void 0;
21367
21211
  }
21368
21212
  function tryGetAll(file, key) {
21369
- if (!existsSync11(file)) return [];
21213
+ if (!existsSync12(file)) return [];
21370
21214
  try {
21371
21215
  const out = gitFile(file, ["--get-all", key]);
21372
21216
  return out.length === 0 ? [] : out.split("\n");
@@ -21376,8 +21220,8 @@ function tryGetAll(file, key) {
21376
21220
  }
21377
21221
  }
21378
21222
  function ownedHook(path) {
21379
- if (!existsSync11(path)) return false;
21380
- return readFileSync6(path, "utf8").includes(HOOK_MARKER);
21223
+ if (!existsSync12(path)) return false;
21224
+ return readFileSync5(path, "utf8").includes(HOOK_MARKER);
21381
21225
  }
21382
21226
  function escapeGitConfigValueRegex(value) {
21383
21227
  return value.replace(/[\\^$.*+?()[\]{}|]/g, "\\$&");
@@ -21403,11 +21247,11 @@ function rmOwnedDir(dir) {
21403
21247
  const hookPath = resolve18(dir, HOOK_FILE);
21404
21248
  if (!ownedHook(hookPath)) return;
21405
21249
  rmSync(hookPath, { force: true });
21406
- if (existsSync11(dir) && readdirSync2(dir).length === 0) rmdirSync(dir);
21250
+ if (existsSync12(dir) && readdirSync2(dir).length === 0) rmdirSync(dir);
21407
21251
  }
21408
21252
  function linkedGitDirs(commonDir) {
21409
21253
  const root = resolve18(commonDir, "worktrees");
21410
- if (!existsSync11(root)) return [];
21254
+ if (!existsSync12(root)) return [];
21411
21255
  return readdirSync2(root).map((name) => resolve18(root, name)).filter((dir) => lstatSync3(dir).isDirectory());
21412
21256
  }
21413
21257
  function uninstallPackageWorkerHooks(cwd) {
@@ -23660,7 +23504,7 @@ __export(in_process_session_exports, {
23660
23504
  });
23661
23505
  import { mkdtemp as mkdtemp2, rm as rm2 } from "node:fs/promises";
23662
23506
  import { tmpdir as tmpdir2 } from "node:os";
23663
- import { join as join31 } from "node:path";
23507
+ import { join as join30 } from "node:path";
23664
23508
  import {
23665
23509
  createAgentSession,
23666
23510
  DefaultResourceLoader,
@@ -23783,7 +23627,7 @@ async function openPiInProcessSession(options) {
23783
23627
  let scratchDir;
23784
23628
  let resolvedAgentDir = options.agentDir;
23785
23629
  if (resolvedAgentDir === void 0) {
23786
- scratchDir = await mkdtemp2(join31(options.credentialScratchParent ?? tmpdir2(), "ak-institutional-"));
23630
+ scratchDir = await mkdtemp2(join30(options.credentialScratchParent ?? tmpdir2(), "ak-institutional-"));
23787
23631
  resolvedAgentDir = scratchDir;
23788
23632
  }
23789
23633
  try {
@@ -24479,7 +24323,7 @@ var init_reviewer_child_executor = __esm({
24479
24323
  import { spawn as spawn4 } from "node:child_process";
24480
24324
  import { mkdtemp as mkdtemp3, rm as rm3 } from "node:fs/promises";
24481
24325
  import { tmpdir as tmpdir3 } from "node:os";
24482
- import { join as join32 } from "node:path";
24326
+ import { join as join31 } from "node:path";
24483
24327
  async function runCommand(command, args, options = {}) {
24484
24328
  return await new Promise((resolve19, reject) => {
24485
24329
  const child = spawn4(command, args, { ...options.cwd === void 0 ? {} : { cwd: options.cwd }, stdio: ["ignore", "pipe", "pipe"], signal: options.signal });
@@ -24528,8 +24372,8 @@ async function prepareSnapshot(accepted, signal, dependencies) {
24528
24372
  if (!sameReviewerPinnedTarget({ repositoryRoot: accepted.repositoryRoot, objectFormat, targetHead }, accepted)) throw new Error("Accepted Reviewer target identity no longer matches the repository");
24529
24373
  await git3(accepted.repositoryRoot, ["cat-file", "-e", `${targetHead}^{commit}`], signal);
24530
24374
  dependencies.fault?.("mirror.before-create");
24531
- mirrorRoot = await mkdtemp3(join32(tmpdir3(), "ak-reviewer-snapshot-"));
24532
- const mirrorPath = join32(mirrorRoot, "repository.git");
24375
+ mirrorRoot = await mkdtemp3(join31(tmpdir3(), "ak-reviewer-snapshot-"));
24376
+ const mirrorPath = join31(mirrorRoot, "repository.git");
24533
24377
  dependencies.fault?.("mirror.create");
24534
24378
  await runCommand("git", ["init", "--bare", `--object-format=${accepted.objectFormat}`, mirrorPath], signal === void 0 ? {} : { signal });
24535
24379
  await git3(mirrorPath, ["fetch", "--no-tags", accepted.repositoryRoot, targetHead], signal);
@@ -24546,7 +24390,7 @@ async function prepareClone(snapshot, signal, dependencies) {
24546
24390
  const target = { repositoryRoot: snapshot.repositoryRoot, objectFormat: snapshot.objectFormat, targetHead: snapshot.targetHead, refs: { ...snapshot.refs } };
24547
24391
  try {
24548
24392
  dependencies.fault?.("workspace.before-create");
24549
- workspace = await mkdtemp3(join32(tmpdir3(), "ak-reviewer-leg-"));
24393
+ workspace = await mkdtemp3(join31(tmpdir3(), "ak-reviewer-leg-"));
24550
24394
  dependencies.fault?.("workspace.init");
24551
24395
  await git3(workspace, ["init", `--object-format=${snapshot.objectFormat}`, "--initial-branch=ak-reviewer-unborn"], signal);
24552
24396
  dependencies.fault?.("workspace.fetch");
@@ -24748,7 +24592,7 @@ var init_reviewer_agent = __esm({
24748
24592
 
24749
24593
  // src/acp-host/production-host.ts
24750
24594
  import { readFile as readFile20 } from "node:fs/promises";
24751
- import { fileURLToPath as fileURLToPath4 } from "node:url";
24595
+ import { fileURLToPath as fileURLToPath3 } from "node:url";
24752
24596
 
24753
24597
  // src/canonical-skill-binding.ts
24754
24598
  import { readFile, realpath } from "node:fs/promises";
@@ -24962,9 +24806,9 @@ init_auditor_soul();
24962
24806
  init_session_opening_materials();
24963
24807
 
24964
24808
  // src/acp-host/description.ts
24965
- import { join as join33 } from "node:path";
24809
+ import { join as join32 } from "node:path";
24966
24810
  function resolveAcpBinary(description, operatorHome) {
24967
- return join33(operatorHome, ...description.binaryFromHome);
24811
+ return join32(operatorHome, ...description.binaryFromHome);
24968
24812
  }
24969
24813
  function acpStdioArgs(description, model) {
24970
24814
  const { prefix, suffix, modelFlag, thinkingFlag } = description.argv;
@@ -24985,8 +24829,8 @@ init_role_runtime();
24985
24829
  import { randomUUID as randomUUID6 } from "node:crypto";
24986
24830
  import { mkdir as mkdir5, readFile as readFile18, writeFile as writeFile8 } from "node:fs/promises";
24987
24831
  import { createServer } from "node:net";
24988
- import { basename as basename7, dirname as dirname17, join as join34 } from "node:path";
24989
- import { fileURLToPath as fileURLToPath3 } from "node:url";
24832
+ import { basename as basename7, dirname as dirname17, join as join33 } from "node:path";
24833
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
24990
24834
 
24991
24835
  // src/acp-host/role-turn-host.ts
24992
24836
  init_agent_start_materials();
@@ -25352,7 +25196,7 @@ async function prepareAcpRoleEnvelope(options) {
25352
25196
  const raw = await readFile18(method.path, "utf8");
25353
25197
  methodSkills.set(name, { path: method.path, body: stripSkillFrontmatter(raw).trim() });
25354
25198
  }
25355
- let sessionFile = options.sessionFile ?? join34(request.runDirectory, "session", "session.jsonl");
25199
+ let sessionFile = options.sessionFile ?? join33(request.runDirectory, "session", "session.jsonl");
25356
25200
  await mkdir5(dirname17(sessionFile), { recursive: true });
25357
25201
  if (request.continuation.kind !== "resume") {
25358
25202
  try {
@@ -25676,7 +25520,7 @@ async function prepareAcpRoleEnvelope(options) {
25676
25520
  });
25677
25521
  }
25678
25522
  await listen(server, options.socketPath);
25679
- const relay = fileURLToPath3(new URL("./mcp-relay.mjs", import.meta.url));
25523
+ const relay = fileURLToPath2(new URL("./mcp-relay.mjs", import.meta.url));
25680
25524
  let disposed = false;
25681
25525
  let priorAkRoleRunDir;
25682
25526
  let priorAkRoleCourtAttempt;
@@ -25817,9 +25661,9 @@ async function prepareAcpRoleEnvelope(options) {
25817
25661
 
25818
25662
  // src/acp-host/session-identity.ts
25819
25663
  import { mkdir as mkdir6, readFile as readFile19, rename, writeFile as writeFile9 } from "node:fs/promises";
25820
- import { dirname as dirname18, join as join35 } from "node:path";
25664
+ import { dirname as dirname18, join as join34 } from "node:path";
25821
25665
  function createAcpSessionIdentityAuthority(authority, sessionBindingFile) {
25822
- const bindingPath = (principal) => join35(authority.decode(principal).sessionDirectory, sessionBindingFile);
25666
+ const bindingPath = (principal) => join34(authority.decode(principal).sessionDirectory, sessionBindingFile);
25823
25667
  return {
25824
25668
  resolveSessionFile(principal) {
25825
25669
  return authority.decode(principal).sessionFile;
@@ -25848,7 +25692,7 @@ function createAcpSessionIdentityAuthority(authority, sessionBindingFile) {
25848
25692
  }
25849
25693
 
25850
25694
  // src/acp-host/production-host.ts
25851
- var navigatorRoutePlaybookPath = fileURLToPath4(
25695
+ var navigatorRoutePlaybookPath = fileURLToPath3(
25852
25696
  new URL("../../resources/navigator-route-playbook.md", import.meta.url)
25853
25697
  );
25854
25698
  function createAcpRoleRuntimeDependencies(packageRoot) {