@akagilnc/pi-workflow-roles 0.1.3708 → 0.1.3716

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/README.md +4 -0
  2. package/README.zh-CN.md +4 -0
  3. package/dist/acp-host/production-host.js +262 -518
  4. package/dist/adr-path-refs.js +1 -1
  5. package/dist/diarist-contracts.js +31 -21
  6. package/dist/diarist-role.js +17 -8
  7. package/dist/diarist.js +39 -388
  8. package/dist/package-contracts/terminating-tools.js +1 -1
  9. package/dist/packaged-role-registry.js +4 -8
  10. package/dist/pi/role-turn-host.js +1 -7
  11. package/dist/public-cli/config.js +106 -2
  12. package/dist/public-cli/main.js +263 -1488
  13. package/dist/public-cli/option-definitions.js +3 -0
  14. package/dist/role-runtime.js +60 -88
  15. package/dist/ticket-provenance-contracts.js +0 -5
  16. package/dist/ticket-provenance.js +2 -149
  17. package/package.json +1 -1
  18. package/resources/diarist-collect.md +21 -11
  19. package/src/acp-host/role-envelope.ts +1 -1
  20. package/src/adr-path-refs.ts +1 -1
  21. package/src/diarist-contracts.ts +48 -32
  22. package/src/diarist-role.ts +31 -16
  23. package/src/diarist.ts +54 -635
  24. package/src/host-contracts.ts +1 -5
  25. package/src/package-contracts/terminating-tools.ts +1 -1
  26. package/src/packaged-role-registry.ts +4 -8
  27. package/src/pi/role-turn-host.ts +1 -7
  28. package/src/public-cli/cli.ts +54 -0
  29. package/src/public-cli/config.ts +157 -1
  30. package/src/public-cli/countersign-run.ts +2 -3
  31. package/src/public-cli/diarist-run.ts +15 -117
  32. package/src/public-cli/option-definitions.ts +3 -0
  33. package/src/role-runtime.ts +73 -105
  34. package/src/ticket-provenance-contracts.ts +6 -12
  35. package/src/ticket-provenance.ts +1 -207
  36. package/dist/diarist-mechanical.js +0 -411
  37. package/src/diarist-mechanical.ts +0 -571
@@ -1740,11 +1740,7 @@ function buildActivationFlagArgs(activation) {
1740
1740
  case "auditor":
1741
1741
  return ["--ak-role", "auditor"];
1742
1742
  case "diarist":
1743
- return [
1744
- "--ak-role",
1745
- "diarist",
1746
- ...activation.sourcesPath === void 0 ? [] : ["--ak-diarist-sources", activation.sourcesPath]
1747
- ];
1743
+ return ["--ak-role", "diarist"];
1748
1744
  default: {
1749
1745
  const _exhaustive = activation;
1750
1746
  return _exhaustive;
@@ -3256,37 +3252,42 @@ function validateRecordedDiaristOutput(value) {
3256
3252
  }
3257
3253
  throw new Error("Diarist output has no execution discriminator");
3258
3254
  }
3259
- function projectDiaristSelections(value) {
3260
- const rows = value?.selections;
3255
+ function projectDiaristEntries(value) {
3256
+ const rows = value?.entries;
3261
3257
  if (!Array.isArray(rows)) return [];
3262
3258
  const out = [];
3263
3259
  for (const row of rows) {
3264
3260
  if (row === null || typeof row !== "object" || Array.isArray(row)) continue;
3265
3261
  const record4 = row;
3266
- const index = record4.candidateIndex;
3267
- if (typeof index !== "number" || !Number.isInteger(index) || index < 0) continue;
3268
- const quotes = Array.isArray(record4.quotes) ? record4.quotes.filter((q) => typeof q === "string" && q.length > 0) : [];
3262
+ if (typeof record4.sourceKind !== "string") continue;
3263
+ if (typeof record4.transcript !== "string" || record4.transcript.length === 0) continue;
3264
+ if (typeof record4.timestamp !== "string" || record4.timestamp.length === 0) continue;
3265
+ if (record4.sourceRef === null || typeof record4.sourceRef !== "object" || Array.isArray(record4.sourceRef)) {
3266
+ continue;
3267
+ }
3268
+ const ref = record4.sourceRef;
3269
+ const sourceRef = {
3270
+ ...typeof ref.sessionFile === "string" ? { sessionFile: ref.sessionFile } : {},
3271
+ ...typeof ref.entryId === "string" || typeof ref.entryId === "number" ? { entryId: ref.entryId } : {},
3272
+ ...typeof ref.path === "string" ? { path: ref.path } : {},
3273
+ ...typeof ref.url === "string" ? { url: ref.url } : {}
3274
+ };
3269
3275
  out.push({
3270
- candidateIndex: index,
3271
- quotes,
3276
+ sourceKind: record4.sourceKind,
3277
+ sourceRef,
3278
+ transcript: record4.transcript,
3279
+ timestamp: record4.timestamp,
3272
3280
  ...typeof record4.note === "string" ? { note: record4.note } : {}
3273
3281
  });
3274
3282
  }
3275
3283
  return out;
3276
3284
  }
3277
- var DIARIST_OUTPUT_TOOL_NAME, DIARIST_ACCEPTED_TEXT, DIARIST_SOURCES_FLAG;
3285
+ var DIARIST_OUTPUT_TOOL_NAME, DIARIST_ACCEPTED_TEXT;
3278
3286
  var init_diarist_contracts = __esm({
3279
3287
  "src/diarist-contracts.ts"() {
3280
3288
  "use strict";
3281
3289
  DIARIST_OUTPUT_TOOL_NAME = "ak_diarist_output";
3282
3290
  DIARIST_ACCEPTED_TEXT = "\u8D77\u5C45\u90CE\u56DE\u6267\u5DF2\u63A5\u53D7";
3283
- DIARIST_SOURCES_FLAG = {
3284
- name: "ak-diarist-sources",
3285
- definition: {
3286
- description: "Frozen source catalog the diarist selects from (may be unbound until LLM asserts ticketNumber)",
3287
- type: "string"
3288
- }
3289
- };
3290
3291
  }
3291
3292
  });
3292
3293
 
@@ -6073,14 +6074,17 @@ var init_option_definitions = __esm({
6073
6074
  "ak-role config unset-engine <seat>",
6074
6075
  "ak-role config set-host <seat> <name>",
6075
6076
  "ak-role config unset-host <seat>",
6076
- "ak-role config set-auto-resume-limit <N>"
6077
+ "ak-role config set-auto-resume-limit <N>",
6078
+ "ak-role config set-provider-alias <provider> <host> <alias>",
6079
+ "ak-role config unset-provider-alias <provider> <host>"
6077
6080
  ],
6078
6081
  examples: [
6079
6082
  "ak-role config set judge openai-codex/gpt-5.6-sol:high",
6080
6083
  "ak-role config unset gatekeeper",
6081
6084
  "ak-role config set-engine judge opus",
6082
6085
  "ak-role config set-host judge grok-build",
6083
- "ak-role config set-auto-resume-limit 3"
6086
+ "ak-role config set-auto-resume-limit 3",
6087
+ "ak-role config set-provider-alias xai hermes xai-oauth"
6084
6088
  ]
6085
6089
  },
6086
6090
  help: {
@@ -8642,14 +8646,13 @@ var init_packaged_role_registry = __esm({
8642
8646
  activationStage: "load-and-install",
8643
8647
  sessionMaterials: AUDITOR_PUBLIC_SESSION_MATERIALS
8644
8648
  },
8645
- // #708 / ADR 0075 `diarist-is-role`: 起居郎 is a seat like any other. The
8646
- // frozen source catalog rides the shared input-flag seam; it is absent for a
8647
- // true-unbound summons (no ticket → no diary).
8649
+ // #708 / ADR 0075 `diarist-is-role` / #779: 起居郎 is a seat like any other.
8650
+ // No input flag — LLM finds materials itself (caller-transparent).
8648
8651
  {
8649
8652
  role: "diarist",
8650
8653
  phases: [null],
8651
8654
  outputTool: DIARIST_OUTPUT_TOOL_NAME,
8652
- inputFlag: DIARIST_SOURCES_FLAG.name,
8655
+ inputFlag: void 0,
8653
8656
  phaseFlag: void 0,
8654
8657
  activationStage: "load-and-install",
8655
8658
  sessionMaterials: [
@@ -8819,6 +8822,7 @@ var init_institutional_resolution = __esm({
8819
8822
  var config_exports = {};
8820
8823
  __export(config_exports, {
8821
8824
  GATE_OFFICER_SEATS: () => GATE_OFFICER_SEATS,
8825
+ applyProviderHostAlias: () => applyProviderHostAlias,
8822
8826
  buildSeatModelCliArgs: () => buildSeatModelCliArgs2,
8823
8827
  clearPersistentSeatConfig: () => clearPersistentSeatConfig,
8824
8828
  credentialProvidersFromAuthData: () => credentialProvidersFromAuthData,
@@ -8839,6 +8843,8 @@ __export(config_exports, {
8839
8843
  setPersistentSeatConfig: () => setPersistentSeatConfig,
8840
8844
  setPersistentSeatEngine: () => setPersistentSeatEngine,
8841
8845
  setPersistentSeatHost: () => setPersistentSeatHost,
8846
+ setProviderHostAlias: () => setProviderHostAlias,
8847
+ unsetProviderHostAlias: () => unsetProviderHostAlias,
8842
8848
  validatePublicCliConfigAxes: () => validatePublicCliConfigAxes
8843
8849
  });
8844
8850
  import { mkdir as mkdir2, readFile as readFile10, writeFile as writeFile5 } from "node:fs/promises";
@@ -8966,6 +8972,50 @@ function parseAutoResumeLimit(value) {
8966
8972
  function setAutoResumeLimit(config, limit) {
8967
8973
  return { ...config, autoResumeLimit: parseAutoResumeLimit(limit) };
8968
8974
  }
8975
+ function requireNonEmptyToken(value, label) {
8976
+ const trimmed = value.trim();
8977
+ if (trimmed === "") {
8978
+ throw new Error(`${label} must be a non-empty string`);
8979
+ }
8980
+ return trimmed;
8981
+ }
8982
+ function setProviderHostAlias(config, provider, host, alias) {
8983
+ const from = requireNonEmptyToken(provider, "provider");
8984
+ const hostName = requireNonEmptyToken(host, "host");
8985
+ const to = requireNonEmptyToken(alias, "alias");
8986
+ const previous = config.providerAliases ?? {};
8987
+ return {
8988
+ ...config,
8989
+ providerAliases: {
8990
+ ...previous,
8991
+ [from]: {
8992
+ ...previous[from] ?? {},
8993
+ [hostName]: to
8994
+ }
8995
+ }
8996
+ };
8997
+ }
8998
+ function unsetProviderHostAlias(config, provider, host) {
8999
+ const from = requireNonEmptyToken(provider, "provider");
9000
+ const hostName = requireNonEmptyToken(host, "host");
9001
+ const previous = config.providerAliases;
9002
+ if (previous === void 0 || previous[from] === void 0) return config;
9003
+ const { [hostName]: _dropped, ...restHosts } = previous[from];
9004
+ const nextForProvider = Object.keys(restHosts).length === 0 ? void 0 : restHosts;
9005
+ const { [from]: _provider, ...restProviders } = previous;
9006
+ const nextAliases = nextForProvider === void 0 ? restProviders : { ...restProviders, [from]: nextForProvider };
9007
+ if (Object.keys(nextAliases).length === 0) {
9008
+ const { providerAliases: _gone, ...rest } = config;
9009
+ return rest;
9010
+ }
9011
+ return { ...config, providerAliases: nextAliases };
9012
+ }
9013
+ function applyProviderHostAlias(selection, host, aliases) {
9014
+ if (selection === void 0 || aliases === void 0) return selection;
9015
+ const mapped = aliases[selection.provider]?.[host];
9016
+ if (mapped === void 0) return selection;
9017
+ return { ...selection, provider: mapped };
9018
+ }
8969
9019
  function validatePublicCliConfigAxes(config, _packageRoot) {
8970
9020
  for (const seat of Object.keys(config.seats)) {
8971
9021
  const row = config.seats[seat];
@@ -9035,9 +9085,44 @@ function serializePublicCliConfig(config) {
9035
9085
  ...config.unknownSeats ?? {},
9036
9086
  ...config.seats
9037
9087
  },
9038
- ...config.autoResumeLimit === void 0 ? {} : { autoResumeLimit: config.autoResumeLimit }
9088
+ ...config.autoResumeLimit === void 0 ? {} : { autoResumeLimit: config.autoResumeLimit },
9089
+ ...config.providerAliases === void 0 || Object.keys(config.providerAliases).length === 0 ? {} : { providerAliases: config.providerAliases }
9039
9090
  };
9040
9091
  }
9092
+ function parseProviderHostAliases(value) {
9093
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
9094
+ throw new Error("public CLI config.providerAliases must be an object");
9095
+ }
9096
+ const out = {};
9097
+ for (const [provider, byHost] of Object.entries(value)) {
9098
+ if (provider.trim() === "") {
9099
+ throw new Error("public CLI config.providerAliases provider key must be non-empty");
9100
+ }
9101
+ if (byHost === null || typeof byHost !== "object" || Array.isArray(byHost)) {
9102
+ throw new Error(
9103
+ `public CLI config.providerAliases[${provider}] must be an object`
9104
+ );
9105
+ }
9106
+ const hosts = {};
9107
+ for (const [host, alias] of Object.entries(byHost)) {
9108
+ if (host.trim() === "") {
9109
+ throw new Error(
9110
+ `public CLI config.providerAliases[${provider}] host key must be non-empty`
9111
+ );
9112
+ }
9113
+ if (typeof alias !== "string" || alias.trim() === "") {
9114
+ throw new Error(
9115
+ `public CLI config.providerAliases[${provider}][${host}] must be a non-empty string`
9116
+ );
9117
+ }
9118
+ hosts[host] = alias;
9119
+ }
9120
+ if (Object.keys(hosts).length > 0) {
9121
+ out[provider] = hosts;
9122
+ }
9123
+ }
9124
+ return out;
9125
+ }
9041
9126
  function parsePublicCliConfig(value) {
9042
9127
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
9043
9128
  throw new Error("public CLI config must be an object");
@@ -9047,6 +9132,13 @@ function parsePublicCliConfig(value) {
9047
9132
  if (record4.autoResumeLimit !== void 0) {
9048
9133
  autoResumeLimit = parseAutoResumeLimit(record4.autoResumeLimit);
9049
9134
  }
9135
+ let providerAliases;
9136
+ if (record4.providerAliases !== void 0) {
9137
+ const parsed = parseProviderHostAliases(record4.providerAliases);
9138
+ if (Object.keys(parsed).length > 0) {
9139
+ providerAliases = parsed;
9140
+ }
9141
+ }
9050
9142
  const unknownSeats = {};
9051
9143
  if (record4.unknownSeats !== void 0) {
9052
9144
  if (record4.unknownSeats === null || typeof record4.unknownSeats !== "object" || Array.isArray(record4.unknownSeats)) {
@@ -9057,6 +9149,7 @@ function parsePublicCliConfig(value) {
9057
9149
  const withOpaque = (seats2) => ({
9058
9150
  seats: seats2,
9059
9151
  ...autoResumeLimit === void 0 ? {} : { autoResumeLimit },
9152
+ ...providerAliases === void 0 ? {} : { providerAliases },
9060
9153
  ...Object.keys(unknownSeats).length === 0 ? {} : { unknownSeats }
9061
9154
  });
9062
9155
  if (record4.seats === void 0) {
@@ -9233,7 +9326,21 @@ function resolveEffectiveSeat(config, seat, credentials, invocation) {
9233
9326
  };
9234
9327
  }
9235
9328
  }
9236
- return attachHostAxis(attachEngineAxis(modelSeat, config, invocation), config, invocation);
9329
+ const withAxes = attachHostAxis(
9330
+ attachEngineAxis(modelSeat, config, invocation),
9331
+ config,
9332
+ invocation
9333
+ );
9334
+ const selection = applyProviderHostAlias(
9335
+ withAxes.selection,
9336
+ withAxes.host,
9337
+ config.providerAliases
9338
+ );
9339
+ if (selection === void 0) {
9340
+ const { selection: _dropped, ...rest } = withAxes;
9341
+ return rest;
9342
+ }
9343
+ return { ...withAxes, selection };
9237
9344
  }
9238
9345
  function effectiveSeatConfigurations(config, credentials, invocation) {
9239
9346
  return PUBLIC_CONFIGURABLE_SEATS.map(
@@ -9372,13 +9479,12 @@ function projectTicketProvenanceEntry(value) {
9372
9479
  timestamp: value.timestamp
9373
9480
  };
9374
9481
  }
9375
- var TICKET_PROVENANCE_KIND, TICKET_PROVENANCE_HUMAN_VIEW, TICKET_PROVENANCE_OFFERED_WATERMARK, TICKET_PROVENANCE_RECORD_CLASS_DIAGNOSTIC, SOURCE_KINDS, BASIS_METHODS, DIAGNOSTIC_KINDS;
9482
+ var TICKET_PROVENANCE_KIND, TICKET_PROVENANCE_HUMAN_VIEW, TICKET_PROVENANCE_RECORD_CLASS_DIAGNOSTIC, SOURCE_KINDS, BASIS_METHODS, DIAGNOSTIC_KINDS;
9376
9483
  var init_ticket_provenance_contracts = __esm({
9377
9484
  "src/ticket-provenance-contracts.ts"() {
9378
9485
  "use strict";
9379
9486
  TICKET_PROVENANCE_KIND = "ticket-provenance";
9380
9487
  TICKET_PROVENANCE_HUMAN_VIEW = "\u8D77\u5C45\u5F55.md";
9381
- TICKET_PROVENANCE_OFFERED_WATERMARK = "offered-identities.jsonl";
9382
9488
  TICKET_PROVENANCE_RECORD_CLASS_DIAGNOSTIC = "diagnostic";
9383
9489
  SOURCE_KINDS = /* @__PURE__ */ new Set([
9384
9490
  "cc-session",
@@ -9397,7 +9503,7 @@ var init_ticket_provenance_contracts = __esm({
9397
9503
 
9398
9504
  // src/ticket-provenance.ts
9399
9505
  import { createHash as createHash5 } from "node:crypto";
9400
- import { appendFileSync as appendFileSync2, existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "node:fs";
9506
+ import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync3, writeFileSync as writeFileSync3 } from "node:fs";
9401
9507
  import { join as join16 } from "node:path";
9402
9508
  function ticketProvenanceSubject(ticketNumber) {
9403
9509
  if (!Number.isSafeInteger(ticketNumber) || ticketNumber < 1) {
@@ -9456,67 +9562,9 @@ function resolveTicketProvenanceVolume(ticketNumber, cwd, home) {
9456
9562
  return {
9457
9563
  recordFile: path.recordFile,
9458
9564
  volumeDir: path.sessionDir,
9459
- humanViewFile: join16(path.sessionDir, TICKET_PROVENANCE_HUMAN_VIEW),
9460
- offeredWatermarkFile: join16(path.sessionDir, TICKET_PROVENANCE_OFFERED_WATERMARK)
9565
+ humanViewFile: join16(path.sessionDir, TICKET_PROVENANCE_HUMAN_VIEW)
9461
9566
  };
9462
9567
  }
9463
- function readOfferedIdentities(ticketNumber, cwd, home) {
9464
- const { offeredWatermarkFile } = resolveTicketProvenanceVolume(ticketNumber, cwd, home);
9465
- if (!existsSync6(offeredWatermarkFile)) return /* @__PURE__ */ new Set();
9466
- let text;
9467
- try {
9468
- text = readFileSync2(offeredWatermarkFile, "utf8");
9469
- } catch (error) {
9470
- throw new TicketProvenanceWatermarkError(
9471
- "unreadable",
9472
- `ticket-provenance offered watermark unreadable (${offeredWatermarkFile})`,
9473
- { cause: error }
9474
- );
9475
- }
9476
- const seen = /* @__PURE__ */ new Set();
9477
- const lines = text.split("\n");
9478
- for (let index = 0; index < lines.length; index += 1) {
9479
- const trimmed = lines[index].trim();
9480
- if (!trimmed) continue;
9481
- let parsed;
9482
- try {
9483
- parsed = JSON.parse(trimmed);
9484
- } catch (error) {
9485
- throw new TicketProvenanceWatermarkError(
9486
- "malformed-json",
9487
- `ticket-provenance offered watermark malformed JSON at line ${index + 1} (${offeredWatermarkFile})`,
9488
- { cause: error }
9489
- );
9490
- }
9491
- if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed) || typeof parsed.identity !== "string" || parsed.identity.length === 0) {
9492
- throw new TicketProvenanceWatermarkError(
9493
- "bad-shape",
9494
- `ticket-provenance offered watermark bad shape at line ${index + 1} (${offeredWatermarkFile})`
9495
- );
9496
- }
9497
- seen.add(parsed.identity);
9498
- }
9499
- return seen;
9500
- }
9501
- function recordOfferedIdentities(input) {
9502
- if (input.identities.length === 0) return;
9503
- const { volumeDir, offeredWatermarkFile } = resolveTicketProvenanceVolume(
9504
- input.ticketNumber,
9505
- input.cwd,
9506
- input.home
9507
- );
9508
- const already = new Set(readOfferedIdentities(input.ticketNumber, input.cwd, input.home));
9509
- const rows = [];
9510
- for (const identity of input.identities) {
9511
- if (identity.length === 0 || already.has(identity)) continue;
9512
- rows.push(`${JSON.stringify({ identity })}
9513
- `);
9514
- already.add(identity);
9515
- }
9516
- if (rows.length === 0) return;
9517
- mkdirSync3(volumeDir, { recursive: true });
9518
- appendFileSync2(offeredWatermarkFile, rows.join(""), "utf8");
9519
- }
9520
9568
  async function readTicketProvenance(ticketNumber, cwd, home) {
9521
9569
  const { recordFile } = resolveTicketProvenanceVolume(ticketNumber, cwd, home);
9522
9570
  const { records: records2 } = await readSitianRecords(recordFile);
@@ -9602,50 +9650,6 @@ function ensureTicketProvenanceVolume(ticketNumber, cwd, home) {
9602
9650
  appendFileSync2(volume.recordFile, "", "utf8");
9603
9651
  return volume;
9604
9652
  }
9605
- function appendTicketProvenanceDiagnostic(input) {
9606
- const subject = ticketProvenanceSubject(input.ticketNumber);
9607
- const identityParts = input.diagnostic.diagnosticKind === "quote-verify-failed" ? [
9608
- subject,
9609
- input.diagnostic.recordClass,
9610
- input.diagnostic.diagnosticKind,
9611
- input.diagnostic.cause,
9612
- input.diagnostic.reason ?? ""
9613
- ] : [
9614
- subject,
9615
- input.diagnostic.recordClass,
9616
- input.diagnostic.diagnosticKind,
9617
- input.diagnostic.recordedAt,
9618
- input.diagnostic.cause,
9619
- input.diagnostic.reason ?? ""
9620
- ];
9621
- const identity = createHash5("sha256").update(identityParts.join("\0"), "utf8").digest("hex");
9622
- return sitianReport({
9623
- level: "event",
9624
- kind: TICKET_PROVENANCE_KIND,
9625
- identity,
9626
- subject,
9627
- cwd: input.cwd,
9628
- ...input.home === void 0 ? {} : { home: input.home },
9629
- host: input.host ?? "diarist",
9630
- source: input.source ?? "diarist-diagnostic",
9631
- payload: input.diagnostic
9632
- });
9633
- }
9634
- function appendQuoteVerifyFailureDiagnostic(input) {
9635
- const recordedAt = input.recordedAt ?? (/* @__PURE__ */ new Date()).toISOString();
9636
- return appendTicketProvenanceDiagnostic({
9637
- ticketNumber: input.ticketNumber,
9638
- cwd: input.cwd,
9639
- ...input.home === void 0 ? {} : { home: input.home },
9640
- source: "diarist-quote-verify",
9641
- diagnostic: {
9642
- recordClass: TICKET_PROVENANCE_RECORD_CLASS_DIAGNOSTIC,
9643
- diagnosticKind: "quote-verify-failed",
9644
- cause: input.cause,
9645
- recordedAt
9646
- }
9647
- });
9648
- }
9649
9653
  function writeTicketProvenanceHumanView(input) {
9650
9654
  const volume = ensureTicketProvenanceVolume(input.ticketNumber, input.cwd, input.home);
9651
9655
  const md = renderTicketProvenanceMarkdown({
@@ -9655,21 +9659,11 @@ function writeTicketProvenanceHumanView(input) {
9655
9659
  writeFileSync3(volume.humanViewFile, md, "utf8");
9656
9660
  return volume.humanViewFile;
9657
9661
  }
9658
- var TicketProvenanceWatermarkError;
9659
9662
  var init_ticket_provenance = __esm({
9660
9663
  "src/ticket-provenance.ts"() {
9661
9664
  "use strict";
9662
9665
  init_sitian_facade();
9663
9666
  init_ticket_provenance_contracts();
9664
- TicketProvenanceWatermarkError = class extends Error {
9665
- code = "ticket-provenance-watermark";
9666
- reason;
9667
- constructor(reason, message, options) {
9668
- super(message, options);
9669
- this.name = "TicketProvenanceWatermarkError";
9670
- this.reason = reason;
9671
- }
9672
- };
9673
9667
  }
9674
9668
  });
9675
9669
 
@@ -10512,14 +10506,14 @@ var init_analyst_gate_cycles_read = __esm({
10512
10506
  });
10513
10507
 
10514
10508
  // src/session-opening-materials.ts
10515
- import { existsSync as existsSync7 } from "node:fs";
10509
+ import { existsSync as existsSync6 } from "node:fs";
10516
10510
  import { readFile as readFile12 } from "node:fs/promises";
10517
10511
  import { dirname as dirname11, join as join20 } from "node:path";
10518
10512
  import { fileURLToPath, pathToFileURL as pathToFileURL2 } from "node:url";
10519
10513
  function resolvePackageRootDir(moduleUrl = import.meta.url) {
10520
10514
  let dir = dirname11(fileURLToPath(moduleUrl));
10521
10515
  for (let i = 0; i < 8; i += 1) {
10522
- if (existsSync7(join20(dir, "package.json")) && existsSync7(join20(dir, "souls"))) {
10516
+ if (existsSync6(join20(dir, "package.json")) && existsSync6(join20(dir, "souls"))) {
10523
10517
  return dir;
10524
10518
  }
10525
10519
  const parent = dirname11(dir);
@@ -16769,7 +16763,7 @@ __export(public_role_summons_exports, {
16769
16763
  summonGateOfficer: () => summonGateOfficer,
16770
16764
  summonPublicRole: () => summonPublicRole
16771
16765
  });
16772
- import { existsSync as existsSync8 } from "node:fs";
16766
+ import { existsSync as existsSync7 } from "node:fs";
16773
16767
  import { join as join26 } from "node:path";
16774
16768
  function createCapturingIo() {
16775
16769
  const chunks = [];
@@ -16793,7 +16787,7 @@ function parentDir(path) {
16793
16787
  function walkPackageRoot(start) {
16794
16788
  let dir = start;
16795
16789
  for (let i = 0; i < 12; i += 1) {
16796
- if (existsSync8(join26(dir, "package.json")) && existsSync8(join26(dir, "souls"))) {
16790
+ if (existsSync7(join26(dir, "package.json")) && existsSync7(join26(dir, "souls"))) {
16797
16791
  return dir;
16798
16792
  }
16799
16793
  const parent = parentDir(dir);
@@ -17211,7 +17205,7 @@ var init_compliance_transport = __esm({
17211
17205
  });
17212
17206
 
17213
17207
  // src/dossier-resolution.ts
17214
- import { existsSync as existsSync9, statSync as statSync2 } from "node:fs";
17208
+ import { existsSync as existsSync8, statSync as statSync2 } from "node:fs";
17215
17209
  import { resolve as resolve12 } from "node:path";
17216
17210
  function resolveAuditDossier(env = process.env) {
17217
17211
  const raw = env[AUDIT_RUN_DIR_ENV];
@@ -17220,7 +17214,7 @@ function resolveAuditDossier(env = process.env) {
17220
17214
  }
17221
17215
  const runDirectory = resolve12(raw);
17222
17216
  try {
17223
- if (!existsSync9(runDirectory) || !statSync2(runDirectory).isDirectory()) {
17217
+ if (!existsSync8(runDirectory) || !statSync2(runDirectory).isDirectory()) {
17224
17218
  return { status: "incomplete", observation: { kind: "missing-dossier" } };
17225
17219
  }
17226
17220
  } catch {
@@ -17498,13 +17492,13 @@ __export(archivist_record_entry_exports, {
17498
17492
  createRecordSessionOpen: () => createRecordSessionOpen,
17499
17493
  subjectKeyedRecordDirectory: () => subjectKeyedRecordDirectory
17500
17494
  });
17501
- import { existsSync as existsSync10, mkdirSync as mkdirSync4, readFileSync as readFileSync3, realpathSync as realpathSync2, writeFileSync as writeFileSync5 } from "node:fs";
17495
+ import { existsSync as existsSync9, mkdirSync as mkdirSync4, readFileSync as readFileSync2, realpathSync as realpathSync2, writeFileSync as writeFileSync5 } from "node:fs";
17502
17496
  import { dirname as dirname13, resolve as resolve13, join as join28 } from "node:path";
17503
17497
  import { SessionManager } from "@earendil-works/pi-coding-agent";
17504
17498
  function readCurrentSession(sessionDir) {
17505
17499
  const ledger = join28(sessionDir, CURRENT_SESSION_LEDGER);
17506
17500
  try {
17507
- const value = JSON.parse(readFileSync3(ledger, "utf8"));
17501
+ const value = JSON.parse(readFileSync2(ledger, "utf8"));
17508
17502
  if (typeof value !== "object" || value === null || typeof value.sessionFile !== "string" || value.sessionFile.length === 0) {
17509
17503
  throw new Error("sessionFile is missing");
17510
17504
  }
@@ -17581,7 +17575,7 @@ function createRecordSessionOpen(options) {
17581
17575
  sessionDir = physicallyContainedIn(ledgerHome, parentResolved) ? join28(dirname13(parentResolved), options.kind) : join28(activationBookDirectory(ledgerHome, resolveBookKeyFromGit(cwd)), options.kind);
17582
17576
  parentSession = parentFile;
17583
17577
  }
17584
- const nestAlreadyExists = existsSync10(sessionDir);
17578
+ const nestAlreadyExists = existsSync9(sessionDir);
17585
17579
  ensureRealDirectoryTree(ledgerHome, sessionDir);
17586
17580
  const mayResumeSameNest = options.subject !== void 0 || options.kind === WORKER_SUBMISSION_GATE_KIND;
17587
17581
  if (mayResumeSameNest && nestAlreadyExists) {
@@ -17599,7 +17593,7 @@ function createRecordSessionOpen(options) {
17599
17593
  );
17600
17594
  if (session.isPersisted()) {
17601
17595
  const file = session.getSessionFile();
17602
- if (file !== void 0 && !existsSync10(file)) {
17596
+ if (file !== void 0 && !existsSync9(file)) {
17603
17597
  const header = session.getHeader();
17604
17598
  if (header !== null && header.type === "session") {
17605
17599
  writeFileSync5(file, `${JSON.stringify(header)}
@@ -20330,7 +20324,7 @@ var init_diarist_role = __esm({
20330
20324
  }),
20331
20325
  ticketNumber: Type23.Optional(
20332
20326
  Type23.Unknown({
20333
- description: "\u672C\u5EAD\u5BF9\u8C61\u7968\u53F7\uFF08\u6B63\u6574\u6570\uFF09\u6216 null/\u7701\u7565\uFF1D\u771F\u65E0\u7968\uFF1B\u673A\u68B0\u9A8C\u771F\u540E\u4E0B\u6E38\u8D70 typed \u952E\uFF1B\u8BA4\u4E0D\u51FA\u7528 status=escalate\uFF0C\u4E0D\u6D17\u6210\u65E0\u5F55"
20327
+ description: "\u672C\u5EAD\u5BF9\u8C61\u7968\u53F7\uFF08\u6B63\u6574\u6570\uFF09\u6216 null/\u7701\u7565\uFF1D\u771F\u65E0\u7968\uFF1B\u4E0B\u6E38\u8D70 typed \u952E\uFF1B\u8BA4\u4E0D\u51FA\u7528 status=escalate\uFF0C\u4E0D\u6D17\u6210\u65E0\u5F55\u3002\u673A\u68B0\u5C42\u4E0D\u91CD\u5224\u3002"
20334
20328
  })
20335
20329
  ),
20336
20330
  reason: Type23.Optional(
@@ -20338,20 +20332,34 @@ var init_diarist_role = __esm({
20338
20332
  description: "status \u4E3A escalate \u65F6\uFF1A\u8BA4\u4E0D\u51FA\u672C\u5EAD\u5BF9\u8C61\u7684\u539F\u56E0"
20339
20333
  })
20340
20334
  ),
20341
- selections: Type23.Array(
20342
- Type23.Object(
20343
- {
20344
- candidateIndex: Type23.Number({ description: "\u5019\u9009\u76EE\u5F55\u4E2D\u7684\u6574\u5757\u5E8F\u53F7" }),
20345
- quotes: Type23.Array(Type23.String(), {
20346
- description: "\u8BE5\u5757 transcript \u5185\u7684\u8FDE\u7EED\u539F\u6587\uFF1B\u673A\u68B0\u53CD\u9A8C"
20347
- }),
20348
- note: Type23.Optional(
20349
- Type23.String({ description: "\u8BE5\u6750\u6599\u4E0E\u672C\u6848\u7684\u5173\u7CFB\uFF08\u4EBA\u8BFB\uFF09" })
20350
- )
20351
- },
20352
- { additionalProperties: true, description: "\u4E00\u6761\u5165\u5F55\u9009\u62E9" }
20353
- ),
20354
- { description: "\u5165\u5F55\u9009\u62E9\uFF1B\u7A7A\u5217\u8868\u5408\u6CD5\u5B8C\u5C40\uFF1Bescalate \u65F6\u53EF\u4E0D\u4EA4" }
20335
+ entries: Type23.Optional(
20336
+ Type23.Array(
20337
+ Type23.Object(
20338
+ {
20339
+ sourceKind: Type23.String({
20340
+ description: "\u6765\u6E90\u65CF\uFF1Acc-session | issue-body-comment | adr-decision-key | ticket-decree-block"
20341
+ }),
20342
+ sourceRef: Type23.Object(
20343
+ {
20344
+ sessionFile: Type23.Optional(Type23.String()),
20345
+ entryId: Type23.Optional(Type23.Unknown()),
20346
+ path: Type23.Optional(Type23.String()),
20347
+ url: Type23.Optional(Type23.String())
20348
+ },
20349
+ { additionalProperties: true, description: "\u4E0D\u53EF\u53D8\u6E90\u6307\u9488" }
20350
+ ),
20351
+ transcript: Type23.String({
20352
+ description: "\u6574\u5757\u539F\u6587\uFF08\u8A8A\u5F55\u6574\u5757\uFF0C\u4E0D\u6307\u9488\u5316\uFF09"
20353
+ }),
20354
+ timestamp: Type23.String({ description: "\u6E90\u65F6\u95F4\u6233 ISO" }),
20355
+ note: Type23.Optional(
20356
+ Type23.String({ description: "\u8BE5\u6750\u6599\u4E0E\u672C\u6848\u7684\u5173\u7CFB\uFF08\u4EBA\u8BFB\uFF09" })
20357
+ )
20358
+ },
20359
+ { additionalProperties: true, description: "\u4E00\u6761\u5165\u5F55\u6574\u5757" }
20360
+ ),
20361
+ { description: "\u5165\u5F55\u6574\u5757\uFF1B\u7A7A\u5217\u8868\u5408\u6CD5\u5B8C\u5C40\uFF1Bescalate \u65F6\u53EF\u4E0D\u4EA4" }
20362
+ )
20355
20363
  )
20356
20364
  })
20357
20365
  )
@@ -20359,294 +20367,66 @@ var init_diarist_role = __esm({
20359
20367
  DIARIST_TOOL_SPEC = {
20360
20368
  name: DIARIST_OUTPUT_TOOL_NAME,
20361
20369
  label: "\u8D77\u5C45\u90CE\u8F93\u51FA",
20362
- description: "\u8D77\u5C45\u90CE\u5165\u5F55\u9009\u62E9\u4E0E\u672C\u7968\u8EAB\u4EFD\u65AD\u8A00\uFF1B\u8BA4\u4E0D\u51FA\u672C\u5EAD\u5BF9\u8C61\u5219 escalate\u3002",
20363
- promptSnippet: "\u8D77\u5C45\u90CE\u5165\u5F55\u9009\u62E9\u4E0E\u672C\u7968\u8EAB\u4EFD",
20370
+ description: "\u8D77\u5C45\u90CE\u5165\u5F55\u6574\u5757\u4E0E\u672C\u7968\u8EAB\u4EFD\u65AD\u8A00\uFF1B\u8BA4\u4E0D\u51FA\u672C\u5EAD\u5BF9\u8C61\u5219 escalate\u3002",
20371
+ promptSnippet: "\u8D77\u5C45\u90CE\u5165\u5F55\u6574\u5757\u4E0E\u672C\u7968\u8EAB\u4EFD",
20364
20372
  parameters: diaristOutputSchema
20365
20373
  };
20366
20374
  }
20367
20375
  });
20368
20376
 
20369
- // src/diarist-mechanical.ts
20370
- function extractCornerQuotes(text, minLength = DEFAULT_QUOTE_MIN) {
20371
- const out = [];
20372
- const re = /「([^」]+)」/g;
20373
- let match;
20374
- while ((match = re.exec(text)) !== null) {
20375
- const q = match[1].trim();
20376
- if (q.length >= minLength) out.push(q);
20377
- }
20378
- return out;
20379
- }
20380
- function buildDiaristAnchors(input) {
20381
- const fromBody = input.ticketBody === void 0 ? [] : extractCornerQuotes(input.ticketBody);
20382
- const quotes = [...fromBody, ...input.extraQuotes ?? []];
20383
- const seen = /* @__PURE__ */ new Set();
20384
- const uniqueQuotes = [];
20385
- for (const q of quotes) {
20386
- if (seen.has(q)) continue;
20387
- seen.add(q);
20388
- uniqueQuotes.push(q);
20389
- }
20390
- return {
20391
- ticketNumber: input.ticketNumber,
20392
- quotes: uniqueQuotes
20393
- };
20394
- }
20395
- function verifyQuotesVerbatim(sourceText, quotes) {
20396
- const failed2 = [];
20397
- for (const q of quotes) {
20398
- if (q.length === 0) continue;
20399
- if (!sourceText.includes(q)) failed2.push(q);
20400
- }
20401
- if (failed2.length === 0) return { ok: true };
20402
- return { ok: false, failedQuotes: failed2 };
20403
- }
20404
- function blockToLlmEntry(block, input) {
20405
- const verify = verifyQuotesVerbatim(block.transcript, input.quotes);
20406
- if (!verify.ok) {
20407
- return {
20408
- ok: false,
20409
- failedQuotes: verify.failedQuotes,
20410
- cause: `verbatim verify failed: ${verify.failedQuotes.join(" | ")}`
20411
- };
20412
- }
20413
- const anchorNotes = [`#${input.anchors.ticketNumber}`];
20414
- const seen = new Set(anchorNotes);
20415
- for (const q of [...input.anchors.quotes, ...input.quotes]) {
20416
- if (seen.has(q)) continue;
20417
- seen.add(q);
20418
- anchorNotes.push(q);
20419
- if (anchorNotes.length >= 12) break;
20420
- }
20421
- return {
20422
- ok: true,
20423
- entry: {
20377
+ // src/diarist.ts
20378
+ async function commitDiaristEntries(input) {
20379
+ const { ticketNumber, cwd } = input;
20380
+ const homeOpt = input.home === void 0 ? {} : { home: input.home };
20381
+ const volumePaths = ensureTicketProvenanceVolume(ticketNumber, cwd, input.home);
20382
+ const before = await readTicketProvenance(ticketNumber, cwd, input.home);
20383
+ let dropped = 0;
20384
+ for (const submitted of input.entries) {
20385
+ const entry = projectTicketProvenanceEntry({
20424
20386
  basis: {
20425
20387
  method: "llm-semantic",
20426
- anchors: anchorNotes,
20427
- ...input.note === void 0 ? {} : { note: input.note }
20388
+ anchors: [`#${ticketNumber}`],
20389
+ ...submitted.note === void 0 ? {} : { note: submitted.note }
20428
20390
  },
20429
- sourceKind: block.sourceKind,
20430
- sourceRef: block.sourceRef,
20431
- transcript: block.transcript,
20432
- timestamp: block.timestamp
20433
- }
20434
- };
20435
- }
20436
- var DEFAULT_QUOTE_MIN;
20437
- var init_diarist_mechanical = __esm({
20438
- "src/diarist-mechanical.ts"() {
20439
- "use strict";
20440
- init_activation_ledger_topology();
20441
- DEFAULT_QUOTE_MIN = 6;
20442
- }
20443
- });
20444
-
20445
- // src/diarist.ts
20446
- import { readFileSync as readFileSync4 } from "node:fs";
20447
- import { execFileSync as execFileSync3 } from "node:child_process";
20448
- function instructionContainsTicketNumber(instruction, ticketNumber) {
20449
- if (!Number.isSafeInteger(ticketNumber) || ticketNumber < 1) return false;
20450
- return new RegExp("(?<!\\d)" + String(ticketNumber) + "(?!\\d)").test(
20451
- instruction
20452
- );
20453
- }
20454
- function createGhTicketExistenceChecker(options) {
20455
- const runner = options?.runner ?? createGhApiRunner();
20456
- return async (input) => {
20457
- const projected = await projectGhIssueBody(runner, {
20458
- owner: input.owner,
20459
- repo: input.repo,
20460
- ticketNumber: input.ticketNumber,
20461
- ...input.signal === void 0 ? {} : { signal: input.signal }
20462
- });
20463
- return projected.status === "available";
20464
- };
20465
- }
20466
- async function verifyAssertedTicketNumber(input) {
20467
- const n = input.ticketNumber;
20468
- if (!Number.isSafeInteger(n) || n < 1) {
20469
- throw new DiaristTicketVerificationError(
20470
- "assertion-uninterpretable",
20471
- `diarist ticket assertion must be a safe integer >= 1, got ${String(n)}`
20472
- );
20473
- }
20474
- if (!instructionContainsTicketNumber(input.instruction, n)) {
20475
- throw new DiaristTicketVerificationError(
20476
- "number-not-in-instruction",
20477
- `diarist ticket assertion #${n} complete decimal number does not appear in accepted instruction`
20478
- );
20479
- }
20480
- const origin = resolveDiaristGithubOrigin(input.projectRoot);
20481
- if (origin === void 0) {
20482
- throw new DiaristTicketVerificationError(
20483
- "origin-unresolved",
20484
- `diarist ticket assertion #${n} requires a resolvable github.com origin remote for live verification`
20485
- );
20486
- }
20487
- const checkExistence = input.checkExistence ?? createGhTicketExistenceChecker();
20488
- let exists;
20489
- try {
20490
- exists = await checkExistence({
20491
- owner: origin.owner,
20492
- repo: origin.repo,
20493
- ticketNumber: n,
20494
- ...input.signal === void 0 ? {} : { signal: input.signal }
20495
- });
20496
- } catch (error) {
20497
- throw new DiaristTicketVerificationError(
20498
- "ticket-missing",
20499
- `diarist ticket assertion #${n} live verification failed`,
20500
- { cause: error }
20501
- );
20502
- }
20503
- if (!exists) {
20504
- throw new DiaristTicketVerificationError(
20505
- "ticket-missing",
20506
- `diarist ticket assertion #${n} does not exist as a live issue on ${origin.owner}/${origin.repo}`
20507
- );
20508
- }
20509
- }
20510
- function resolveDiaristGithubOrigin(projectRoot) {
20511
- let remoteUrl;
20512
- try {
20513
- remoteUrl = execFileSync3("git", ["remote", "get-url", "origin"], {
20514
- cwd: projectRoot,
20515
- encoding: "utf8",
20516
- stdio: ["ignore", "pipe", "pipe"]
20517
- }).trim();
20518
- } catch {
20519
- return void 0;
20520
- }
20521
- if (remoteUrl.length === 0) return void 0;
20522
- return parseGitHubOriginRemote(remoteUrl);
20523
- }
20524
- function blockEntryIdentity(ticketNumber, block) {
20525
- return ticketProvenanceEntryIdentity({
20526
- ticketNumber,
20527
- sourceKind: block.sourceKind,
20528
- sourceRef: block.sourceRef,
20529
- transcript: block.transcript
20530
- });
20531
- }
20532
- function loadDiaristSourceCatalog(path) {
20533
- const parsed = JSON.parse(readFileSync4(path, "utf8"));
20534
- if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
20535
- throw new Error(`diarist source catalog is not an object (${path})`);
20536
- }
20537
- const record4 = parsed;
20538
- if (typeof record4.cwd !== "string") {
20539
- throw new Error(`diarist source catalog is missing cwd (${path})`);
20540
- }
20541
- if (typeof record4.instruction !== "string") {
20542
- throw new Error(`diarist source catalog is missing instruction (${path})`);
20543
- }
20544
- if (typeof record4.runDirectory !== "string") {
20545
- throw new Error(`diarist source catalog is missing runDirectory (${path})`);
20546
- }
20547
- if (typeof record4.projectRoot !== "string") {
20548
- throw new Error(`diarist source catalog is missing projectRoot (${path})`);
20549
- }
20550
- if (record4.ticketNumber !== void 0 && (typeof record4.ticketNumber !== "number" || !Number.isSafeInteger(record4.ticketNumber) || record4.ticketNumber < 1)) {
20551
- throw new Error(`diarist source catalog ticketNumber is not a safe ticket (${path})`);
20552
- }
20553
- if (!Array.isArray(record4.candidates)) {
20554
- throw new Error(`diarist source catalog is missing candidates (${path})`);
20555
- }
20556
- return parsed;
20557
- }
20558
- async function commitDiaristSelections(input) {
20559
- const ticketNumber = input.catalog.ticketNumber;
20560
- if (ticketNumber === void 0) {
20561
- throw new Error(
20562
- "commitDiaristSelections requires a bound ticketNumber on the catalog"
20563
- );
20564
- }
20565
- const { cwd } = input.catalog;
20566
- const homeOpt = input.catalog.home === void 0 ? {} : { home: input.catalog.home };
20567
- const volumePaths = ensureTicketProvenanceVolume(ticketNumber, cwd, input.catalog.home);
20568
- const anchors = buildDiaristAnchors({ ticketNumber });
20569
- const before = await readTicketProvenance(ticketNumber, cwd, input.catalog.home);
20570
- let acceptedRows = 0;
20571
- let rejectedQuotes = 0;
20572
- let unknownCandidate = false;
20573
- for (const selection of input.selections) {
20574
- const block = input.catalog.candidates[selection.candidateIndex];
20575
- if (block === void 0) {
20576
- unknownCandidate = true;
20577
- continue;
20578
- }
20579
- const projected = blockToLlmEntry(block, {
20580
- anchors,
20581
- quotes: selection.quotes,
20582
- ...selection.note === void 0 ? {} : { note: selection.note }
20391
+ sourceKind: submitted.sourceKind,
20392
+ sourceRef: submitted.sourceRef,
20393
+ transcript: submitted.transcript,
20394
+ timestamp: submitted.timestamp
20583
20395
  });
20584
- if (!projected.ok) {
20585
- rejectedQuotes += 1;
20586
- appendQuoteVerifyFailureDiagnostic({
20587
- ticketNumber,
20588
- cwd,
20589
- ...homeOpt,
20590
- cause: projected.cause
20591
- });
20396
+ if (entry === void 0) {
20397
+ dropped += 1;
20592
20398
  continue;
20593
20399
  }
20594
20400
  appendTicketProvenanceEntry({
20595
20401
  ticketNumber,
20596
20402
  cwd,
20597
20403
  ...homeOpt,
20598
- entry: projected.entry,
20404
+ entry,
20599
20405
  source: "diarist"
20600
20406
  });
20601
- acceptedRows += 1;
20602
20407
  }
20603
- const identities = input.catalog.candidates.map(
20604
- (block) => blockEntryIdentity(ticketNumber, block)
20605
- );
20606
- const alreadyWatermarked = readOfferedIdentities(ticketNumber, cwd, input.catalog.home);
20607
- const watermarked = identities.filter((identity) => !alreadyWatermarked.has(identity)).length;
20608
- recordOfferedIdentities({ ticketNumber, cwd, ...homeOpt, identities });
20609
- const volume = await readTicketProvenance(ticketNumber, cwd, input.catalog.home);
20408
+ const volume = await readTicketProvenance(ticketNumber, cwd, input.home);
20610
20409
  const humanViewFile = writeTicketProvenanceHumanView({
20611
20410
  ticketNumber,
20612
20411
  cwd,
20613
20412
  ...homeOpt,
20614
20413
  entries: volume.entries
20615
20414
  });
20415
+ const appended = volume.entries.length - before.entries.length;
20616
20416
  return {
20617
20417
  ticketNumber,
20618
- offered: input.catalog.candidates.length,
20619
- appended: volume.entries.length - before.entries.length,
20620
- rejectedQuotes,
20621
- watermarked,
20418
+ appended,
20419
+ dropped,
20622
20420
  volumeRecordFile: volumePaths.recordFile,
20623
20421
  humanViewFile,
20624
- collectorStatus: input.catalog.candidates.length === 0 ? "skipped-no-fresh" : acceptedRows > 0 ? "ok" : input.selections.length === 0 ? "empty-selection" : "nothing-appended",
20625
- failureCauses: [
20626
- ...unknownCandidate ? ["unknown-candidate"] : [],
20627
- ...rejectedQuotes > 0 ? ["quote-verify-rejected"] : []
20628
- ]
20422
+ collectorStatus: appended > 0 ? "ok" : input.entries.length === 0 ? "empty-selection" : "nothing-appended"
20629
20423
  };
20630
20424
  }
20631
- var DiaristTicketVerificationError;
20632
20425
  var init_diarist = __esm({
20633
20426
  "src/diarist.ts"() {
20634
20427
  "use strict";
20635
- init_adr_path_refs();
20636
- init_collector_github();
20637
- init_diarist_mechanical();
20638
- init_reviewer_pinned_git();
20639
20428
  init_ticket_provenance();
20640
- init_sitian_facade();
20641
- DiaristTicketVerificationError = class extends Error {
20642
- code = "diarist-ticket-verification";
20643
- reason;
20644
- constructor(reason, message, options) {
20645
- super(message, options);
20646
- this.name = "DiaristTicketVerificationError";
20647
- this.reason = reason;
20648
- }
20649
- };
20429
+ init_ticket_provenance_contracts();
20650
20430
  }
20651
20431
  });
20652
20432
 
@@ -21169,11 +20949,11 @@ var init_reviewer_role = __esm({
21169
20949
  });
21170
20950
 
21171
20951
  // src/worker-submission-gates.ts
21172
- import { execFileSync as execFileSync4 } from "node:child_process";
21173
- import { existsSync as existsSync11, lstatSync as lstatSync3, readdirSync as readdirSync2, readFileSync as readFileSync5, rmdirSync, rmSync } from "node:fs";
20952
+ import { execFileSync as execFileSync3 } from "node:child_process";
20953
+ import { existsSync as existsSync10, lstatSync as lstatSync3, readdirSync as readdirSync2, readFileSync as readFileSync3, rmdirSync, rmSync } from "node:fs";
21174
20954
  import { resolve as resolve18 } from "node:path";
21175
20955
  function git2(cwd, args) {
21176
- return execFileSync4("git", args, {
20956
+ return execFileSync3("git", args, {
21177
20957
  cwd,
21178
20958
  encoding: "utf8",
21179
20959
  stdio: ["ignore", "pipe", "pipe"],
@@ -21181,7 +20961,7 @@ function git2(cwd, args) {
21181
20961
  }).trim();
21182
20962
  }
21183
20963
  function gitFile(file, args) {
21184
- return execFileSync4("git", ["config", "--file", file, ...args], {
20964
+ return execFileSync3("git", ["config", "--file", file, ...args], {
21185
20965
  encoding: "utf8",
21186
20966
  stdio: ["ignore", "pipe", "pipe"],
21187
20967
  env: { ...process.env, GIT_DIR: void 0, GIT_WORK_TREE: void 0, GIT_COMMON_DIR: void 0 }
@@ -21191,7 +20971,7 @@ function statusOf(error) {
21191
20971
  return typeof error === "object" && error !== null && "status" in error ? error.status : void 0;
21192
20972
  }
21193
20973
  function tryGetAll(file, key) {
21194
- if (!existsSync11(file)) return [];
20974
+ if (!existsSync10(file)) return [];
21195
20975
  try {
21196
20976
  const out = gitFile(file, ["--get-all", key]);
21197
20977
  return out.length === 0 ? [] : out.split("\n");
@@ -21201,8 +20981,8 @@ function tryGetAll(file, key) {
21201
20981
  }
21202
20982
  }
21203
20983
  function ownedHook(path) {
21204
- if (!existsSync11(path)) return false;
21205
- return readFileSync5(path, "utf8").includes(HOOK_MARKER);
20984
+ if (!existsSync10(path)) return false;
20985
+ return readFileSync3(path, "utf8").includes(HOOK_MARKER);
21206
20986
  }
21207
20987
  function escapeGitConfigValueRegex(value) {
21208
20988
  return value.replace(/[\\^$.*+?()[\]{}|]/g, "\\$&");
@@ -21228,11 +21008,11 @@ function rmOwnedDir(dir) {
21228
21008
  const hookPath = resolve18(dir, HOOK_FILE);
21229
21009
  if (!ownedHook(hookPath)) return;
21230
21010
  rmSync(hookPath, { force: true });
21231
- if (existsSync11(dir) && readdirSync2(dir).length === 0) rmdirSync(dir);
21011
+ if (existsSync10(dir) && readdirSync2(dir).length === 0) rmdirSync(dir);
21232
21012
  }
21233
21013
  function linkedGitDirs(commonDir) {
21234
21014
  const root = resolve18(commonDir, "worktrees");
21235
- if (!existsSync11(root)) return [];
21015
+ if (!existsSync10(root)) return [];
21236
21016
  return readdirSync2(root).map((name) => resolve18(root, name)).filter((dir) => lstatSync3(dir).isDirectory());
21237
21017
  }
21238
21018
  function uninstallPackageWorkerHooks(cwd) {
@@ -21920,7 +21700,8 @@ var init_activation_reconciliation = __esm({
21920
21700
  });
21921
21701
 
21922
21702
  // src/role-runtime.ts
21923
- import { writeSync as writeSync4 } from "node:fs";
21703
+ import { readFileSync as readFileSync4, writeSync as writeSync4 } from "node:fs";
21704
+ import { join as join30 } from "node:path";
21924
21705
  import { Value as Value5 } from "typebox/value";
21925
21706
  function decodeReviewerAdmittedInputs(getFlag) {
21926
21707
  let reviewScopeKeys;
@@ -22283,14 +22064,30 @@ function readDiaristTicketAssertion(submitted) {
22283
22064
  return { kind: "ticket", ticketNumber: n };
22284
22065
  }
22285
22066
  }
22286
- throw new DiaristTicketVerificationError(
22287
- "assertion-uninterpretable",
22067
+ throw new Error(
22288
22068
  "diarist ticketNumber must be a safe integer >= 1, null, or absent"
22289
22069
  );
22290
22070
  }
22291
- function createDiaristRoleRuntime(roleHost, dependencies, getSourcesFlag) {
22292
- let catalog;
22293
- const runtime = createFiledOfficerRuntime(
22071
+ function readDiaristRunCoordinates() {
22072
+ const runDirectory = process.env.AK_ROLE_RUN_DIR;
22073
+ if (typeof runDirectory !== "string" || runDirectory.trim() === "") {
22074
+ throw new Error("diarist accept requires AK_ROLE_RUN_DIR");
22075
+ }
22076
+ const admittedPath = join30(runDirectory, "admitted-request.json");
22077
+ const admitted = JSON.parse(readFileSync4(admittedPath, "utf8"));
22078
+ if (typeof admitted.projectRoot !== "string" || admitted.projectRoot.trim() === "") {
22079
+ throw new Error(`diarist admitted-request missing projectRoot (${admittedPath})`);
22080
+ }
22081
+ const bound = typeof admitted.ticketNumber === "number" && Number.isSafeInteger(admitted.ticketNumber) && admitted.ticketNumber >= 1 ? admitted.ticketNumber : void 0;
22082
+ return {
22083
+ runDirectory,
22084
+ projectRoot: admitted.projectRoot,
22085
+ home: homeFromRunDirectory(runDirectory),
22086
+ ...bound === void 0 ? {} : { boundTicketNumber: bound }
22087
+ };
22088
+ }
22089
+ function createDiaristRoleRuntime(roleHost, dependencies) {
22090
+ return createFiledOfficerRuntime(
22294
22091
  roleHost,
22295
22092
  {
22296
22093
  role: "diarist",
@@ -22309,30 +22106,9 @@ function createDiaristRoleRuntime(roleHost, dependencies, getSourcesFlag) {
22309
22106
  return stripped;
22310
22107
  }
22311
22108
  const assertion = readDiaristTicketAssertion(submitted);
22312
- if (catalog === void 0) {
22313
- if (assertion.kind === "ticket") {
22314
- throw new DiaristTicketVerificationError(
22315
- "assertion-uninterpretable",
22316
- `diarist asserted ticket #${assertion.ticketNumber} but no source catalog was frozen for this turn`
22317
- );
22318
- }
22319
- if (submitted === void 0 || !("sitian" in submitted)) return void 0;
22320
- const stripped = { ...submitted };
22321
- delete stripped.sitian;
22322
- return stripped;
22323
- }
22324
- if (catalog.ticketNumber !== void 0) {
22325
- const facts2 = await commitDiaristSelections({
22326
- catalog,
22327
- selections: projectDiaristSelections(parameters)
22328
- });
22329
- return {
22330
- ...submitted ?? { receipt: parameters },
22331
- ticketNumber: catalog.ticketNumber,
22332
- sitian: facts2
22333
- };
22334
- }
22335
- if (assertion.kind === "true-unbound") {
22109
+ const coords = readDiaristRunCoordinates();
22110
+ const ticketNumber = coords.boundTicketNumber !== void 0 ? coords.boundTicketNumber : assertion.kind === "ticket" ? assertion.ticketNumber : void 0;
22111
+ if (ticketNumber === void 0) {
22336
22112
  if (submitted === void 0 || !("sitian" in submitted)) {
22337
22113
  return { ...submitted ?? { receipt: parameters }, ticketNumber: null };
22338
22114
  }
@@ -22343,46 +22119,24 @@ function createDiaristRoleRuntime(roleHost, dependencies, getSourcesFlag) {
22343
22119
  delete stripped.sitian;
22344
22120
  return stripped;
22345
22121
  }
22346
- await verifyAssertedTicketNumber({
22347
- ticketNumber: assertion.ticketNumber,
22348
- instruction: catalog.instruction,
22349
- projectRoot: catalog.projectRoot
22350
- });
22351
- await bindTicketNumberOnRunDirectory(
22352
- catalog.runDirectory,
22353
- assertion.ticketNumber
22354
- );
22355
- const boundCatalog = {
22356
- ...catalog,
22357
- ticketNumber: assertion.ticketNumber
22358
- };
22359
- const facts = await commitDiaristSelections({
22360
- catalog: boundCatalog,
22361
- selections: projectDiaristSelections(parameters)
22122
+ if (coords.boundTicketNumber === void 0) {
22123
+ await bindTicketNumberOnRunDirectory(coords.runDirectory, ticketNumber);
22124
+ }
22125
+ const facts = await commitDiaristEntries({
22126
+ ticketNumber,
22127
+ cwd: coords.projectRoot,
22128
+ home: coords.home,
22129
+ entries: projectDiaristEntries(parameters)
22362
22130
  });
22363
22131
  return {
22364
22132
  ...submitted ?? { receipt: parameters },
22365
- ticketNumber: assertion.ticketNumber,
22133
+ ticketNumber,
22366
22134
  sitian: facts
22367
22135
  };
22368
22136
  }
22369
22137
  },
22370
22138
  dependencies
22371
22139
  );
22372
- return {
22373
- async activate() {
22374
- catalog = loadFrozenDiaristCatalog(getSourcesFlag);
22375
- return runtime.activate();
22376
- }
22377
- };
22378
- }
22379
- function loadFrozenDiaristCatalog(getFlag) {
22380
- const raw = getFlag();
22381
- if (raw === void 0) return void 0;
22382
- if (typeof raw !== "string" || raw.trim() === "") {
22383
- throw new Error("Diarist source catalog flag must be a nonempty path");
22384
- }
22385
- return loadDiaristSourceCatalog(raw);
22386
22140
  }
22387
22141
  function createCountersignRoleRuntime(roleHost, dependencies, hostActions) {
22388
22142
  const beforeAccept = hostActions !== void 0 && roleHost.requireGatekeeperPass !== void 0 ? async ({ toolCallId, parameters, signal, ctx }) => {
@@ -22435,9 +22189,6 @@ function createRoleRuntimeExtension(dependencies) {
22435
22189
  for (const flag of GLEANER_LEFT_TRANSPORT_FLAGS) {
22436
22190
  roleHost.registerFlag(flag.name, flag.definition);
22437
22191
  }
22438
- for (const flag of DIARIST_TRANSPORT_FLAGS) {
22439
- roleHost.registerFlag(flag.name, flag.definition);
22440
- }
22441
22192
  let admitted = false;
22442
22193
  let selectedRole;
22443
22194
  let activeReviewerParent;
@@ -22847,8 +22598,7 @@ function createRoleRuntimeExtension(dependencies) {
22847
22598
  if (!dependencies.loadDiaristSoul) throw new Error("Diarist runtime dependencies are not configured");
22848
22599
  return dependencies.loadDiaristSoul();
22849
22600
  }
22850
- },
22851
- () => envelopeHost.host.getFlag(DIARIST_SOURCES_FLAG.name)
22601
+ }
22852
22602
  );
22853
22603
  let sessionMergerGitState = dependencies.mergerGitState;
22854
22604
  const merger = createMergerRoleRuntime(roleHost, {
@@ -23132,7 +22882,7 @@ function createRoleRuntimeExtension(dependencies) {
23132
22882
  });
23133
22883
  };
23134
22884
  }
23135
- var REVIEWER_TRANSPORT_FLAGS, NOTARY_TRANSPORT_FLAGS, GLEANER_LEFT_TRANSPORT_FLAGS, DIARIST_TRANSPORT_FLAGS, ActivationBarrierError, WORKFLOW_ROLES, ROLE_FLAG, COUNTERSIGN_QUEUE_STATUSES, COUNTERSIGN_STATUS_REASK;
22885
+ var REVIEWER_TRANSPORT_FLAGS, NOTARY_TRANSPORT_FLAGS, GLEANER_LEFT_TRANSPORT_FLAGS, ActivationBarrierError, WORKFLOW_ROLES, ROLE_FLAG, COUNTERSIGN_QUEUE_STATUSES, COUNTERSIGN_STATUS_REASK;
23136
22886
  var init_role_runtime = __esm({
23137
22887
  "src/role-runtime.ts"() {
23138
22888
  "use strict";
@@ -23252,12 +23002,6 @@ var init_role_runtime = __esm({
23252
23002
  definition: GLEANER_LEFT_BASE_FLAG.definition
23253
23003
  })
23254
23004
  ]);
23255
- DIARIST_TRANSPORT_FLAGS = Object.freeze([
23256
- Object.freeze({
23257
- name: DIARIST_SOURCES_FLAG.name,
23258
- definition: DIARIST_SOURCES_FLAG.definition
23259
- })
23260
- ]);
23261
23005
  ActivationBarrierError = class extends Error {
23262
23006
  code = "AK_ACTIVATION_NOT_ADMITTED";
23263
23007
  constructor(role) {
@@ -23572,7 +23316,7 @@ __export(in_process_session_exports, {
23572
23316
  });
23573
23317
  import { mkdtemp as mkdtemp2, rm as rm2 } from "node:fs/promises";
23574
23318
  import { tmpdir as tmpdir2 } from "node:os";
23575
- import { join as join30 } from "node:path";
23319
+ import { join as join31 } from "node:path";
23576
23320
  import {
23577
23321
  createAgentSession,
23578
23322
  DefaultResourceLoader,
@@ -23695,7 +23439,7 @@ async function openPiInProcessSession(options) {
23695
23439
  let scratchDir;
23696
23440
  let resolvedAgentDir = options.agentDir;
23697
23441
  if (resolvedAgentDir === void 0) {
23698
- scratchDir = await mkdtemp2(join30(options.credentialScratchParent ?? tmpdir2(), "ak-institutional-"));
23442
+ scratchDir = await mkdtemp2(join31(options.credentialScratchParent ?? tmpdir2(), "ak-institutional-"));
23699
23443
  resolvedAgentDir = scratchDir;
23700
23444
  }
23701
23445
  try {
@@ -24391,7 +24135,7 @@ var init_reviewer_child_executor = __esm({
24391
24135
  import { spawn as spawn4 } from "node:child_process";
24392
24136
  import { mkdtemp as mkdtemp3, rm as rm3 } from "node:fs/promises";
24393
24137
  import { tmpdir as tmpdir3 } from "node:os";
24394
- import { join as join31 } from "node:path";
24138
+ import { join as join32 } from "node:path";
24395
24139
  async function runCommand(command, args, options = {}) {
24396
24140
  return await new Promise((resolve19, reject) => {
24397
24141
  const child = spawn4(command, args, { ...options.cwd === void 0 ? {} : { cwd: options.cwd }, stdio: ["ignore", "pipe", "pipe"], signal: options.signal });
@@ -24440,8 +24184,8 @@ async function prepareSnapshot(accepted, signal, dependencies) {
24440
24184
  if (!sameReviewerPinnedTarget({ repositoryRoot: accepted.repositoryRoot, objectFormat, targetHead }, accepted)) throw new Error("Accepted Reviewer target identity no longer matches the repository");
24441
24185
  await git3(accepted.repositoryRoot, ["cat-file", "-e", `${targetHead}^{commit}`], signal);
24442
24186
  dependencies.fault?.("mirror.before-create");
24443
- mirrorRoot = await mkdtemp3(join31(tmpdir3(), "ak-reviewer-snapshot-"));
24444
- const mirrorPath = join31(mirrorRoot, "repository.git");
24187
+ mirrorRoot = await mkdtemp3(join32(tmpdir3(), "ak-reviewer-snapshot-"));
24188
+ const mirrorPath = join32(mirrorRoot, "repository.git");
24445
24189
  dependencies.fault?.("mirror.create");
24446
24190
  await runCommand("git", ["init", "--bare", `--object-format=${accepted.objectFormat}`, mirrorPath], signal === void 0 ? {} : { signal });
24447
24191
  await git3(mirrorPath, ["fetch", "--no-tags", accepted.repositoryRoot, targetHead], signal);
@@ -24458,7 +24202,7 @@ async function prepareClone(snapshot, signal, dependencies) {
24458
24202
  const target = { repositoryRoot: snapshot.repositoryRoot, objectFormat: snapshot.objectFormat, targetHead: snapshot.targetHead, refs: { ...snapshot.refs } };
24459
24203
  try {
24460
24204
  dependencies.fault?.("workspace.before-create");
24461
- workspace = await mkdtemp3(join31(tmpdir3(), "ak-reviewer-leg-"));
24205
+ workspace = await mkdtemp3(join32(tmpdir3(), "ak-reviewer-leg-"));
24462
24206
  dependencies.fault?.("workspace.init");
24463
24207
  await git3(workspace, ["init", `--object-format=${snapshot.objectFormat}`, "--initial-branch=ak-reviewer-unborn"], signal);
24464
24208
  dependencies.fault?.("workspace.fetch");
@@ -24873,9 +24617,9 @@ init_auditor_soul();
24873
24617
  init_session_opening_materials();
24874
24618
 
24875
24619
  // src/acp-host/description.ts
24876
- import { join as join32 } from "node:path";
24620
+ import { join as join33 } from "node:path";
24877
24621
  function resolveAcpBinary(description, operatorHome) {
24878
- return join32(operatorHome, ...description.binaryFromHome);
24622
+ return join33(operatorHome, ...description.binaryFromHome);
24879
24623
  }
24880
24624
  function acpStdioArgs(description, model) {
24881
24625
  const { prefix, suffix, modelFlag, thinkingFlag } = description.argv;
@@ -24896,7 +24640,7 @@ init_role_runtime();
24896
24640
  import { randomUUID as randomUUID6 } from "node:crypto";
24897
24641
  import { mkdir as mkdir5, readFile as readFile18, writeFile as writeFile8 } from "node:fs/promises";
24898
24642
  import { createServer } from "node:net";
24899
- import { basename as basename7, dirname as dirname17, join as join33 } from "node:path";
24643
+ import { basename as basename7, dirname as dirname17, join as join34 } from "node:path";
24900
24644
  import { fileURLToPath as fileURLToPath2 } from "node:url";
24901
24645
 
24902
24646
  // src/acp-host/role-turn-host.ts
@@ -25199,7 +24943,7 @@ function projectAcpActivationFlags(request) {
25199
24943
  const phaseFlag = packagedRolePhaseFlag(activation.role);
25200
24944
  if ("phase" in activation && phaseFlag !== void 0) flags.set(phaseFlag, activation.phase);
25201
24945
  if (inputFlag !== void 0) {
25202
- const path = "taskPath" in activation ? activation.taskPath : "packetPath" in activation ? activation.packetPath : "casePath" in activation ? activation.casePath : "inputPath" in activation ? activation.inputPath : "sourceRun" in activation ? activation.sourceRun : "sourcesPath" in activation ? activation.sourcesPath : void 0;
24946
+ const path = "taskPath" in activation ? activation.taskPath : "packetPath" in activation ? activation.packetPath : "casePath" in activation ? activation.casePath : "inputPath" in activation ? activation.inputPath : "sourceRun" in activation ? activation.sourceRun : void 0;
25203
24947
  if (path !== void 0) flags.set(inputFlag, path);
25204
24948
  }
25205
24949
  if (activation.role === "fixer" && activation.prerequisitesPath !== void 0) flags.set("ak-fixer-prerequisites", activation.prerequisitesPath);
@@ -25263,7 +25007,7 @@ async function prepareAcpRoleEnvelope(options) {
25263
25007
  const raw = await readFile18(method.path, "utf8");
25264
25008
  methodSkills.set(name, { path: method.path, body: stripSkillFrontmatter(raw).trim() });
25265
25009
  }
25266
- let sessionFile = options.sessionFile ?? join33(request.runDirectory, "session", "session.jsonl");
25010
+ let sessionFile = options.sessionFile ?? join34(request.runDirectory, "session", "session.jsonl");
25267
25011
  await mkdir5(dirname17(sessionFile), { recursive: true });
25268
25012
  if (request.continuation.kind !== "resume") {
25269
25013
  try {
@@ -25728,9 +25472,9 @@ async function prepareAcpRoleEnvelope(options) {
25728
25472
 
25729
25473
  // src/acp-host/session-identity.ts
25730
25474
  import { mkdir as mkdir6, readFile as readFile19, rename, writeFile as writeFile9 } from "node:fs/promises";
25731
- import { dirname as dirname18, join as join34 } from "node:path";
25475
+ import { dirname as dirname18, join as join35 } from "node:path";
25732
25476
  function createAcpSessionIdentityAuthority(authority, sessionBindingFile) {
25733
- const bindingPath = (principal) => join34(authority.decode(principal).sessionDirectory, sessionBindingFile);
25477
+ const bindingPath = (principal) => join35(authority.decode(principal).sessionDirectory, sessionBindingFile);
25734
25478
  return {
25735
25479
  resolveSessionFile(principal) {
25736
25480
  return authority.decode(principal).sessionFile;