@akagilnc/pi-workflow-roles 0.1.3565 → 0.1.3572

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 (35) hide show
  1. package/README.md +4 -1
  2. package/README.zh-CN.md +1 -1
  3. package/dist/acp-host/production-host.js +755 -60
  4. package/dist/diarist-contracts.js +72 -0
  5. package/dist/package-contracts/terminating-tools.js +20 -2
  6. package/dist/packaged-role-registry.js +20 -0
  7. package/dist/public-cli/main.js +533 -634
  8. package/dist/public-cli/registry.js +4 -1
  9. package/extensions/role-runtime.ts +1 -0
  10. package/package.json +1 -1
  11. package/resources/diarist-collect.md +6 -10
  12. package/souls/diarist.md +9 -0
  13. package/src/acp-host/production-host.ts +1 -0
  14. package/src/acp-host/role-envelope.ts +2 -1
  15. package/src/diarist-contracts.ts +88 -0
  16. package/src/diarist-role.ts +60 -0
  17. package/src/diarist.ts +253 -179
  18. package/src/host-contracts.ts +6 -1
  19. package/src/package-contracts/terminating-tools.ts +22 -2
  20. package/src/packaged-role-registry.ts +20 -0
  21. package/src/pi/role-turn-host.ts +8 -0
  22. package/src/public-cli/cli.ts +29 -0
  23. package/src/public-cli/countersign-run.ts +9 -129
  24. package/src/public-cli/diarist-run.ts +312 -0
  25. package/src/public-cli/invocation.ts +23 -2
  26. package/src/public-cli/option-definitions.ts +18 -0
  27. package/src/public-cli/post-admission.ts +2 -2
  28. package/src/public-cli/registry.ts +3 -0
  29. package/src/public-cli/run-lifecycle.ts +31 -3
  30. package/src/public-cli/settlement.ts +50 -2
  31. package/src/public-cli/terminal.ts +2 -1
  32. package/src/role-runtime.ts +117 -6
  33. package/src/ticket-provenance-contracts.ts +1 -0
  34. package/src/ticket-provenance.ts +0 -23
  35. package/src/diarist-llm-collector.ts +0 -324
@@ -2874,6 +2874,50 @@ function validateRecordedInspectorOutput(value) {
2874
2874
  throw new Error("Inspector output has no execution discriminator");
2875
2875
  }
2876
2876
 
2877
+ // src/diarist-contracts.ts
2878
+ var DIARIST_OUTPUT_TOOL_NAME = "ak_diarist_output";
2879
+ var DIARIST_ACCEPTED_TEXT = "\u8D77\u5C45\u90CE\u56DE\u6267\u5DF2\u63A5\u53D7";
2880
+ var DIARIST_SOURCES_FLAG = {
2881
+ name: "ak-diarist-sources",
2882
+ definition: {
2883
+ description: "Frozen per-ticket source catalog the diarist selects from",
2884
+ type: "string"
2885
+ }
2886
+ };
2887
+ function validateRecordedDiaristOutput(value) {
2888
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
2889
+ throw new Error("Diarist output has no execution discriminator");
2890
+ }
2891
+ let status;
2892
+ try {
2893
+ status = value.status;
2894
+ } catch {
2895
+ throw new Error("Diarist output has no execution discriminator");
2896
+ }
2897
+ if (status === "completed") {
2898
+ return value;
2899
+ }
2900
+ throw new Error("Diarist output has no execution discriminator");
2901
+ }
2902
+ function projectDiaristSelections(value) {
2903
+ const rows = value?.selections;
2904
+ if (!Array.isArray(rows)) return [];
2905
+ const out = [];
2906
+ for (const row of rows) {
2907
+ if (row === null || typeof row !== "object" || Array.isArray(row)) continue;
2908
+ const record4 = row;
2909
+ const index = record4.candidateIndex;
2910
+ if (typeof index !== "number" || !Number.isInteger(index) || index < 0) continue;
2911
+ const quotes = Array.isArray(record4.quotes) ? record4.quotes.filter((q) => typeof q === "string" && q.length > 0) : [];
2912
+ out.push({
2913
+ candidateIndex: index,
2914
+ quotes,
2915
+ ...typeof record4.note === "string" ? { note: record4.note } : {}
2916
+ });
2917
+ }
2918
+ return out;
2919
+ }
2920
+
2877
2921
  // src/packaged-role-registry.ts
2878
2922
  var NOTARY_SESSION_MATERIALS = [
2879
2923
  "CLAUDE.md",
@@ -3040,6 +3084,22 @@ var PUBLIC_ROLE_RECORDS = [
3040
3084
  phaseFlag: void 0,
3041
3085
  activationStage: "load-and-install",
3042
3086
  sessionMaterials: ["CLAUDE.md", "souls/navigator.md"]
3087
+ },
3088
+ // #708 / ADR 0075 `diarist-is-role`: 起居郎 is a seat like any other. The
3089
+ // frozen source catalog rides the shared input-flag seam; it is absent for a
3090
+ // true-unbound summons (no ticket → no diary).
3091
+ {
3092
+ role: "diarist",
3093
+ phases: [null],
3094
+ outputTool: DIARIST_OUTPUT_TOOL_NAME,
3095
+ inputFlag: DIARIST_SOURCES_FLAG.name,
3096
+ phaseFlag: void 0,
3097
+ activationStage: "load-and-install",
3098
+ sessionMaterials: [
3099
+ "CLAUDE.md",
3100
+ "souls/diarist.md",
3101
+ "resources/diarist-collect.md"
3102
+ ]
3043
3103
  }
3044
3104
  ];
3045
3105
  var PACKAGED_ROLE_REGISTRY = PUBLIC_ROLE_RECORDS.map(({ sessionMaterials: _omit, ...metadata }) => metadata);
@@ -5188,7 +5248,8 @@ var TERMINATING_TOOL_NAMES = [
5188
5248
  GLEANER_LEFT_OUTPUT_TOOL_NAME,
5189
5249
  INSPECTOR_OUTPUT_TOOL_NAME,
5190
5250
  GATEKEEPER_OUTPUT_TOOL_NAME,
5191
- NAVIGATOR_OUTPUT_TOOL_NAME
5251
+ NAVIGATOR_OUTPUT_TOOL_NAME,
5252
+ DIARIST_OUTPUT_TOOL_NAME
5192
5253
  ];
5193
5254
  function isTerminatingToolName(name) {
5194
5255
  return TERMINATING_TOOL_NAMES.includes(name);
@@ -5234,7 +5295,8 @@ function validateAcceptedDetails(toolName, details) {
5234
5295
  [GLEANER_LEFT_OUTPUT_TOOL_NAME]: ["completed"],
5235
5296
  [INSPECTOR_OUTPUT_TOOL_NAME]: ["pass", "bounce"],
5236
5297
  [GATEKEEPER_OUTPUT_TOOL_NAME]: ["dispatch", "pass"],
5237
- [NAVIGATOR_OUTPUT_TOOL_NAME]: ["advice"]
5298
+ [NAVIGATOR_OUTPUT_TOOL_NAME]: ["advice"],
5299
+ [DIARIST_OUTPUT_TOOL_NAME]: ["completed"]
5238
5300
  };
5239
5301
  const collectorDiscriminator = toolName === COLLECTOR_OUTPUT_TOOL && Array.isArray(candidate?.groups);
5240
5302
  const baseDiscriminator = discriminator;
@@ -5270,6 +5332,8 @@ function validateAcceptedDetails(toolName, details) {
5270
5332
  return validateRecordedGatekeeperOutput(details);
5271
5333
  case NAVIGATOR_OUTPUT_TOOL_NAME:
5272
5334
  return validateRecordedNavigatorOutput(details);
5335
+ case DIARIST_OUTPUT_TOOL_NAME:
5336
+ return validateRecordedDiaristOutput(details);
5273
5337
  }
5274
5338
  } catch (error) {
5275
5339
  if (error instanceof Error && error.constructor === Error) throw new AcceptedDetailsContractError(error.message, { cause: error });
@@ -5287,6 +5351,7 @@ function acceptedFacts(toolName, details) {
5287
5351
  case INSPECTOR_OUTPUT_TOOL_NAME:
5288
5352
  case GATEKEEPER_OUTPUT_TOOL_NAME:
5289
5353
  case NAVIGATOR_OUTPUT_TOOL_NAME:
5354
+ case DIARIST_OUTPUT_TOOL_NAME:
5290
5355
  return { status: details.status };
5291
5356
  case JUDGE_OUTPUT_TOOL_NAME:
5292
5357
  return { status: details.judgeStatus };
@@ -6593,6 +6658,10 @@ var COUNTERSIGN_OPTIONS = [
6593
6658
  bindOwner("countersign", SHARED_PROJECT_SEMANTICS),
6594
6659
  bindOwner("countersign", SHARED_ATTACH_SEMANTICS)
6595
6660
  ];
6661
+ var DIARIST_OPTIONS = [
6662
+ bindOwner("diarist", SHARED_PROJECT_SEMANTICS),
6663
+ bindOwner("diarist", SHARED_ATTACH_SEMANTICS)
6664
+ ];
6596
6665
  var CODER_OPTIONS = [
6597
6666
  {
6598
6667
  id: "phase",
@@ -6907,6 +6976,15 @@ var ROLE_COMMAND_HELP = {
6907
6976
  'ak-role navigator "\u521A\u5B8C\u6210 coder apply \u6536\u655B\uFF0C\u4E0B\u4E00\u6B65\uFF1F"'
6908
6977
  ]
6909
6978
  },
6979
+ diarist: {
6980
+ command: "diarist",
6981
+ summary: "Direct Diarist (\u8D77\u5C45\u90CE) pass: gather and organize this case's decision basis into its \u8D77\u5C45\u5F55.",
6982
+ usage: ["ak-role diarist [options] [instruction]"],
6983
+ examples: [
6984
+ 'ak-role diarist "\u6574\u7406 #708 \u7684\u672C\u6848\u4F9D\u636E\u3002"',
6985
+ 'ak-role diarist --attach ./design.md "\u8865\u5F55\u672C\u8F6E\u8BBE\u8BA1\u4FEE\u8BA2\u3002"'
6986
+ ]
6987
+ },
6910
6988
  notary: {
6911
6989
  command: "notary",
6912
6990
  summary: "Direct Notary document check (quote fidelity + ticket alignment); zero prompt/attachment.",
@@ -7075,7 +7153,7 @@ async function readRoleRunStateDisk(runDirectory) {
7075
7153
  if (typeof record4.runId !== "string" || record4.runId.trim() === "") {
7076
7154
  return void 0;
7077
7155
  }
7078
- if (record4.role !== "judge" && record4.role !== "coder" && record4.role !== "fixer" && record4.role !== "collector" && record4.role !== "doctor" && record4.role !== "reviewer" && record4.role !== "merger" && record4.role !== "notary" && record4.role !== "countersign" && record4.role !== "gleaner-left" && record4.role !== "inspector" && record4.role !== "gatekeeper" && record4.role !== "navigator") {
7156
+ if (record4.role !== "judge" && record4.role !== "coder" && record4.role !== "fixer" && record4.role !== "collector" && record4.role !== "doctor" && record4.role !== "reviewer" && record4.role !== "merger" && record4.role !== "notary" && record4.role !== "countersign" && record4.role !== "gleaner-left" && record4.role !== "inspector" && record4.role !== "gatekeeper" && record4.role !== "navigator" && record4.role !== "diarist") {
7079
7157
  return void 0;
7080
7158
  }
7081
7159
  if (record4.state !== "admitted" && record4.state !== "running" && record4.state !== "resumable" && record4.state !== "terminal") {
@@ -11297,6 +11375,561 @@ var INSPECTOR_TOOL_SPEC = {
11297
11375
  parameters: inspectorOutputSchema
11298
11376
  };
11299
11377
 
11378
+ // src/diarist-role.ts
11379
+ import { Type as Type23 } from "typebox";
11380
+ var diaristOutputSchema = withInfrastructureFailureDeclaration(
11381
+ openToolObject(
11382
+ Type23.Object({
11383
+ status: Type23.Unknown({
11384
+ description: "completed \u2014 \u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8"
11385
+ }),
11386
+ selections: Type23.Array(
11387
+ Type23.Object(
11388
+ {
11389
+ candidateIndex: Type23.Number({ description: "\u5019\u9009\u76EE\u5F55\u4E2D\u7684\u6574\u5757\u5E8F\u53F7" }),
11390
+ quotes: Type23.Array(Type23.String(), {
11391
+ description: "\u8BE5\u5757 transcript \u5185\u7684\u8FDE\u7EED\u539F\u6587\uFF1B\u673A\u68B0\u53CD\u9A8C"
11392
+ }),
11393
+ note: Type23.Optional(
11394
+ Type23.String({ description: "\u8BE5\u6750\u6599\u4E0E\u672C\u6848\u7684\u5173\u7CFB\uFF08\u4EBA\u8BFB\uFF09" })
11395
+ )
11396
+ },
11397
+ { additionalProperties: true, description: "\u4E00\u6761\u5165\u5F55\u9009\u62E9" }
11398
+ ),
11399
+ { description: "\u5165\u5F55\u9009\u62E9\uFF1B\u7A7A\u5217\u8868\u5408\u6CD5\u5B8C\u5C40" }
11400
+ )
11401
+ })
11402
+ )
11403
+ );
11404
+ var DIARIST_TOOL_SPEC = {
11405
+ name: DIARIST_OUTPUT_TOOL_NAME,
11406
+ label: "\u8D77\u5C45\u90CE\u8F93\u51FA",
11407
+ description: "\u8D77\u5C45\u90CE\u5165\u5F55\u9009\u62E9\u3002",
11408
+ promptSnippet: "\u8D77\u5C45\u90CE\u5165\u5F55\u9009\u62E9",
11409
+ parameters: diaristOutputSchema
11410
+ };
11411
+
11412
+ // src/diarist.ts
11413
+ import { readFileSync as readFileSync4 } from "node:fs";
11414
+
11415
+ // src/diarist-mechanical.ts
11416
+ init_activation_ledger_topology();
11417
+ var DEFAULT_QUOTE_MIN = 6;
11418
+ function extractCornerQuotes(text, minLength = DEFAULT_QUOTE_MIN) {
11419
+ const out = [];
11420
+ const re = /「([^」]+)」/g;
11421
+ let match;
11422
+ while ((match = re.exec(text)) !== null) {
11423
+ const q = match[1].trim();
11424
+ if (q.length >= minLength) out.push(q);
11425
+ }
11426
+ return out;
11427
+ }
11428
+ function buildDiaristAnchors(input) {
11429
+ const fromBody = input.ticketBody === void 0 ? [] : extractCornerQuotes(input.ticketBody);
11430
+ const quotes = [...fromBody, ...input.extraQuotes ?? []];
11431
+ const seen = /* @__PURE__ */ new Set();
11432
+ const uniqueQuotes = [];
11433
+ for (const q of quotes) {
11434
+ if (seen.has(q)) continue;
11435
+ seen.add(q);
11436
+ uniqueQuotes.push(q);
11437
+ }
11438
+ return {
11439
+ ticketNumber: input.ticketNumber,
11440
+ quotes: uniqueQuotes
11441
+ };
11442
+ }
11443
+ function verifyQuotesVerbatim(sourceText, quotes) {
11444
+ const failed2 = [];
11445
+ for (const q of quotes) {
11446
+ if (q.length === 0) continue;
11447
+ if (!sourceText.includes(q)) failed2.push(q);
11448
+ }
11449
+ if (failed2.length === 0) return { ok: true };
11450
+ return { ok: false, failedQuotes: failed2 };
11451
+ }
11452
+ function blockToLlmEntry(block, input) {
11453
+ const verify = verifyQuotesVerbatim(block.transcript, input.quotes);
11454
+ if (!verify.ok) {
11455
+ return {
11456
+ ok: false,
11457
+ failedQuotes: verify.failedQuotes,
11458
+ cause: `verbatim verify failed: ${verify.failedQuotes.join(" | ")}`
11459
+ };
11460
+ }
11461
+ const anchorNotes = [`#${input.anchors.ticketNumber}`];
11462
+ const seen = new Set(anchorNotes);
11463
+ for (const q of [...input.anchors.quotes, ...input.quotes]) {
11464
+ if (seen.has(q)) continue;
11465
+ seen.add(q);
11466
+ anchorNotes.push(q);
11467
+ if (anchorNotes.length >= 12) break;
11468
+ }
11469
+ return {
11470
+ ok: true,
11471
+ entry: {
11472
+ basis: {
11473
+ method: "llm-semantic",
11474
+ anchors: anchorNotes,
11475
+ ...input.note === void 0 ? {} : { note: input.note }
11476
+ },
11477
+ sourceKind: block.sourceKind,
11478
+ sourceRef: block.sourceRef,
11479
+ transcript: block.transcript,
11480
+ timestamp: block.timestamp
11481
+ }
11482
+ };
11483
+ }
11484
+
11485
+ // src/ticket-provenance.ts
11486
+ import { createHash as createHash9 } from "node:crypto";
11487
+ import { appendFileSync as appendFileSync2, existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync6 } from "node:fs";
11488
+ import { join as join22 } from "node:path";
11489
+
11490
+ // src/ticket-provenance-contracts.ts
11491
+ var TICKET_PROVENANCE_KIND = "ticket-provenance";
11492
+ var TICKET_PROVENANCE_HUMAN_VIEW = "\u8D77\u5C45\u5F55.md";
11493
+ var TICKET_PROVENANCE_OFFERED_WATERMARK = "offered-identities.jsonl";
11494
+ var TICKET_PROVENANCE_RECORD_CLASS_DIAGNOSTIC = "diagnostic";
11495
+ function isRecord13(value) {
11496
+ return typeof value === "object" && value !== null && !Array.isArray(value);
11497
+ }
11498
+ var SOURCE_KINDS = /* @__PURE__ */ new Set([
11499
+ "cc-session",
11500
+ "issue-body-comment",
11501
+ "adr-decision-key",
11502
+ "ticket-decree-block"
11503
+ ]);
11504
+ var BASIS_METHODS = /* @__PURE__ */ new Set(["llm-semantic"]);
11505
+ var DIAGNOSTIC_KINDS = /* @__PURE__ */ new Set([
11506
+ "collector-failed",
11507
+ "issue-source-failed",
11508
+ "quote-verify-failed"
11509
+ ]);
11510
+ function projectTicketProvenanceDiagnostic(value) {
11511
+ if (!isRecord13(value)) return void 0;
11512
+ if (value.recordClass !== TICKET_PROVENANCE_RECORD_CLASS_DIAGNOSTIC) {
11513
+ return void 0;
11514
+ }
11515
+ if (typeof value.diagnosticKind !== "string" || !DIAGNOSTIC_KINDS.has(value.diagnosticKind)) {
11516
+ return void 0;
11517
+ }
11518
+ if (typeof value.cause !== "string" || value.cause.length === 0) {
11519
+ return void 0;
11520
+ }
11521
+ if (typeof value.recordedAt !== "string" || value.recordedAt.length === 0) {
11522
+ return void 0;
11523
+ }
11524
+ return {
11525
+ recordClass: TICKET_PROVENANCE_RECORD_CLASS_DIAGNOSTIC,
11526
+ diagnosticKind: value.diagnosticKind,
11527
+ cause: value.cause,
11528
+ recordedAt: value.recordedAt,
11529
+ ...typeof value.reason === "string" ? { reason: value.reason } : {}
11530
+ };
11531
+ }
11532
+ function projectTicketProvenanceEntry(value) {
11533
+ if (!isRecord13(value)) return void 0;
11534
+ if (value.recordClass === TICKET_PROVENANCE_RECORD_CLASS_DIAGNOSTIC) {
11535
+ return void 0;
11536
+ }
11537
+ if (!isRecord13(value.basis)) return void 0;
11538
+ if (typeof value.basis.method !== "string" || !BASIS_METHODS.has(value.basis.method)) {
11539
+ return void 0;
11540
+ }
11541
+ if (typeof value.sourceKind !== "string" || !SOURCE_KINDS.has(value.sourceKind)) {
11542
+ return void 0;
11543
+ }
11544
+ if (!isRecord13(value.sourceRef)) return void 0;
11545
+ if (typeof value.transcript !== "string" || value.transcript.length === 0) {
11546
+ return void 0;
11547
+ }
11548
+ if (typeof value.timestamp !== "string" || value.timestamp.length === 0) {
11549
+ return void 0;
11550
+ }
11551
+ const basis = {
11552
+ method: value.basis.method,
11553
+ ...Array.isArray(value.basis.anchors) ? {
11554
+ anchors: value.basis.anchors.filter(
11555
+ (item) => typeof item === "string"
11556
+ )
11557
+ } : {},
11558
+ ...typeof value.basis.note === "string" ? { note: value.basis.note } : {}
11559
+ };
11560
+ const sourceRef = {
11561
+ ...typeof value.sourceRef.sessionFile === "string" ? { sessionFile: value.sourceRef.sessionFile } : {},
11562
+ ...typeof value.sourceRef.entryId === "string" || typeof value.sourceRef.entryId === "number" ? { entryId: value.sourceRef.entryId } : {},
11563
+ ...typeof value.sourceRef.path === "string" ? { path: value.sourceRef.path } : {},
11564
+ ...typeof value.sourceRef.url === "string" ? { url: value.sourceRef.url } : {}
11565
+ };
11566
+ return {
11567
+ basis,
11568
+ sourceKind: value.sourceKind,
11569
+ sourceRef,
11570
+ transcript: value.transcript,
11571
+ timestamp: value.timestamp
11572
+ };
11573
+ }
11574
+
11575
+ // src/ticket-provenance.ts
11576
+ function ticketProvenanceSubject(ticketNumber) {
11577
+ if (!Number.isSafeInteger(ticketNumber) || ticketNumber < 1) {
11578
+ throw new Error(`ticket-provenance subject requires a positive ticket number, got ${String(ticketNumber)}`);
11579
+ }
11580
+ return String(ticketNumber);
11581
+ }
11582
+ function ticketProvenanceEntryIdentity(input) {
11583
+ const ref = input.sourceRef;
11584
+ const refKey = [
11585
+ ref.sessionFile ?? "",
11586
+ ref.entryId === void 0 ? "" : String(ref.entryId),
11587
+ ref.path ?? "",
11588
+ ref.url ?? ""
11589
+ ].join("");
11590
+ const material = [
11591
+ String(input.ticketNumber),
11592
+ input.sourceKind,
11593
+ refKey,
11594
+ input.transcript
11595
+ ].join("\0");
11596
+ return createHash9("sha256").update(material, "utf8").digest("hex");
11597
+ }
11598
+ function appendTicketProvenanceEntry(input) {
11599
+ const subject = ticketProvenanceSubject(input.ticketNumber);
11600
+ const identity = ticketProvenanceEntryIdentity({
11601
+ ticketNumber: input.ticketNumber,
11602
+ sourceKind: input.entry.sourceKind,
11603
+ sourceRef: input.entry.sourceRef,
11604
+ transcript: input.entry.transcript
11605
+ });
11606
+ return sitianReport({
11607
+ level: "event",
11608
+ kind: TICKET_PROVENANCE_KIND,
11609
+ identity,
11610
+ subject,
11611
+ cwd: input.cwd,
11612
+ ...input.home === void 0 ? {} : { home: input.home },
11613
+ host: input.host ?? "diarist",
11614
+ source: input.source ?? "diarist",
11615
+ payload: input.entry,
11616
+ raw: input.entry.sourceRef.sessionFile !== void 0 && input.entry.sourceRef.entryId !== void 0 ? {
11617
+ sessionFile: input.entry.sourceRef.sessionFile,
11618
+ entryId: input.entry.sourceRef.entryId
11619
+ } : void 0
11620
+ });
11621
+ }
11622
+ function resolveTicketProvenanceVolume(ticketNumber, cwd, home) {
11623
+ const path = resolveSitianRecordPath({
11624
+ level: "event",
11625
+ kind: TICKET_PROVENANCE_KIND,
11626
+ subject: ticketProvenanceSubject(ticketNumber),
11627
+ cwd,
11628
+ ...home === void 0 ? {} : { home }
11629
+ });
11630
+ return {
11631
+ recordFile: path.recordFile,
11632
+ volumeDir: path.sessionDir,
11633
+ humanViewFile: join22(path.sessionDir, TICKET_PROVENANCE_HUMAN_VIEW),
11634
+ offeredWatermarkFile: join22(path.sessionDir, TICKET_PROVENANCE_OFFERED_WATERMARK)
11635
+ };
11636
+ }
11637
+ var TicketProvenanceWatermarkError = class extends Error {
11638
+ code = "ticket-provenance-watermark";
11639
+ reason;
11640
+ constructor(reason, message, options) {
11641
+ super(message, options);
11642
+ this.name = "TicketProvenanceWatermarkError";
11643
+ this.reason = reason;
11644
+ }
11645
+ };
11646
+ function readOfferedIdentities(ticketNumber, cwd, home) {
11647
+ const { offeredWatermarkFile } = resolveTicketProvenanceVolume(ticketNumber, cwd, home);
11648
+ if (!existsSync7(offeredWatermarkFile)) return /* @__PURE__ */ new Set();
11649
+ let text;
11650
+ try {
11651
+ text = readFileSync3(offeredWatermarkFile, "utf8");
11652
+ } catch (error) {
11653
+ throw new TicketProvenanceWatermarkError(
11654
+ "unreadable",
11655
+ `ticket-provenance offered watermark unreadable (${offeredWatermarkFile})`,
11656
+ { cause: error }
11657
+ );
11658
+ }
11659
+ const seen = /* @__PURE__ */ new Set();
11660
+ const lines = text.split("\n");
11661
+ for (let index = 0; index < lines.length; index += 1) {
11662
+ const trimmed = lines[index].trim();
11663
+ if (!trimmed) continue;
11664
+ let parsed;
11665
+ try {
11666
+ parsed = JSON.parse(trimmed);
11667
+ } catch (error) {
11668
+ throw new TicketProvenanceWatermarkError(
11669
+ "malformed-json",
11670
+ `ticket-provenance offered watermark malformed JSON at line ${index + 1} (${offeredWatermarkFile})`,
11671
+ { cause: error }
11672
+ );
11673
+ }
11674
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed) || typeof parsed.identity !== "string" || parsed.identity.length === 0) {
11675
+ throw new TicketProvenanceWatermarkError(
11676
+ "bad-shape",
11677
+ `ticket-provenance offered watermark bad shape at line ${index + 1} (${offeredWatermarkFile})`
11678
+ );
11679
+ }
11680
+ seen.add(parsed.identity);
11681
+ }
11682
+ return seen;
11683
+ }
11684
+ function recordOfferedIdentities(input) {
11685
+ if (input.identities.length === 0) return;
11686
+ const { volumeDir, offeredWatermarkFile } = resolveTicketProvenanceVolume(
11687
+ input.ticketNumber,
11688
+ input.cwd,
11689
+ input.home
11690
+ );
11691
+ const already = new Set(readOfferedIdentities(input.ticketNumber, input.cwd, input.home));
11692
+ const rows = [];
11693
+ for (const identity of input.identities) {
11694
+ if (identity.length === 0 || already.has(identity)) continue;
11695
+ rows.push(`${JSON.stringify({ identity })}
11696
+ `);
11697
+ already.add(identity);
11698
+ }
11699
+ if (rows.length === 0) return;
11700
+ mkdirSync3(volumeDir, { recursive: true });
11701
+ appendFileSync2(offeredWatermarkFile, rows.join(""), "utf8");
11702
+ }
11703
+ async function readTicketProvenance(ticketNumber, cwd, home) {
11704
+ const { recordFile } = resolveTicketProvenanceVolume(ticketNumber, cwd, home);
11705
+ const { records: records2 } = await readSitianRecords(recordFile);
11706
+ const entries = [];
11707
+ const diagnostics = [];
11708
+ let skipped = 0;
11709
+ for (const record4 of records2) {
11710
+ if (record4.kind !== TICKET_PROVENANCE_KIND) {
11711
+ skipped += 1;
11712
+ continue;
11713
+ }
11714
+ const diagnostic = projectTicketProvenanceDiagnostic(record4.payload);
11715
+ if (diagnostic !== void 0) {
11716
+ diagnostics.push(diagnostic);
11717
+ continue;
11718
+ }
11719
+ const entry = projectTicketProvenanceEntry(record4.payload);
11720
+ if (entry === void 0) {
11721
+ skipped += 1;
11722
+ continue;
11723
+ }
11724
+ entries.push(entry);
11725
+ }
11726
+ return { entries, diagnostics, records: records2, recordFile, skipped };
11727
+ }
11728
+ function markdownFenceFor(text) {
11729
+ let longest = 0;
11730
+ const runs = text.match(/`+/g);
11731
+ if (runs !== null) {
11732
+ for (const run of runs) {
11733
+ if (run.length > longest) longest = run.length;
11734
+ }
11735
+ }
11736
+ return "`".repeat(Math.max(3, longest + 1));
11737
+ }
11738
+ function renderTicketProvenanceMarkdown(input) {
11739
+ const lines = [
11740
+ `# \u8D77\u5C45\u5F55 \xB7 #${input.ticketNumber}`,
11741
+ "",
11742
+ `\u6761\u76EE\u6570\uFF1A${input.entries.length}`,
11743
+ ""
11744
+ ];
11745
+ let index = 0;
11746
+ for (const entry of input.entries) {
11747
+ index += 1;
11748
+ lines.push(`## ${index}. ${entry.sourceKind} \xB7 ${entry.timestamp}`);
11749
+ lines.push("");
11750
+ lines.push(`- basis.method: \`${entry.basis.method}\``);
11751
+ if (entry.basis.anchors !== void 0 && entry.basis.anchors.length > 0) {
11752
+ lines.push(`- anchors: ${entry.basis.anchors.map((a) => `\`${a}\``).join(", ")}`);
11753
+ }
11754
+ if (entry.basis.note !== void 0) {
11755
+ lines.push(`- note: ${entry.basis.note}`);
11756
+ }
11757
+ const refParts = [];
11758
+ if (entry.sourceRef.sessionFile !== void 0) {
11759
+ refParts.push(`sessionFile=${entry.sourceRef.sessionFile}`);
11760
+ }
11761
+ if (entry.sourceRef.entryId !== void 0) {
11762
+ refParts.push(`entryId=${String(entry.sourceRef.entryId)}`);
11763
+ }
11764
+ if (entry.sourceRef.path !== void 0) {
11765
+ refParts.push(`path=${entry.sourceRef.path}`);
11766
+ }
11767
+ if (entry.sourceRef.url !== void 0) {
11768
+ refParts.push(`url=${entry.sourceRef.url}`);
11769
+ }
11770
+ if (refParts.length > 0) {
11771
+ lines.push(`- sourceRef: ${refParts.join(" \xB7 ")}`);
11772
+ }
11773
+ lines.push("");
11774
+ const fence = markdownFenceFor(entry.transcript);
11775
+ lines.push(fence);
11776
+ lines.push(entry.transcript);
11777
+ lines.push(fence);
11778
+ lines.push("");
11779
+ }
11780
+ return lines.join("\n");
11781
+ }
11782
+ function ensureTicketProvenanceVolume(ticketNumber, cwd, home) {
11783
+ const volume = resolveTicketProvenanceVolume(ticketNumber, cwd, home);
11784
+ mkdirSync3(volume.volumeDir, { recursive: true });
11785
+ appendFileSync2(volume.recordFile, "", "utf8");
11786
+ return volume;
11787
+ }
11788
+ function appendTicketProvenanceDiagnostic(input) {
11789
+ const subject = ticketProvenanceSubject(input.ticketNumber);
11790
+ const identityParts = input.diagnostic.diagnosticKind === "quote-verify-failed" ? [
11791
+ subject,
11792
+ input.diagnostic.recordClass,
11793
+ input.diagnostic.diagnosticKind,
11794
+ input.diagnostic.cause,
11795
+ input.diagnostic.reason ?? ""
11796
+ ] : [
11797
+ subject,
11798
+ input.diagnostic.recordClass,
11799
+ input.diagnostic.diagnosticKind,
11800
+ input.diagnostic.recordedAt,
11801
+ input.diagnostic.cause,
11802
+ input.diagnostic.reason ?? ""
11803
+ ];
11804
+ const identity = createHash9("sha256").update(identityParts.join("\0"), "utf8").digest("hex");
11805
+ return sitianReport({
11806
+ level: "event",
11807
+ kind: TICKET_PROVENANCE_KIND,
11808
+ identity,
11809
+ subject,
11810
+ cwd: input.cwd,
11811
+ ...input.home === void 0 ? {} : { home: input.home },
11812
+ host: input.host ?? "diarist",
11813
+ source: input.source ?? "diarist-diagnostic",
11814
+ payload: input.diagnostic
11815
+ });
11816
+ }
11817
+ function appendQuoteVerifyFailureDiagnostic(input) {
11818
+ const recordedAt = input.recordedAt ?? (/* @__PURE__ */ new Date()).toISOString();
11819
+ return appendTicketProvenanceDiagnostic({
11820
+ ticketNumber: input.ticketNumber,
11821
+ cwd: input.cwd,
11822
+ ...input.home === void 0 ? {} : { home: input.home },
11823
+ source: "diarist-quote-verify",
11824
+ diagnostic: {
11825
+ recordClass: TICKET_PROVENANCE_RECORD_CLASS_DIAGNOSTIC,
11826
+ diagnosticKind: "quote-verify-failed",
11827
+ cause: input.cause,
11828
+ recordedAt
11829
+ }
11830
+ });
11831
+ }
11832
+ function writeTicketProvenanceHumanView(input) {
11833
+ const volume = ensureTicketProvenanceVolume(input.ticketNumber, input.cwd, input.home);
11834
+ const md = renderTicketProvenanceMarkdown({
11835
+ ticketNumber: input.ticketNumber,
11836
+ entries: input.entries
11837
+ });
11838
+ writeFileSync6(volume.humanViewFile, md, "utf8");
11839
+ return volume.humanViewFile;
11840
+ }
11841
+
11842
+ // src/diarist.ts
11843
+ function blockEntryIdentity(ticketNumber, block) {
11844
+ return ticketProvenanceEntryIdentity({
11845
+ ticketNumber,
11846
+ sourceKind: block.sourceKind,
11847
+ sourceRef: block.sourceRef,
11848
+ transcript: block.transcript
11849
+ });
11850
+ }
11851
+ function loadDiaristSourceCatalog(path) {
11852
+ const parsed = JSON.parse(readFileSync4(path, "utf8"));
11853
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
11854
+ throw new Error(`diarist source catalog is not an object (${path})`);
11855
+ }
11856
+ const record4 = parsed;
11857
+ if (typeof record4.ticketNumber !== "number" || typeof record4.cwd !== "string") {
11858
+ throw new Error(`diarist source catalog is missing ticket coordinates (${path})`);
11859
+ }
11860
+ if (!Array.isArray(record4.candidates)) {
11861
+ throw new Error(`diarist source catalog is missing candidates (${path})`);
11862
+ }
11863
+ return parsed;
11864
+ }
11865
+ async function commitDiaristSelections(input) {
11866
+ const { ticketNumber, cwd } = input.catalog;
11867
+ const homeOpt = input.catalog.home === void 0 ? {} : { home: input.catalog.home };
11868
+ const volumePaths = ensureTicketProvenanceVolume(ticketNumber, cwd, input.catalog.home);
11869
+ const anchors = buildDiaristAnchors({ ticketNumber });
11870
+ const before = await readTicketProvenance(ticketNumber, cwd, input.catalog.home);
11871
+ let acceptedRows = 0;
11872
+ let rejectedQuotes = 0;
11873
+ let unknownCandidate = false;
11874
+ for (const selection of input.selections) {
11875
+ const block = input.catalog.candidates[selection.candidateIndex];
11876
+ if (block === void 0) {
11877
+ unknownCandidate = true;
11878
+ continue;
11879
+ }
11880
+ const projected = blockToLlmEntry(block, {
11881
+ anchors,
11882
+ quotes: selection.quotes,
11883
+ ...selection.note === void 0 ? {} : { note: selection.note }
11884
+ });
11885
+ if (!projected.ok) {
11886
+ rejectedQuotes += 1;
11887
+ appendQuoteVerifyFailureDiagnostic({
11888
+ ticketNumber,
11889
+ cwd,
11890
+ ...homeOpt,
11891
+ cause: projected.cause
11892
+ });
11893
+ continue;
11894
+ }
11895
+ appendTicketProvenanceEntry({
11896
+ ticketNumber,
11897
+ cwd,
11898
+ ...homeOpt,
11899
+ entry: projected.entry,
11900
+ source: "diarist"
11901
+ });
11902
+ acceptedRows += 1;
11903
+ }
11904
+ const identities = input.catalog.candidates.map(
11905
+ (block) => blockEntryIdentity(ticketNumber, block)
11906
+ );
11907
+ const alreadyWatermarked = readOfferedIdentities(ticketNumber, cwd, input.catalog.home);
11908
+ const watermarked = identities.filter((identity) => !alreadyWatermarked.has(identity)).length;
11909
+ recordOfferedIdentities({ ticketNumber, cwd, ...homeOpt, identities });
11910
+ const volume = await readTicketProvenance(ticketNumber, cwd, input.catalog.home);
11911
+ const humanViewFile = writeTicketProvenanceHumanView({
11912
+ ticketNumber,
11913
+ cwd,
11914
+ ...homeOpt,
11915
+ entries: volume.entries
11916
+ });
11917
+ return {
11918
+ ticketNumber,
11919
+ offered: input.catalog.candidates.length,
11920
+ appended: volume.entries.length - before.entries.length,
11921
+ rejectedQuotes,
11922
+ watermarked,
11923
+ volumeRecordFile: volumePaths.recordFile,
11924
+ humanViewFile,
11925
+ collectorStatus: input.catalog.candidates.length === 0 ? "skipped-no-fresh" : acceptedRows > 0 ? "ok" : input.selections.length === 0 ? "empty-selection" : "nothing-appended",
11926
+ failureCauses: [
11927
+ ...unknownCandidate ? ["unknown-candidate"] : [],
11928
+ ...rejectedQuotes > 0 ? ["quote-verify-rejected"] : []
11929
+ ]
11930
+ };
11931
+ }
11932
+
11300
11933
  // src/navigator-role.ts
11301
11934
  var NAVIGATOR_TOOL_SPEC = {
11302
11935
  name: NAVIGATOR_OUTPUT_TOOL_NAME,
@@ -11348,30 +11981,30 @@ function raceNavigatorGrace(work, graceMs = NAVIGATOR_POST_ROLE_GRACE_MS, sleep
11348
11981
  }
11349
11982
 
11350
11983
  // src/judge-role.ts
11351
- import { Type as Type23 } from "typebox";
11984
+ import { Type as Type24 } from "typebox";
11352
11985
  var judgeVerdictSchema = withInfrastructureFailureDeclaration(
11353
- Type23.Object(
11986
+ Type24.Object(
11354
11987
  {
11355
11988
  judgeStatus: stringEnum(["converged", "continue", "escalate"], { description: "converged | continue | escalate \u2014 \u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8" }),
11356
- fix: Type23.Optional(
11357
- Type23.Object(
11358
- { summary: Type23.String({ minLength: 1, description: "continue \u65F6\u7684\u8865\u6551\u6458\u8981" }) },
11989
+ fix: Type24.Optional(
11990
+ Type24.Object(
11991
+ { summary: Type24.String({ minLength: 1, description: "continue \u65F6\u7684\u8865\u6551\u6458\u8981" }) },
11359
11992
  { additionalProperties: false, description: "continue \u65F6\u7684\u8865\u6551\u8BF4\u660E" }
11360
11993
  )
11361
11994
  ),
11362
- classes: Type23.Optional(Type23.Array(Type23.Object({
11363
- name: Type23.String({ minLength: 1 }),
11364
- owner: Type23.String({ minLength: 1 }),
11365
- boundary: Type23.String({ minLength: 1 }),
11366
- disposition: Type23.String({ minLength: 1 })
11995
+ classes: Type24.Optional(Type24.Array(Type24.Object({
11996
+ name: Type24.String({ minLength: 1 }),
11997
+ owner: Type24.String({ minLength: 1 }),
11998
+ boundary: Type24.String({ minLength: 1 }),
11999
+ disposition: Type24.String({ minLength: 1 })
11367
12000
  }, { additionalProperties: false }), { minItems: 1, description: "\u5DF2\u88C1\u51B3 finding \u7C7B\u53CA\u5176 owner \u4E0E\u4FEE\u7406\u8FB9\u754C" })),
11368
- note: Type23.Optional(Type23.String({ minLength: 1, description: "\u53EF\u9009\u88C1\u51B3\u9644\u6CE8" })),
11369
- evidence: Type23.Optional(Type23.Unknown({ description: "\u7559\u5B58\u7684\u88C1\u51B3\u8BC1\u636E" })),
11370
- decisionGate: Type23.Optional(
11371
- Type23.Object(
12001
+ note: Type24.Optional(Type24.String({ minLength: 1, description: "\u53EF\u9009\u88C1\u51B3\u9644\u6CE8" })),
12002
+ evidence: Type24.Optional(Type24.Unknown({ description: "\u7559\u5B58\u7684\u88C1\u51B3\u8BC1\u636E" })),
12003
+ decisionGate: Type24.Optional(
12004
+ Type24.Object(
11372
12005
  {
11373
- question: Type23.String({ minLength: 1 }),
11374
- options: Type23.Array(Type23.String({ minLength: 1 }), { minItems: 1 })
12006
+ question: Type24.String({ minLength: 1 }),
12007
+ options: Type24.Array(Type24.String({ minLength: 1 }), { minItems: 1 })
11375
12008
  },
11376
12009
  { additionalProperties: false, description: "\u9700\u4EBA\u6743\u5A01\u5904\u7F6E\u7684\u95EE\u9898\u4E0E\u9009\u9879" }
11377
12010
  )
@@ -11461,7 +12094,7 @@ ${soul}
11461
12094
  }
11462
12095
 
11463
12096
  // src/reviewer-role.ts
11464
- import { Type as Type24 } from "typebox";
12097
+ import { Type as Type25 } from "typebox";
11465
12098
 
11466
12099
  // src/reviewer-execution-ledger.ts
11467
12100
  function projectAcceptedDispatch(dispatch) {
@@ -11667,19 +12300,19 @@ function assembleRuntimeReviewerReceipt(input) {
11667
12300
  }
11668
12301
 
11669
12302
  // src/reviewer-role.ts
11670
- var reviewerAmendmentsSchema = Type24.Object({
11671
- standards: Type24.Optional(Type24.String({ description: "\u76F8\u5BF9 Standards \u5B50\u62A5\u544A\u7684\u589E\u91CF\uFF1A\u589E finding\u3001\u64A4\u56DE\u6216\u4E8B\u5B9E\u66F4\u6B63" })),
11672
- spec: Type24.Optional(Type24.String({ description: "\u76F8\u5BF9 Spec \u5B50\u62A5\u544A\u7684\u589E\u91CF\uFF1A\u589E finding\u3001\u64A4\u56DE\u6216\u4E8B\u5B9E\u66F4\u6B63" }))
12303
+ var reviewerAmendmentsSchema = Type25.Object({
12304
+ standards: Type25.Optional(Type25.String({ description: "\u76F8\u5BF9 Standards \u5B50\u62A5\u544A\u7684\u589E\u91CF\uFF1A\u589E finding\u3001\u64A4\u56DE\u6216\u4E8B\u5B9E\u66F4\u6B63" })),
12305
+ spec: Type25.Optional(Type25.String({ description: "\u76F8\u5BF9 Spec \u5B50\u62A5\u544A\u7684\u589E\u91CF\uFF1A\u589E finding\u3001\u64A4\u56DE\u6216\u4E8B\u5B9E\u66F4\u6B63" }))
11673
12306
  }, { additionalProperties: true, description: "\u76F8\u5BF9\u5B50\u62A5\u544A\u7684\u53EF\u9009\u8F74\u589E\u91CF\uFF1B\u975E\u66FF\u4EE3\u62A5\u544A\u3002\u65E0\u589E\u91CF\u7684\u8F74\u53EF\u7701\u7565\u3002" });
11674
- var reviewerOutputVariants = Type24.Union([
11675
- Type24.Object({
11676
- status: Type24.Literal("completed", { description: "completed \u2014 \u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8" }),
11677
- amendments: Type24.Optional(reviewerAmendmentsSchema)
12307
+ var reviewerOutputVariants = Type25.Union([
12308
+ Type25.Object({
12309
+ status: Type25.Literal("completed", { description: "completed \u2014 \u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8" }),
12310
+ amendments: Type25.Optional(reviewerAmendmentsSchema)
11678
12311
  }, { additionalProperties: false }),
11679
- Type24.Object({
11680
- status: Type24.Literal("refused", { description: "refused \u2014 \u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8" }),
11681
- diagnostic: Type24.String({ minLength: 1, description: "\u62D2\u7EDD\u8BCA\u65AD\u8BF4\u660E" }),
11682
- amendments: Type24.Optional(reviewerAmendmentsSchema)
12312
+ Type25.Object({
12313
+ status: Type25.Literal("refused", { description: "refused \u2014 \u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8" }),
12314
+ diagnostic: Type25.String({ minLength: 1, description: "\u62D2\u7EDD\u8BCA\u65AD\u8BF4\u660E" }),
12315
+ amendments: Type25.Optional(reviewerAmendmentsSchema)
11683
12316
  }, { additionalProperties: false })
11684
12317
  ]);
11685
12318
  var reviewerOutputSchema = withInfrastructureFailureDeclaration(
@@ -11807,12 +12440,12 @@ function createReviewerRoleRuntime(pi, dependencies, hostActions) {
11807
12440
  }
11808
12441
 
11809
12442
  // src/worker-role.ts
11810
- import { Type as Type25 } from "typebox";
12443
+ import { Type as Type26 } from "typebox";
11811
12444
 
11812
12445
  // src/worker-submission-gates.ts
11813
12446
  init_archivist_record_entry();
11814
12447
  import { execFileSync as execFileSync2 } from "node:child_process";
11815
- import { existsSync as existsSync7, lstatSync as lstatSync3, readdirSync as readdirSync2, readFileSync as readFileSync3, rmdirSync, rmSync } from "node:fs";
12448
+ import { existsSync as existsSync8, lstatSync as lstatSync3, readdirSync as readdirSync2, readFileSync as readFileSync5, rmdirSync, rmSync } from "node:fs";
11816
12449
  import { resolve as resolve16 } from "node:path";
11817
12450
  var WORKER_SUBMISSION_GATE_RECORD_KIND = WORKER_SUBMISSION_GATE_KIND;
11818
12451
  var WORKER_COMMIT_BASELINE_ENTRY_TYPE = "commit-baseline";
@@ -11843,7 +12476,7 @@ function statusOf(error) {
11843
12476
  return typeof error === "object" && error !== null && "status" in error ? error.status : void 0;
11844
12477
  }
11845
12478
  function tryGetAll(file, key) {
11846
- if (!existsSync7(file)) return [];
12479
+ if (!existsSync8(file)) return [];
11847
12480
  try {
11848
12481
  const out = gitFile(file, ["--get-all", key]);
11849
12482
  return out.length === 0 ? [] : out.split("\n");
@@ -11853,8 +12486,8 @@ function tryGetAll(file, key) {
11853
12486
  }
11854
12487
  }
11855
12488
  function ownedHook(path) {
11856
- if (!existsSync7(path)) return false;
11857
- return readFileSync3(path, "utf8").includes(HOOK_MARKER);
12489
+ if (!existsSync8(path)) return false;
12490
+ return readFileSync5(path, "utf8").includes(HOOK_MARKER);
11858
12491
  }
11859
12492
  function escapeGitConfigValueRegex(value) {
11860
12493
  return value.replace(/[\\^$.*+?()[\]{}|]/g, "\\$&");
@@ -11880,11 +12513,11 @@ function rmOwnedDir(dir) {
11880
12513
  const hookPath = resolve16(dir, HOOK_FILE);
11881
12514
  if (!ownedHook(hookPath)) return;
11882
12515
  rmSync(hookPath, { force: true });
11883
- if (existsSync7(dir) && readdirSync2(dir).length === 0) rmdirSync(dir);
12516
+ if (existsSync8(dir) && readdirSync2(dir).length === 0) rmdirSync(dir);
11884
12517
  }
11885
12518
  function linkedGitDirs(commonDir) {
11886
12519
  const root = resolve16(commonDir, "worktrees");
11887
- if (!existsSync7(root)) return [];
12520
+ if (!existsSync8(root)) return [];
11888
12521
  return readdirSync2(root).map((name) => resolve16(root, name)).filter((dir) => lstatSync3(dir).isDirectory());
11889
12522
  }
11890
12523
  function uninstallPackageWorkerHooks(cwd) {
@@ -11909,7 +12542,7 @@ function uninstallPackageWorkerHooks(cwd) {
11909
12542
  rmOwnedDir(resolve16(gitDir, HOOKS_DIR));
11910
12543
  }
11911
12544
  }
11912
- function isRecord13(value) {
12545
+ function isRecord14(value) {
11913
12546
  return typeof value === "object" && value !== null && !Array.isArray(value);
11914
12547
  }
11915
12548
  function unfinishedReasonPresent(details) {
@@ -11925,7 +12558,7 @@ function readGateState(session) {
11925
12558
  if (entry.type !== "custom") continue;
11926
12559
  if (entry.customType === WORKER_COMMIT_BASELINE_ENTRY_TYPE) {
11927
12560
  const data = entry.data;
11928
- if (isRecord13(data) && (data.head === null || typeof data.head === "string")) {
12561
+ if (isRecord14(data) && (data.head === null || typeof data.head === "string")) {
11929
12562
  baseline = data.head;
11930
12563
  }
11931
12564
  } else if (entry.customType === WORKER_COMMIT_REMINDER_BOUNCE_ENTRY_TYPE) {
@@ -12068,24 +12701,24 @@ function fixerBashSeatbeltDenyReason(matched) {
12068
12701
  }
12069
12702
 
12070
12703
  // src/worker-role.ts
12071
- var coderOutputVariants = Type25.Union([
12072
- Type25.Object({
12704
+ var coderOutputVariants = Type26.Union([
12705
+ Type26.Object({
12073
12706
  status: stringEnum(["planned"], { description: "planned \u2014 \u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8" }),
12074
- report: Type25.String({ minLength: 1, description: "\u5982\u5B9E\u7ED3\u679C\u62A5\u544A" })
12707
+ report: Type26.String({ minLength: 1, description: "\u5982\u5B9E\u7ED3\u679C\u62A5\u544A" })
12075
12708
  }, { additionalProperties: false }),
12076
- Type25.Object({
12709
+ Type26.Object({
12077
12710
  status: stringEnum(["completed", "refused"], {
12078
12711
  description: "completed | refused \u2014 \u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8\uFF1Bcompleted \u56DE\u6267\u542B TDD\u3001\u540C\u6A21\u5F0F\u3001\u5F15\u5165\u56DE\u5F52\u3001\u884C\u4E3A\u4E8B\u5B9E\u56DB\u9879\u8BC1\u636E"
12079
12712
  }),
12080
- report: Type25.String({ minLength: 1, description: "\u5982\u5B9E\u7ED3\u679C\u62A5\u544A" })
12713
+ report: Type26.String({ minLength: 1, description: "\u5982\u5B9E\u7ED3\u679C\u62A5\u544A" })
12081
12714
  }, { additionalProperties: false }),
12082
- Type25.Object({
12715
+ Type26.Object({
12083
12716
  status: stringEnum(["unfinished"], {
12084
12717
  description: "unfinished \u2014 \u5F62\u72B6\u6307\u5F15\uFF0C\u975E schema \u95F8\uFF1B\u7F3A\u524D\u7F6E\u6216\u8FDD\u5BAA\u7EA6\u675F\u81F4\u672C\u5C40\u672A\u5B8C\u6210\u65F6\u53EF\u7528\u3002\u7F3A\u5F85\u51B3 owner \u51B3\u5B9A\u6216\u7B54\u590D\u5C5E\u7F3A\u524D\u7F6E\u3002"
12085
12718
  }),
12086
- report: Type25.String({ minLength: 1, description: "\u5982\u5B9E\u7ED3\u679C\u62A5\u544A" }),
12087
- remainingScope: Type25.String({ minLength: 1, description: "\u672C\u5C40\u540E\u5269\u4F59\u5DE5\u4F5C" }),
12088
- reason: Type25.Optional(Type25.String({
12719
+ report: Type26.String({ minLength: 1, description: "\u5982\u5B9E\u7ED3\u679C\u62A5\u544A" }),
12720
+ remainingScope: Type26.String({ minLength: 1, description: "\u672C\u5C40\u540E\u5269\u4F59\u5DE5\u4F5C" }),
12721
+ reason: Type26.Optional(Type26.String({
12089
12722
  minLength: 1,
12090
12723
  description: "\u963B\u65AD\u539F\u56E0\uFF1A\u7F3A\u524D\u7F6E\u6216\u8FDD\u5BAA\u7EA6\u675F\u3002\u7F3A\u5F85\u51B3 owner \u51B3\u5B9A\u6216\u7B54\u590D\u5C5E\u7F3A\u524D\u7F6E\u3002"
12091
12724
  }))
@@ -12556,6 +13189,12 @@ var GLEANER_LEFT_TRANSPORT_FLAGS = Object.freeze([
12556
13189
  definition: GLEANER_LEFT_BASE_FLAG.definition
12557
13190
  })
12558
13191
  ]);
13192
+ var DIARIST_TRANSPORT_FLAGS = Object.freeze([
13193
+ Object.freeze({
13194
+ name: DIARIST_SOURCES_FLAG.name,
13195
+ definition: DIARIST_SOURCES_FLAG.definition
13196
+ })
13197
+ ]);
12559
13198
  function decodeReviewerAdmittedInputs(getFlag) {
12560
13199
  let reviewScopeKeys;
12561
13200
  const rawScopeKeys = getFlag("ak-review-scope-keys");
@@ -12673,6 +13312,8 @@ function activationStage(role, runtime) {
12673
13312
  return { id: "load-and-install", run: async () => runtime.gatekeeper.activate() };
12674
13313
  case "navigator":
12675
13314
  return { id: "load-and-install", run: async () => runtime.navigator.activate() };
13315
+ case "diarist":
13316
+ return { id: "load-and-install", run: async () => runtime.diarist.activate() };
12676
13317
  case "merger":
12677
13318
  return { id: "prepare-git-and-install", run: async () => runtime.merger() };
12678
13319
  }
@@ -12810,12 +13451,10 @@ function createFiledOfficerRuntime(roleHost, spec, dependencies) {
12810
13451
  parameters: spec.tool.parameters,
12811
13452
  async execute(toolCallId, parameters, signal, _onUpdate, ctx) {
12812
13453
  if (soul === void 0) throw new Error(`${spec.role} \u804C\u5206\u672A\u88C5\u8F7D`);
12813
- if (spec.beforeAccept !== void 0) {
12814
- await spec.beforeAccept({ toolCallId, parameters, signal, ctx });
12815
- }
13454
+ const projected = spec.beforeAccept === void 0 ? void 0 : await spec.beforeAccept({ toolCallId, parameters, signal, ctx });
12816
13455
  return {
12817
13456
  content: [{ type: "text", text: spec.acceptedText }],
12818
- details: parameters,
13457
+ details: projected === void 0 ? parameters : projected,
12819
13458
  terminate: true
12820
13459
  };
12821
13460
  }
@@ -12892,6 +13531,47 @@ function createNavigatorRoleRuntime(roleHost, dependencies) {
12892
13531
  dependencies
12893
13532
  );
12894
13533
  }
13534
+ function createDiaristRoleRuntime(roleHost, dependencies, getSourcesFlag) {
13535
+ let catalog;
13536
+ const runtime = createFiledOfficerRuntime(
13537
+ roleHost,
13538
+ {
13539
+ role: "diarist",
13540
+ tool: DIARIST_TOOL_SPEC,
13541
+ acceptedText: DIARIST_ACCEPTED_TEXT,
13542
+ soulTag: "diarist",
13543
+ beforeAccept: async ({ parameters }) => {
13544
+ const submitted = parameters !== null && typeof parameters === "object" && !Array.isArray(parameters) ? parameters : void 0;
13545
+ if (catalog === void 0) {
13546
+ if (submitted === void 0 || !("sitian" in submitted)) return void 0;
13547
+ const stripped = { ...submitted };
13548
+ delete stripped.sitian;
13549
+ return stripped;
13550
+ }
13551
+ const facts = await commitDiaristSelections({
13552
+ catalog,
13553
+ selections: projectDiaristSelections(parameters)
13554
+ });
13555
+ return { ...submitted ?? { receipt: parameters }, sitian: facts };
13556
+ }
13557
+ },
13558
+ dependencies
13559
+ );
13560
+ return {
13561
+ async activate() {
13562
+ catalog = loadFrozenDiaristCatalog(getSourcesFlag);
13563
+ return runtime.activate();
13564
+ }
13565
+ };
13566
+ }
13567
+ function loadFrozenDiaristCatalog(getFlag) {
13568
+ const raw = getFlag();
13569
+ if (raw === void 0) return void 0;
13570
+ if (typeof raw !== "string" || raw.trim() === "") {
13571
+ throw new Error("Diarist source catalog flag must be a nonempty path");
13572
+ }
13573
+ return loadDiaristSourceCatalog(raw);
13574
+ }
12895
13575
  function createCountersignRoleRuntime(roleHost, dependencies, hostActions) {
12896
13576
  const beforeAccept = hostActions !== void 0 && roleHost.requireGatekeeperPass !== void 0 ? async ({ toolCallId, signal, ctx }) => {
12897
13577
  await roleHost.requireGatekeeperPass({
@@ -12935,6 +13615,9 @@ function createRoleRuntimeExtension(dependencies) {
12935
13615
  for (const flag of GLEANER_LEFT_TRANSPORT_FLAGS) {
12936
13616
  roleHost.registerFlag(flag.name, flag.definition);
12937
13617
  }
13618
+ for (const flag of DIARIST_TRANSPORT_FLAGS) {
13619
+ roleHost.registerFlag(flag.name, flag.definition);
13620
+ }
12938
13621
  let admitted = false;
12939
13622
  let selectedRole;
12940
13623
  let activeReviewerParent;
@@ -13325,6 +14008,16 @@ function createRoleRuntimeExtension(dependencies) {
13325
14008
  return dependencies.loadNavigatorSoul();
13326
14009
  }
13327
14010
  });
14011
+ const diarist = createDiaristRoleRuntime(
14012
+ roleHost,
14013
+ {
14014
+ async loadSoul() {
14015
+ if (!dependencies.loadDiaristSoul) throw new Error("Diarist runtime dependencies are not configured");
14016
+ return dependencies.loadDiaristSoul();
14017
+ }
14018
+ },
14019
+ () => envelopeHost.host.getFlag(DIARIST_SOURCES_FLAG.name)
14020
+ );
13328
14021
  let sessionMergerGitState = dependencies.mergerGitState;
13329
14022
  const merger = createMergerRoleRuntime(roleHost, {
13330
14023
  async loadSoul() {
@@ -13477,6 +14170,7 @@ function createRoleRuntimeExtension(dependencies) {
13477
14170
  inspector,
13478
14171
  gatekeeper,
13479
14172
  navigator,
14173
+ diarist,
13480
14174
  merger: async () => {
13481
14175
  if (dependencies.mergerGitState === void 0) {
13482
14176
  sessionMergerGitState = dependencies.createMergerGitState?.(ctx.cwd);
@@ -13587,9 +14281,9 @@ function createRoleRuntimeExtension(dependencies) {
13587
14281
  }
13588
14282
 
13589
14283
  // src/acp-host/description.ts
13590
- import { join as join22 } from "node:path";
14284
+ import { join as join23 } from "node:path";
13591
14285
  function resolveAcpBinary(description, operatorHome) {
13592
- return join22(operatorHome, ...description.binaryFromHome);
14286
+ return join23(operatorHome, ...description.binaryFromHome);
13593
14287
  }
13594
14288
  function acpStdioArgs(description, model) {
13595
14289
  const { prefix, suffix, modelFlag, thinkingFlag } = description.argv;
@@ -13606,7 +14300,7 @@ function acpStdioArgs(description, model) {
13606
14300
  import { randomUUID as randomUUID2 } from "node:crypto";
13607
14301
  import { mkdir as mkdir3, readFile as readFile13, writeFile as writeFile7 } from "node:fs/promises";
13608
14302
  import { createServer } from "node:net";
13609
- import { basename as basename7, dirname as dirname15, join as join23 } from "node:path";
14303
+ import { basename as basename7, dirname as dirname15, join as join24 } from "node:path";
13610
14304
  import { fileURLToPath as fileURLToPath2 } from "node:url";
13611
14305
 
13612
14306
  // src/acp-host/role-turn-host.ts
@@ -13913,7 +14607,7 @@ function projectAcpActivationFlags(request) {
13913
14607
  const phaseFlag = packagedRolePhaseFlag(activation.role);
13914
14608
  if ("phase" in activation && phaseFlag !== void 0) flags.set(phaseFlag, activation.phase);
13915
14609
  if (inputFlag !== void 0) {
13916
- 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;
14610
+ 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;
13917
14611
  if (path !== void 0) flags.set(inputFlag, path);
13918
14612
  }
13919
14613
  if (activation.role === "fixer" && activation.prerequisitesPath !== void 0) flags.set("ak-fixer-prerequisites", activation.prerequisitesPath);
@@ -13977,7 +14671,7 @@ async function prepareAcpRoleEnvelope(options) {
13977
14671
  const raw = await readFile13(method.path, "utf8");
13978
14672
  methodSkills.set(name, { path: method.path, body: stripSkillFrontmatter(raw).trim() });
13979
14673
  }
13980
- let sessionFile = options.sessionFile ?? join23(request.runDirectory, "session", "session.jsonl");
14674
+ let sessionFile = options.sessionFile ?? join24(request.runDirectory, "session", "session.jsonl");
13981
14675
  await mkdir3(dirname15(sessionFile), { recursive: true });
13982
14676
  if (request.continuation.kind !== "resume") {
13983
14677
  try {
@@ -14444,9 +15138,9 @@ async function prepareAcpRoleEnvelope(options) {
14444
15138
 
14445
15139
  // src/acp-host/session-identity.ts
14446
15140
  import { mkdir as mkdir4, readFile as readFile14, rename, writeFile as writeFile8 } from "node:fs/promises";
14447
- import { dirname as dirname16, join as join24 } from "node:path";
15141
+ import { dirname as dirname16, join as join25 } from "node:path";
14448
15142
  function createAcpSessionIdentityAuthority(authority, sessionBindingFile) {
14449
- const bindingPath = (principal) => join24(authority.decode(principal).sessionDirectory, sessionBindingFile);
15143
+ const bindingPath = (principal) => join25(authority.decode(principal).sessionDirectory, sessionBindingFile);
14450
15144
  return {
14451
15145
  resolveSessionFile(principal) {
14452
15146
  return authority.decode(principal).sessionFile;
@@ -14502,6 +15196,7 @@ function createAcpRoleRuntimeDependencies(packageRoot) {
14502
15196
  loadNotarySoul: () => loadMainRoleSessionMaterials("notary"),
14503
15197
  loadCountersignSoul: () => loadMainRoleSessionMaterials("countersign"),
14504
15198
  loadGleanerLeftSoul: () => loadMainRoleSessionMaterials("gleaner-left"),
15199
+ loadDiaristSoul: () => loadMainRoleSessionMaterials("diarist"),
14505
15200
  loadNotarySourceRun: loadNotarySourceRunLocator,
14506
15201
  loadMergerSoul: () => loadMainRoleSessionMaterials("merger"),
14507
15202
  loadMergerInput: async (path) => JSON.parse(await readFile15(path, "utf8")),