@akagilnc/pi-workflow-roles 0.1.1918 → 0.1.2004

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 (42) hide show
  1. package/dist/evidence-child-executor.js +12 -6
  2. package/dist/package-contracts/reviewer-output.js +16 -0
  3. package/dist/public-cli/main.js +2520 -72
  4. package/dist/reviewer-construction.js +46 -6
  5. package/dist/reviewer-dispatch.js +64 -1
  6. package/dist/reviewer-execution-ledger.js +2 -1
  7. package/dist/reviewer-pinned-git.js +33 -0
  8. package/package.json +1 -1
  9. package/src/atomic-write.ts +26 -0
  10. package/src/evidence-child-executor.ts +13 -6
  11. package/src/ledger-session-read.ts +260 -0
  12. package/src/package-contracts/reviewer-output.ts +19 -0
  13. package/src/public-cli/cli.ts +24 -0
  14. package/src/public-cli/invocation.ts +398 -2
  15. package/src/public-cli/main.ts +21 -2
  16. package/src/public-cli/registry.ts +18 -1
  17. package/src/public-cli/reviewer-run.ts +12 -0
  18. package/src/public-cli/run-lifecycle.ts +22 -1
  19. package/src/public-cli/settlement.ts +17 -0
  20. package/src/public-cli/taishi-run.ts +235 -0
  21. package/src/reviewer-construction.ts +64 -7
  22. package/src/reviewer-dispatch.ts +81 -2
  23. package/src/reviewer-execution-ledger.ts +2 -1
  24. package/src/reviewer-pinned-git.ts +43 -0
  25. package/src/reviewer-role.ts +143 -132
  26. package/src/reviewer-settlement.ts +4 -0
  27. package/src/role-runtime.ts +186 -3
  28. package/src/run-terminal-artifacts.ts +231 -0
  29. package/src/taishi-cohort.ts +232 -0
  30. package/src/taishi-entry.ts +429 -0
  31. package/src/taishi-index.ts +269 -0
  32. package/src/taishi-ledger.ts +466 -0
  33. package/src/taishi-median.ts +15 -0
  34. package/src/taishi-metric-families/acceptance-success-rework.ts +346 -0
  35. package/src/taishi-metric-families/b2-frame-buckets-actions.ts +274 -0
  36. package/src/taishi-metric-families/leg-wall-clock.ts +90 -0
  37. package/src/taishi-metric-families/round-timeline.ts +201 -0
  38. package/src/taishi-metric-families.ts +36 -0
  39. package/src/taishi-metric-family.ts +41 -0
  40. package/src/taishi-model-groups.ts +198 -0
  41. package/src/taishi-page.ts +320 -0
  42. package/src/ticket-trajectory.ts +9 -62
@@ -147,6 +147,18 @@ function validateRuntimeReviewerReceipt(output) {
147
147
  throw new Error("Successful Reviewer outcome lacks report");
148
148
  if (status === "failed" && report !== void 0) throw new Error("Failed Reviewer outcome cannot bind a report");
149
149
  }
150
+ const specDisposition = read(output, "specDisposition");
151
+ if (specDisposition === "launched") {
152
+ if (expectedAxes.length !== 2 || expectedAxes[0] !== "standards" || expectedAxes[1] !== "spec") {
153
+ throw new Error("Reviewer specDisposition launched requires Standards+Spec accepted legs");
154
+ }
155
+ } else if (specDisposition === "skipped-missing") {
156
+ if (expectedAxes.length !== 1 || expectedAxes[0] !== "standards") {
157
+ throw new Error("Reviewer specDisposition skipped-missing requires Standards-only accepted legs");
158
+ }
159
+ } else if (specDisposition !== void 0) {
160
+ throw new Error("Invalid Reviewer specDisposition");
161
+ }
150
162
  }
151
163
  return output;
152
164
  }
@@ -14261,7 +14273,13 @@ function listHelpCapabilities() {
14261
14273
  defaultPhase
14262
14274
  };
14263
14275
  });
14264
- return [...support, ...roles];
14276
+ const deterministic = PUBLIC_DETERMINISTIC_COMMANDS.map(
14277
+ (name) => ({
14278
+ kind: "deterministic",
14279
+ name
14280
+ })
14281
+ );
14282
+ return [...support, ...roles, ...deterministic];
14265
14283
  }
14266
14284
  function isPublicConfigurableSeat(value) {
14267
14285
  return PUBLIC_CONFIGURABLE_SEATS.includes(value);
@@ -14269,7 +14287,7 @@ function isPublicConfigurableSeat(value) {
14269
14287
  function isPublicCliSupportCommand(value) {
14270
14288
  return PUBLIC_CLI_SUPPORT_COMMANDS.includes(value);
14271
14289
  }
14272
- var INTERNAL_ROLE_ENTRYPOINT_RELATIVE, PUBLIC_CALLABLE_ROLES, AUTOMATIC_NAVIGATOR_SEAT, PUBLIC_CONFIGURABLE_SEATS, PUBLIC_CLI_SUPPORT_COMMANDS, STARTUP_CANDIDATES;
14290
+ var INTERNAL_ROLE_ENTRYPOINT_RELATIVE, PUBLIC_CALLABLE_ROLES, AUTOMATIC_NAVIGATOR_SEAT, PUBLIC_CONFIGURABLE_SEATS, PUBLIC_CLI_SUPPORT_COMMANDS, STARTUP_CANDIDATES, PUBLIC_DETERMINISTIC_COMMANDS;
14273
14291
  var init_registry2 = __esm({
14274
14292
  "src/public-cli/registry.ts"() {
14275
14293
  "use strict";
@@ -14323,6 +14341,7 @@ var init_registry2 = __esm({
14323
14341
  { provider: "xai", model: "grok-4.5", thinking: "high" }
14324
14342
  ]
14325
14343
  };
14344
+ PUBLIC_DETERMINISTIC_COMMANDS = ["taishi"];
14326
14345
  }
14327
14346
  });
14328
14347
 
@@ -14755,6 +14774,26 @@ function ensureRealDirectoryTree(root, targetDir) {
14755
14774
  );
14756
14775
  }
14757
14776
  }
14777
+ function assertLedgerFileInsideHome(ledgerPath, ledgerHome) {
14778
+ if (!isAbsolute(ledgerHome)) {
14779
+ throw new ActivationLedgerError(`activation ledger home must be absolute: ${ledgerHome}`);
14780
+ }
14781
+ const resolvedLedger = resolve(ledgerPath);
14782
+ try {
14783
+ if (!lstatSync2(resolvedLedger).isSymbolicLink()) return;
14784
+ throw new ActivationLedgerError(
14785
+ `activation ledger file is a symbolic link: ${resolvedLedger}`
14786
+ );
14787
+ } catch (error) {
14788
+ if (errnoCode(error) !== "ENOENT") {
14789
+ if (error instanceof ActivationLedgerError) throw error;
14790
+ throw new ActivationLedgerError(
14791
+ `activation ledger failed to stat ledger file (${resolvedLedger}): ${errorText(error)}`,
14792
+ { cause: error }
14793
+ );
14794
+ }
14795
+ }
14796
+ }
14758
14797
  var ActivationLedgerError;
14759
14798
  var init_activation_ledger_topology = __esm({
14760
14799
  "src/activation-ledger-topology.ts"() {
@@ -15464,6 +15503,17 @@ function requireOptionPath(flag, value) {
15464
15503
  }
15465
15504
  return value;
15466
15505
  }
15506
+ function requireAuthorityRef(value) {
15507
+ if (value === void 0 || value.trim() === "") {
15508
+ throw new CliUsageError("--authority-ref requires a nonempty durable reference");
15509
+ }
15510
+ if (/\s/.test(value)) {
15511
+ throw new CliUsageError(
15512
+ "--authority-ref requires a durable reference, not inline Spec prose"
15513
+ );
15514
+ }
15515
+ return value;
15516
+ }
15467
15517
  function parseJudgeArgv(args) {
15468
15518
  const attachmentPaths = [];
15469
15519
  let project;
@@ -16426,6 +16476,7 @@ function buildDoctorTransportPrompt(admitted) {
16426
16476
  }
16427
16477
  function parseReviewerArgv(args) {
16428
16478
  const attachmentPaths = [];
16479
+ const authorityRefs = [];
16429
16480
  let project;
16430
16481
  let baseRevision;
16431
16482
  const positional = [];
@@ -16452,6 +16503,14 @@ function parseReviewerArgv(args) {
16452
16503
  baseRevision = requireOptionPath("--base", token.slice("--base=".length));
16453
16504
  continue;
16454
16505
  }
16506
+ if (token === "--authority-ref") {
16507
+ authorityRefs.push(requireAuthorityRef(tokens.shift()));
16508
+ continue;
16509
+ }
16510
+ if (token.startsWith("--authority-ref=")) {
16511
+ authorityRefs.push(requireAuthorityRef(token.slice("--authority-ref=".length)));
16512
+ continue;
16513
+ }
16455
16514
  if (token.startsWith("-") && token !== "-") {
16456
16515
  throw new CliUsageError(`unknown reviewer option: ${token}`);
16457
16516
  }
@@ -16464,6 +16523,7 @@ function parseReviewerArgv(args) {
16464
16523
  instruction: positional.join(" "),
16465
16524
  attachmentPaths,
16466
16525
  baseRevision,
16526
+ authorityRefs,
16467
16527
  ...project === void 0 ? {} : { project }
16468
16528
  };
16469
16529
  }
@@ -16474,6 +16534,9 @@ async function admitReviewerInvocation(options) {
16474
16534
  if (options.baseRevision.trim() === "") {
16475
16535
  throw new CliUsageError("--base requires a nonempty revision");
16476
16536
  }
16537
+ const authorityRefs = Object.freeze(
16538
+ (options.authorityRefs ?? []).map((ref) => requireAuthorityRef(ref))
16539
+ );
16477
16540
  const projectRoot = resolve4(options.project ?? options.cwd);
16478
16541
  const runId = (options.createRunId ?? uuidv7)();
16479
16542
  const { ledgerHome, bookKey, runDirectory, sessionDirectory, sessionFile } = roleRunSessionCoordinates({ cwd: projectRoot, runId, role: "reviewer", home: options.home });
@@ -16499,6 +16562,7 @@ async function admitReviewerInvocation(options) {
16499
16562
  instruction,
16500
16563
  instructionEmpty,
16501
16564
  baseRevision: options.baseRevision,
16565
+ authorityRefs: [...authorityRefs],
16502
16566
  attachments: attachments.map((a) => ({
16503
16567
  provenancePath: a.provenancePath,
16504
16568
  frozenPath: a.frozenPath,
@@ -16528,6 +16592,7 @@ async function admitReviewerInvocation(options) {
16528
16592
  sessionFile,
16529
16593
  admittedRequestPath,
16530
16594
  baseRevision: options.baseRevision,
16595
+ authorityRefs,
16531
16596
  ...ticketFields
16532
16597
  };
16533
16598
  }
@@ -16731,7 +16796,260 @@ function buildMergerTransportPrompt(admitted) {
16731
16796
  }
16732
16797
  return lines.join("\n");
16733
16798
  }
16734
- var MergerEnvelopeDerivationError, DOCTOR_ISSUE_NUMBER_PATTERN, DOCTOR_CASE_RUNS_PATH_PATTERN;
16799
+ function parseTaishiTicketNumber(raw, flag = "--ticket") {
16800
+ const trimmed = raw.trim();
16801
+ if (!TAISHI_TICKET_NUMBER_PATTERN.test(trimmed)) {
16802
+ throw new CliUsageError(
16803
+ `taishi ${flag} must be a positive integer, got ${raw}`
16804
+ );
16805
+ }
16806
+ const value = Number(trimmed);
16807
+ if (!Number.isSafeInteger(value) || value < 1) {
16808
+ throw new CliUsageError(
16809
+ `taishi ${flag} must be a positive integer, got ${raw}`
16810
+ );
16811
+ }
16812
+ return value;
16813
+ }
16814
+ function parseTaishiIssueNumberList(raw, flag) {
16815
+ const trimmed = raw.trim();
16816
+ if (trimmed === "") {
16817
+ throw new CliUsageError(`${flag} requires a comma-separated positive integer list`);
16818
+ }
16819
+ const parts = trimmed.split(",").map((part) => part.trim());
16820
+ if (parts.some((part) => part === "")) {
16821
+ throw new CliUsageError(`${flag} requires a comma-separated positive integer list`);
16822
+ }
16823
+ return parts.map((part) => parseTaishiTicketNumber(part, flag));
16824
+ }
16825
+ function requireOptionValue(flag, value, what) {
16826
+ if (value === void 0 || value.trim() === "") {
16827
+ throw new CliUsageError(`${flag} requires ${what}`);
16828
+ }
16829
+ return value;
16830
+ }
16831
+ function parseTaishiArgv(args) {
16832
+ let query = "issue";
16833
+ let ticketRaw;
16834
+ const projectRoots = [];
16835
+ let groupALabel;
16836
+ let groupAIssuesRaw;
16837
+ let groupBLabel;
16838
+ let groupBIssuesRaw;
16839
+ let sweepToken = false;
16840
+ const attachmentPaths = [];
16841
+ const tokens = [...args];
16842
+ while (tokens.length > 0) {
16843
+ const token = tokens.shift();
16844
+ if (token === "--") {
16845
+ if (tokens.length > 0) {
16846
+ throw new CliUsageError(`unexpected taishi argument: ${tokens[0]}`);
16847
+ }
16848
+ break;
16849
+ }
16850
+ if (token === "--cohort") {
16851
+ if (query !== "issue") {
16852
+ throw new CliUsageError("taishi accepts only one of --cohort / --model-groups");
16853
+ }
16854
+ query = "cohort";
16855
+ continue;
16856
+ }
16857
+ if (token === "--model-groups") {
16858
+ if (query !== "issue") {
16859
+ throw new CliUsageError("taishi accepts only one of --cohort / --model-groups");
16860
+ }
16861
+ query = "model-groups";
16862
+ continue;
16863
+ }
16864
+ if (token === "--ticket") {
16865
+ const value = tokens.shift();
16866
+ if (value === void 0 || value.trim() === "") {
16867
+ throw new CliUsageError("taishi --ticket requires a positive integer");
16868
+ }
16869
+ ticketRaw = value;
16870
+ continue;
16871
+ }
16872
+ if (token.startsWith("--ticket=")) {
16873
+ ticketRaw = token.slice("--ticket=".length);
16874
+ if (ticketRaw.trim() === "") {
16875
+ throw new CliUsageError("taishi --ticket requires a positive integer");
16876
+ }
16877
+ continue;
16878
+ }
16879
+ if (token === "--project-root") {
16880
+ projectRoots.push(requireOptionPath("--project-root", tokens.shift()));
16881
+ continue;
16882
+ }
16883
+ if (token.startsWith("--project-root=")) {
16884
+ projectRoots.push(
16885
+ requireOptionPath("--project-root", token.slice("--project-root=".length))
16886
+ );
16887
+ continue;
16888
+ }
16889
+ if (token === "--group-a-label") {
16890
+ groupALabel = requireOptionValue("--group-a-label", tokens.shift(), "a label");
16891
+ continue;
16892
+ }
16893
+ if (token.startsWith("--group-a-label=")) {
16894
+ groupALabel = requireOptionValue(
16895
+ "--group-a-label",
16896
+ token.slice("--group-a-label=".length),
16897
+ "a label"
16898
+ );
16899
+ continue;
16900
+ }
16901
+ if (token === "--group-a-issues") {
16902
+ groupAIssuesRaw = requireOptionValue(
16903
+ "--group-a-issues",
16904
+ tokens.shift(),
16905
+ "a comma-separated positive integer list"
16906
+ );
16907
+ continue;
16908
+ }
16909
+ if (token.startsWith("--group-a-issues=")) {
16910
+ groupAIssuesRaw = requireOptionValue(
16911
+ "--group-a-issues",
16912
+ token.slice("--group-a-issues=".length),
16913
+ "a comma-separated positive integer list"
16914
+ );
16915
+ continue;
16916
+ }
16917
+ if (token === "--group-b-label") {
16918
+ groupBLabel = requireOptionValue("--group-b-label", tokens.shift(), "a label");
16919
+ continue;
16920
+ }
16921
+ if (token.startsWith("--group-b-label=")) {
16922
+ groupBLabel = requireOptionValue(
16923
+ "--group-b-label",
16924
+ token.slice("--group-b-label=".length),
16925
+ "a label"
16926
+ );
16927
+ continue;
16928
+ }
16929
+ if (token === "--group-b-issues") {
16930
+ groupBIssuesRaw = requireOptionValue(
16931
+ "--group-b-issues",
16932
+ tokens.shift(),
16933
+ "a comma-separated positive integer list"
16934
+ );
16935
+ continue;
16936
+ }
16937
+ if (token.startsWith("--group-b-issues=")) {
16938
+ groupBIssuesRaw = requireOptionValue(
16939
+ "--group-b-issues",
16940
+ token.slice("--group-b-issues=".length),
16941
+ "a comma-separated positive integer list"
16942
+ );
16943
+ continue;
16944
+ }
16945
+ if (token === "--attach") {
16946
+ attachmentPaths.push(requireOptionPath("--attach", tokens.shift()));
16947
+ continue;
16948
+ }
16949
+ if (token.startsWith("--attach=")) {
16950
+ attachmentPaths.push(
16951
+ requireOptionPath("--attach", token.slice("--attach=".length))
16952
+ );
16953
+ continue;
16954
+ }
16955
+ if (token.startsWith("-") && token !== "-") {
16956
+ throw new CliUsageError(`unknown taishi option: ${token}`);
16957
+ }
16958
+ if (token === "sweep") {
16959
+ if (sweepToken) {
16960
+ throw new CliUsageError("unexpected taishi argument: sweep");
16961
+ }
16962
+ sweepToken = true;
16963
+ continue;
16964
+ }
16965
+ throw new CliUsageError(`unexpected taishi argument: ${token}`);
16966
+ }
16967
+ const hasSweepFace = sweepToken || attachmentPaths.length > 0;
16968
+ const hasCohortFlags = groupALabel !== void 0 || groupAIssuesRaw !== void 0 || groupBLabel !== void 0 || groupBIssuesRaw !== void 0;
16969
+ if (query === "cohort") {
16970
+ if (groupALabel === void 0 || groupAIssuesRaw === void 0 || groupBLabel === void 0 || groupBIssuesRaw === void 0) {
16971
+ throw new CliUsageError(
16972
+ "usage: ak-role taishi --cohort --group-a-label <L> --group-a-issues <N[,N...]> --group-b-label <L> --group-b-issues <N[,N...]>"
16973
+ );
16974
+ }
16975
+ if (ticketRaw !== void 0 || projectRoots.length > 0) {
16976
+ throw new CliUsageError(
16977
+ "taishi --cohort does not accept --ticket or --project-root"
16978
+ );
16979
+ }
16980
+ if (hasSweepFace) {
16981
+ throw new CliUsageError(
16982
+ "taishi --cohort does not accept sweep --attach"
16983
+ );
16984
+ }
16985
+ return {
16986
+ query: "cohort",
16987
+ groups: [
16988
+ {
16989
+ groupLabel: groupALabel,
16990
+ issues: parseTaishiIssueNumberList(groupAIssuesRaw, "--group-a-issues")
16991
+ },
16992
+ {
16993
+ groupLabel: groupBLabel,
16994
+ issues: parseTaishiIssueNumberList(groupBIssuesRaw, "--group-b-issues")
16995
+ }
16996
+ ]
16997
+ };
16998
+ }
16999
+ if (query === "model-groups") {
17000
+ if (projectRoots.length === 0) {
17001
+ throw new CliUsageError(
17002
+ "usage: ak-role taishi --model-groups --project-root <P> [--project-root <P> ...]"
17003
+ );
17004
+ }
17005
+ if (ticketRaw !== void 0) {
17006
+ throw new CliUsageError("taishi --model-groups does not accept --ticket");
17007
+ }
17008
+ if (hasCohortFlags) {
17009
+ throw new CliUsageError("taishi --model-groups does not accept cohort group flags");
17010
+ }
17011
+ if (hasSweepFace) {
17012
+ throw new CliUsageError(
17013
+ "taishi --model-groups does not accept sweep --attach"
17014
+ );
17015
+ }
17016
+ return {
17017
+ query: "model-groups",
17018
+ projectRoots
17019
+ };
17020
+ }
17021
+ if (hasCohortFlags) {
17022
+ throw new CliUsageError("taishi issue query does not accept cohort group flags");
17023
+ }
17024
+ if (hasSweepFace) {
17025
+ if (ticketRaw !== void 0 || projectRoots.length > 0) {
17026
+ throw new CliUsageError(
17027
+ "taishi sweep --attach cannot combine with --ticket or --project-root"
17028
+ );
17029
+ }
17030
+ return {
17031
+ query: "sweep",
17032
+ attachmentPaths
17033
+ };
17034
+ }
17035
+ if (projectRoots.length > 1) {
17036
+ throw new CliUsageError(
17037
+ "taishi issue query accepts at most one --project-root (use --model-groups for many)"
17038
+ );
17039
+ }
17040
+ const projectRoot = projectRoots[0];
17041
+ if (ticketRaw === void 0 && projectRoot === void 0) {
17042
+ throw new CliUsageError(
17043
+ "usage: ak-role taishi ((--ticket <N> | --project-root <P>) | [sweep] --attach <sweep.json> | --cohort ... | --model-groups ...)"
17044
+ );
17045
+ }
17046
+ return {
17047
+ query: "issue",
17048
+ ...ticketRaw === void 0 ? {} : { ticket: parseTaishiTicketNumber(ticketRaw) },
17049
+ ...projectRoot === void 0 ? {} : { projectRoot }
17050
+ };
17051
+ }
17052
+ var MergerEnvelopeDerivationError, DOCTOR_ISSUE_NUMBER_PATTERN, DOCTOR_CASE_RUNS_PATH_PATTERN, TAISHI_TICKET_NUMBER_PATTERN;
16735
17053
  var init_invocation = __esm({
16736
17054
  "src/public-cli/invocation.ts"() {
16737
17055
  "use strict";
@@ -16758,6 +17076,7 @@ var init_invocation = __esm({
16758
17076
  };
16759
17077
  DOCTOR_ISSUE_NUMBER_PATTERN = /^[1-9]\d*$/;
16760
17078
  DOCTOR_CASE_RUNS_PATH_PATTERN = /\/\.ak-roles\/books\/[^/]+\/issues\/([1-9]\d*)\/runs$/;
17079
+ TAISHI_TICKET_NUMBER_PATTERN = /^[1-9]\d*$/;
16761
17080
  }
16762
17081
  });
16763
17082
 
@@ -16804,7 +17123,7 @@ var init_reviewer_scope_prompt = __esm({
16804
17123
  });
16805
17124
 
16806
17125
  // src/reviewer-construction.ts
16807
- var REVIEWER_CONSTRUCTION_RECIPE, REVIEWER_AXIS_OUTPUT_ADAPTER, REVIEWER_STANDARDS_CONCLUSION_KEYS, REVIEWER_STANDARDS_CONCLUSION_LABELS;
17126
+ var REVIEWER_CONSTRUCTION_RECIPE, REVIEWER_AXIS_OUTPUT_ADAPTER, REVIEWER_VERIFICATION_BOUNDARY, REVIEWER_STANDARDS_CONCLUSION_KEYS, REVIEWER_STANDARDS_CONCLUSION_LABELS;
16808
17127
  var init_reviewer_construction = __esm({
16809
17128
  "src/reviewer-construction.ts"() {
16810
17129
  "use strict";
@@ -16821,6 +17140,14 @@ var init_reviewer_construction = __esm({
16821
17140
  version: 1,
16822
17141
  implementationSha256: sha256Hex("reviewer-axis-output:v1:single-axis-verbatim-report+standards-three-priorities")
16823
17142
  });
17143
+ REVIEWER_VERIFICATION_BOUNDARY = [
17144
+ "Verification-Boundary: you may run focused product tests during this review turn when independent verification needs them.",
17145
+ "A full repository test suite is not forbidden, but do not re-run it every review round;",
17146
+ "prefer once at family wrap-up unless this review specifically requires a broader run.",
17147
+ "Slice and review work should not trigger frequent full-suite reruns.",
17148
+ "Independently discover test facts (including existing coder/fixer receipts and any tests you run);",
17149
+ "do not treat caller prose as the source of those facts."
17150
+ ].join(" ");
16824
17151
  REVIEWER_STANDARDS_CONCLUSION_KEYS = Object.freeze([
16825
17152
  "constitutionality",
16826
17153
  "minimum-necessary-test-cost",
@@ -16845,6 +17172,7 @@ var init_reviewer_dispatch = __esm({
16845
17172
  init_reviewer_prompt_identity();
16846
17173
  init_sha256();
16847
17174
  init_reviewer_construction();
17175
+ init_reviewer_construction();
16848
17176
  init_reviewer_preflight_error();
16849
17177
  init_sha256();
16850
17178
  init_reviewer_prompt_identity();
@@ -17640,6 +17968,7 @@ async function loadResumableRunRecord(home, runId) {
17640
17968
  let prerequisitesPath;
17641
17969
  let prerequisites;
17642
17970
  let baseRevision;
17971
+ let authorityRefs;
17643
17972
  let mergerInputPath;
17644
17973
  let derived;
17645
17974
  let correlationId;
@@ -17677,6 +18006,18 @@ async function loadResumableRunRecord(home, runId) {
17677
18006
  if (typeof record4.baseRevision === "string" && record4.baseRevision.trim() !== "") {
17678
18007
  baseRevision = record4.baseRevision;
17679
18008
  }
18009
+ if (Array.isArray(record4.authorityRefs)) {
18010
+ authorityRefs = Object.freeze(
18011
+ record4.authorityRefs.map((ref) => {
18012
+ if (typeof ref !== "string") {
18013
+ throw new CliUsageError(
18014
+ "role run admitted authority refs must be durable reference strings"
18015
+ );
18016
+ }
18017
+ return requireAuthorityRef(ref);
18018
+ })
18019
+ );
18020
+ }
17680
18021
  if (typeof record4.mergerInputPath === "string" && record4.mergerInputPath.trim() !== "") {
17681
18022
  mergerInputPath = record4.mergerInputPath;
17682
18023
  }
@@ -17696,9 +18037,11 @@ async function loadResumableRunRecord(home, runId) {
17696
18037
  correlationId = fromAdmitted.correlationId;
17697
18038
  ticketNumber = fromAdmitted.ticketNumber;
17698
18039
  }
17699
- } catch {
18040
+ } catch (error) {
18041
+ if (error instanceof CliUsageError) throw error;
17700
18042
  throw new CliUsageError(
17701
- `role run admitted request is unreadable: ${runId}`
18043
+ `role run admitted request is unreadable: ${runId}`,
18044
+ { cause: error }
17702
18045
  );
17703
18046
  }
17704
18047
  if (correlationId === void 0 || ticketNumber === void 0) {
@@ -17735,6 +18078,7 @@ async function loadResumableRunRecord(home, runId) {
17735
18078
  ...prerequisitesPath === void 0 ? {} : { prerequisitesPath },
17736
18079
  ...prerequisites === void 0 ? {} : { prerequisites },
17737
18080
  ...baseRevision === void 0 ? {} : { baseRevision },
18081
+ ...authorityRefs === void 0 ? {} : { authorityRefs },
17738
18082
  ...mergerInputPath === void 0 ? {} : { mergerInputPath },
17739
18083
  ...derived === void 0 ? {} : { derived },
17740
18084
  ...correlationId === void 0 ? {} : { correlationId },
@@ -17890,6 +18234,7 @@ async function loadResumableReviewerRun(home, runId) {
17890
18234
  sessionFile: loaded.run.sessionFile,
17891
18235
  admittedRequestPath: loaded.run.admittedRequestPath,
17892
18236
  baseRevision,
18237
+ authorityRefs: Object.freeze([...loaded.admittedFields.authorityRefs ?? []]),
17893
18238
  ...restoredTicketFields(loaded.admittedFields)
17894
18239
  };
17895
18240
  return {
@@ -18093,8 +18438,9 @@ var init_evidence_child_executor = __esm({
18093
18438
  "use strict";
18094
18439
  init_compliance_transport();
18095
18440
  init_package_owned_tool_idle();
18096
- init_stream_idle_guard();
18097
18441
  init_receipt_delivery_policy();
18442
+ init_reviewer_construction();
18443
+ init_stream_idle_guard();
18098
18444
  init_upstream_error_testimony();
18099
18445
  }
18100
18446
  });
@@ -18670,6 +19016,11 @@ function formatFailureStderrDiagnostic(failure) {
18670
19016
  function presentStructuralRejection(error, io) {
18671
19017
  io.stderr(formatCliDiagnostic(error.message));
18672
19018
  }
19019
+ function presentControlledFailure(failure, io) {
19020
+ io.stdout(`${JSON.stringify(failure, null, 2)}
19021
+ `);
19022
+ io.stderr(formatFailureStderrDiagnostic(failure));
19023
+ }
18673
19024
  async function inspectJudgeSession(sessionFile) {
18674
19025
  try {
18675
19026
  await readFile9(sessionFile, "utf8");
@@ -19352,6 +19703,7 @@ function reviewerDecisiveFacts(output) {
19352
19703
  const axes = reviewerAxes(outcomes.readable ? outcomes.value : void 0);
19353
19704
  const reportAxes = reviewerAxes(reports.readable ? reports.value : void 0);
19354
19705
  const acceptedBatch = safelyRead(candidate, "acceptedBatch");
19706
+ const specDisposition = safelyRead(candidate, "specDisposition");
19355
19707
  const facts = {
19356
19708
  axes,
19357
19709
  reportAxes,
@@ -19359,6 +19711,9 @@ function reviewerDecisiveFacts(output) {
19359
19711
  ...auditNoReceiptDecisiveFact(candidate)
19360
19712
  };
19361
19713
  if (status.readable && typeof status.value === "string") facts.reviewerStatus = status.value;
19714
+ if (specDisposition.readable && (specDisposition.value === "launched" || specDisposition.value === "skipped-missing")) {
19715
+ facts.specDisposition = specDisposition.value;
19716
+ }
19362
19717
  const diagnostic = safelyRead(candidate, "diagnostic");
19363
19718
  if (status.readable && status.value === "refused" && diagnostic.readable) {
19364
19719
  facts.diagnosticPresent = typeof diagnostic.value === "string" && diagnostic.value.trim().length > 0;
@@ -20649,6 +21004,7 @@ async function publishReviewerArtifacts(admitted, roleOutcome, sessionDirectory,
20649
21004
  sessionFile: admitted.sessionFile,
20650
21005
  admittedRequestPath: admitted.admittedRequestPath,
20651
21006
  baseRevision: admitted.baseRevision,
21007
+ authorityRefs: [...admitted.authorityRefs],
20652
21008
  ...admitted.instructionEmpty ? {} : { callerProvenance: admitted.instruction },
20653
21009
  attachments: admitted.attachments.map((a) => ({
20654
21010
  provenancePath: a.provenancePath,
@@ -21315,7 +21671,7 @@ function buildCoderResumeActivationExtraArgs(admitted, options) {
21315
21671
  RESUME_TRANSPORT_ENVELOPE
21316
21672
  ];
21317
21673
  }
21318
- async function presentControlledFailure(admitted, failureInput, io) {
21674
+ async function presentControlledFailure2(admitted, failureInput, io) {
21319
21675
  const hasThrown = Object.hasOwn(failureInput, "thrown");
21320
21676
  const resumeObservation = await resolveControlledFailureResumeObservation({
21321
21677
  runDirectory: admitted.runDirectory,
@@ -21371,7 +21727,7 @@ async function dispatchAdmittedCoder(input) {
21371
21727
  env.credentials
21372
21728
  );
21373
21729
  if (missingCredential !== void 0) {
21374
- return await presentControlledFailure(
21730
+ return await presentControlledFailure2(
21375
21731
  admitted,
21376
21732
  missingCredential,
21377
21733
  io
@@ -21402,7 +21758,7 @@ async function dispatchAdmittedCoder(input) {
21402
21758
  ...env.piRunner === void 0 ? {} : { runner: env.piRunner }
21403
21759
  });
21404
21760
  } catch (error) {
21405
- return await presentControlledFailure(
21761
+ return await presentControlledFailure2(
21406
21762
  admitted,
21407
21763
  {
21408
21764
  timedOut: false,
@@ -21427,7 +21783,7 @@ async function dispatchAdmittedCoder(input) {
21427
21783
  ...methodProvenance === void 0 ? {} : { methodProvenance }
21428
21784
  });
21429
21785
  } catch (error) {
21430
- return await presentControlledFailure(
21786
+ return await presentControlledFailure2(
21431
21787
  admitted,
21432
21788
  {
21433
21789
  timedOut: false,
@@ -21458,7 +21814,7 @@ async function dispatchAdmittedCoder(input) {
21458
21814
  credential: credentialFailure,
21459
21815
  runDirectory: admitted.runDirectory
21460
21816
  });
21461
- return await presentControlledFailure(
21817
+ return await presentControlledFailure2(
21462
21818
  admitted,
21463
21819
  {
21464
21820
  timedOut: result2.timedOut,
@@ -21513,7 +21869,7 @@ async function runPublicCoder(argv, env, io, parseCoderArgv2) {
21513
21869
  methodProvenance = material.provenance;
21514
21870
  } catch (error) {
21515
21871
  await lease.release();
21516
- return await presentControlledFailure(
21872
+ return await presentControlledFailure2(
21517
21873
  admitted,
21518
21874
  {
21519
21875
  timedOut: false,
@@ -21590,7 +21946,7 @@ async function runPublicCoderResume(argv, env, io) {
21590
21946
  methodProvenance = material.provenance;
21591
21947
  } catch (error) {
21592
21948
  await lease.release();
21593
- return await presentControlledFailure(
21949
+ return await presentControlledFailure2(
21594
21950
  admitted,
21595
21951
  {
21596
21952
  timedOut: false,
@@ -21673,7 +22029,7 @@ function buildCollectorActivationExtraArgs(admitted, options = {}) {
21673
22029
  prompt
21674
22030
  ];
21675
22031
  }
21676
- async function presentControlledFailure2(admitted, failureInput, io) {
22032
+ async function presentControlledFailure3(admitted, failureInput, io) {
21677
22033
  const hasThrown = Object.hasOwn(failureInput, "thrown");
21678
22034
  const session = !hasThrown && !failureInput.timedOut && failureInput.knownFailure === void 0 && failureInput.knownCause === void 0 ? await inspectJudgeSession(admitted.sessionFile) : void 0;
21679
22035
  const failure = classifyPostAdmissionFailure({
@@ -21704,7 +22060,7 @@ async function dispatchAdmittedCollector(input) {
21704
22060
  env.credentials
21705
22061
  );
21706
22062
  if (missingCredential !== void 0) {
21707
- return await presentControlledFailure2(
22063
+ return await presentControlledFailure3(
21708
22064
  admitted,
21709
22065
  missingCredential,
21710
22066
  io
@@ -21735,7 +22091,7 @@ async function dispatchAdmittedCollector(input) {
21735
22091
  ...env.piRunner === void 0 ? {} : { runner: env.piRunner }
21736
22092
  });
21737
22093
  } catch (error) {
21738
- return await presentControlledFailure2(
22094
+ return await presentControlledFailure3(
21739
22095
  admitted,
21740
22096
  {
21741
22097
  timedOut: false,
@@ -21758,7 +22114,7 @@ async function dispatchAdmittedCollector(input) {
21758
22114
  try {
21759
22115
  lawful = await trySettleCollectorTerminalResult(admitted);
21760
22116
  } catch (error) {
21761
- return await presentControlledFailure2(
22117
+ return await presentControlledFailure3(
21762
22118
  admitted,
21763
22119
  {
21764
22120
  timedOut: false,
@@ -21796,7 +22152,7 @@ async function dispatchAdmittedCollector(input) {
21796
22152
  credential: credentialFailure,
21797
22153
  runDirectory: admitted.runDirectory
21798
22154
  });
21799
- return await presentControlledFailure2(
22155
+ return await presentControlledFailure3(
21800
22156
  admitted,
21801
22157
  {
21802
22158
  timedOut: result2.timedOut,
@@ -21907,7 +22263,7 @@ function buildDoctorActivationExtraArgs(admitted, options = {}) {
21907
22263
  prompt
21908
22264
  ];
21909
22265
  }
21910
- async function presentControlledFailure3(admitted, failureInput, io) {
22266
+ async function presentControlledFailure4(admitted, failureInput, io) {
21911
22267
  const hasThrown = Object.hasOwn(failureInput, "thrown");
21912
22268
  const session = !hasThrown && !failureInput.timedOut && failureInput.knownFailure === void 0 ? await inspectJudgeSession(admitted.sessionFile) : void 0;
21913
22269
  const failure = classifyPostAdmissionFailure({
@@ -21935,7 +22291,7 @@ async function dispatchAdmittedDoctor(input) {
21935
22291
  env.credentials
21936
22292
  );
21937
22293
  if (missingCredential !== void 0) {
21938
- return await presentControlledFailure3(
22294
+ return await presentControlledFailure4(
21939
22295
  admitted,
21940
22296
  missingCredential,
21941
22297
  io
@@ -21965,7 +22321,7 @@ async function dispatchAdmittedDoctor(input) {
21965
22321
  ...env.piRunner === void 0 ? {} : { runner: env.piRunner }
21966
22322
  });
21967
22323
  } catch (error) {
21968
- return await presentControlledFailure3(
22324
+ return await presentControlledFailure4(
21969
22325
  admitted,
21970
22326
  {
21971
22327
  timedOut: false,
@@ -21988,7 +22344,7 @@ async function dispatchAdmittedDoctor(input) {
21988
22344
  try {
21989
22345
  lawful = await trySettleDoctorTerminalResult(admitted);
21990
22346
  } catch (error) {
21991
- return await presentControlledFailure3(
22347
+ return await presentControlledFailure4(
21992
22348
  admitted,
21993
22349
  {
21994
22350
  timedOut: false,
@@ -22033,7 +22389,7 @@ async function dispatchAdmittedDoctor(input) {
22033
22389
  credential: credentialFailure,
22034
22390
  runDirectory: admitted.runDirectory
22035
22391
  });
22036
- return await presentControlledFailure3(
22392
+ return await presentControlledFailure4(
22037
22393
  admitted,
22038
22394
  {
22039
22395
  timedOut: result2.timedOut,
@@ -22187,7 +22543,7 @@ function buildFixerResumeActivationExtraArgs(admitted, options) {
22187
22543
  RESUME_TRANSPORT_ENVELOPE
22188
22544
  ];
22189
22545
  }
22190
- async function presentControlledFailure4(admitted, failureInput, io) {
22546
+ async function presentControlledFailure5(admitted, failureInput, io) {
22191
22547
  const hasThrown = Object.hasOwn(failureInput, "thrown");
22192
22548
  const resumeObservation = await resolveControlledFailureResumeObservation({
22193
22549
  runDirectory: admitted.runDirectory,
@@ -22240,7 +22596,7 @@ async function dispatchAdmittedFixer(input) {
22240
22596
  env.credentials
22241
22597
  );
22242
22598
  if (missingCredential !== void 0) {
22243
- return await presentControlledFailure4(
22599
+ return await presentControlledFailure5(
22244
22600
  admitted,
22245
22601
  missingCredential,
22246
22602
  io
@@ -22271,7 +22627,7 @@ async function dispatchAdmittedFixer(input) {
22271
22627
  ...env.piRunner === void 0 ? {} : { runner: env.piRunner }
22272
22628
  });
22273
22629
  } catch (error) {
22274
- return await presentControlledFailure4(
22630
+ return await presentControlledFailure5(
22275
22631
  admitted,
22276
22632
  {
22277
22633
  timedOut: false,
@@ -22301,7 +22657,7 @@ async function dispatchAdmittedFixer(input) {
22301
22657
  )
22302
22658
  });
22303
22659
  } catch (error) {
22304
- return await presentControlledFailure4(
22660
+ return await presentControlledFailure5(
22305
22661
  admitted,
22306
22662
  {
22307
22663
  timedOut: false,
@@ -22346,7 +22702,7 @@ async function dispatchAdmittedFixer(input) {
22346
22702
  credential: credentialFailure,
22347
22703
  runDirectory: admitted.runDirectory
22348
22704
  });
22349
- return await presentControlledFailure4(
22705
+ return await presentControlledFailure5(
22350
22706
  admitted,
22351
22707
  {
22352
22708
  timedOut: result2.timedOut,
@@ -22400,7 +22756,7 @@ async function runPublicFixer(argv, env, io, parseFixerArgv2) {
22400
22756
  methodMaterial = await loadFixerMethodMaterial(env.packageRoot);
22401
22757
  } catch (error) {
22402
22758
  await lease.release();
22403
- return await presentControlledFailure4(
22759
+ return await presentControlledFailure5(
22404
22760
  admitted,
22405
22761
  {
22406
22762
  timedOut: false,
@@ -22470,7 +22826,7 @@ async function runPublicFixerResume(argv, env, io) {
22470
22826
  methodMaterial = await loadFixerMethodMaterial(env.packageRoot);
22471
22827
  } catch (error) {
22472
22828
  await lease.release();
22473
- return await presentControlledFailure4(
22829
+ return await presentControlledFailure5(
22474
22830
  admitted,
22475
22831
  {
22476
22832
  timedOut: false,
@@ -22566,7 +22922,7 @@ function buildJudgeResumeActivationExtraArgs(admitted, options = {}) {
22566
22922
  RESUME_TRANSPORT_ENVELOPE
22567
22923
  ];
22568
22924
  }
22569
- async function presentControlledFailure5(admitted, failureInput, io) {
22925
+ async function presentControlledFailure6(admitted, failureInput, io) {
22570
22926
  const hasThrown = Object.hasOwn(failureInput, "thrown");
22571
22927
  const resumeObservation = await resolveControlledFailureResumeObservation({
22572
22928
  runDirectory: admitted.runDirectory,
@@ -22619,7 +22975,7 @@ async function dispatchAdmittedJudge(input) {
22619
22975
  env.credentials
22620
22976
  );
22621
22977
  if (missingCredential !== void 0) {
22622
- return await presentControlledFailure5(
22978
+ return await presentControlledFailure6(
22623
22979
  admitted,
22624
22980
  missingCredential,
22625
22981
  io
@@ -22652,7 +23008,7 @@ async function dispatchAdmittedJudge(input) {
22652
23008
  ...env.piRunner === void 0 ? {} : { runner: env.piRunner }
22653
23009
  });
22654
23010
  } catch (error) {
22655
- return await presentControlledFailure5(
23011
+ return await presentControlledFailure6(
22656
23012
  admitted,
22657
23013
  {
22658
23014
  timedOut: false,
@@ -22675,7 +23031,7 @@ async function dispatchAdmittedJudge(input) {
22675
23031
  try {
22676
23032
  lawful = await trySettleJudgeTerminalResult(admitted);
22677
23033
  } catch (error) {
22678
- return await presentControlledFailure5(
23034
+ return await presentControlledFailure6(
22679
23035
  admitted,
22680
23036
  {
22681
23037
  timedOut: false,
@@ -22720,7 +23076,7 @@ async function dispatchAdmittedJudge(input) {
22720
23076
  credential: credentialFailure,
22721
23077
  runDirectory: admitted.runDirectory
22722
23078
  });
22723
- return await presentControlledFailure5(
23079
+ return await presentControlledFailure6(
22724
23080
  admitted,
22725
23081
  {
22726
23082
  timedOut: result2.timedOut,
@@ -22913,7 +23269,7 @@ function buildMergerResumeActivationExtraArgs(admitted, options) {
22913
23269
  RESUME_TRANSPORT_ENVELOPE
22914
23270
  ];
22915
23271
  }
22916
- async function presentControlledFailure6(admitted, failureInput, io) {
23272
+ async function presentControlledFailure7(admitted, failureInput, io) {
22917
23273
  const hasThrown = Object.hasOwn(failureInput, "thrown");
22918
23274
  const resumeObservation = await resolveControlledFailureResumeObservation({
22919
23275
  runDirectory: admitted.runDirectory,
@@ -22969,7 +23325,7 @@ async function dispatchAdmittedMerger(input) {
22969
23325
  env.credentials
22970
23326
  );
22971
23327
  if (missingCredential !== void 0) {
22972
- return await presentControlledFailure6(
23328
+ return await presentControlledFailure7(
22973
23329
  admitted,
22974
23330
  missingCredential,
22975
23331
  io
@@ -23000,7 +23356,7 @@ async function dispatchAdmittedMerger(input) {
23000
23356
  ...env.piRunner === void 0 ? {} : { runner: env.piRunner }
23001
23357
  });
23002
23358
  } catch (error) {
23003
- return await presentControlledFailure6(
23359
+ return await presentControlledFailure7(
23004
23360
  admitted,
23005
23361
  {
23006
23362
  timedOut: false,
@@ -23030,7 +23386,7 @@ async function dispatchAdmittedMerger(input) {
23030
23386
  )
23031
23387
  });
23032
23388
  } catch (error) {
23033
- return await presentControlledFailure6(
23389
+ return await presentControlledFailure7(
23034
23390
  admitted,
23035
23391
  {
23036
23392
  timedOut: false,
@@ -23061,7 +23417,7 @@ async function dispatchAdmittedMerger(input) {
23061
23417
  credential: credentialFailure,
23062
23418
  runDirectory: admitted.runDirectory
23063
23419
  });
23064
- return await presentControlledFailure6(
23420
+ return await presentControlledFailure7(
23065
23421
  admitted,
23066
23422
  {
23067
23423
  timedOut: result2.timedOut,
@@ -23167,7 +23523,7 @@ async function runPublicMerger(argv, env, io, parseMergerArgv2) {
23167
23523
  ...env.createRunId === void 0 ? {} : { createRunId: env.createRunId }
23168
23524
  });
23169
23525
  await markRunAdmitted(shell);
23170
- return await presentControlledFailure6(
23526
+ return await presentControlledFailure7(
23171
23527
  shell,
23172
23528
  {
23173
23529
  timedOut: false,
@@ -23198,7 +23554,7 @@ async function runPublicMerger(argv, env, io, parseMergerArgv2) {
23198
23554
  methodMaterial = await loadMergerMethodMaterial(env.packageRoot);
23199
23555
  } catch (error) {
23200
23556
  await lease.release();
23201
- return await presentControlledFailure6(
23557
+ return await presentControlledFailure7(
23202
23558
  admitted,
23203
23559
  {
23204
23560
  timedOut: false,
@@ -23269,7 +23625,7 @@ async function runPublicMergerResume(argv, env, io) {
23269
23625
  methodMaterial = await loadMergerMethodMaterial(env.packageRoot);
23270
23626
  } catch (error) {
23271
23627
  await lease.release();
23272
- return await presentControlledFailure6(
23628
+ return await presentControlledFailure7(
23273
23629
  admitted,
23274
23630
  {
23275
23631
  timedOut: false,
@@ -23335,6 +23691,7 @@ function buildReviewerActivationExtraArgs(admitted, options) {
23335
23691
  options.packageRoot,
23336
23692
  "code-review"
23337
23693
  );
23694
+ const authorityRefArgs = admitted.authorityRefs.length === 0 ? [] : ["--ak-review-authority-refs", JSON.stringify([...admitted.authorityRefs])];
23338
23695
  return [
23339
23696
  "--no-skills",
23340
23697
  "--skill",
@@ -23351,6 +23708,7 @@ function buildReviewerActivationExtraArgs(admitted, options) {
23351
23708
  "reviewer",
23352
23709
  "--ak-review-base",
23353
23710
  admitted.baseRevision,
23711
+ ...authorityRefArgs,
23354
23712
  "--mode",
23355
23713
  "json",
23356
23714
  ...buildModelArgs7(options.model),
@@ -23362,6 +23720,7 @@ function buildReviewerResumeActivationExtraArgs(admitted, options) {
23362
23720
  options.packageRoot,
23363
23721
  "code-review"
23364
23722
  );
23723
+ const authorityRefArgs = admitted.authorityRefs.length === 0 ? [] : ["--ak-review-authority-refs", JSON.stringify([...admitted.authorityRefs])];
23365
23724
  return [
23366
23725
  "--no-skills",
23367
23726
  "--skill",
@@ -23378,13 +23737,14 @@ function buildReviewerResumeActivationExtraArgs(admitted, options) {
23378
23737
  "reviewer",
23379
23738
  "--ak-review-base",
23380
23739
  admitted.baseRevision,
23740
+ ...authorityRefArgs,
23381
23741
  "--mode",
23382
23742
  "json",
23383
23743
  ...buildModelArgs7(options.model),
23384
23744
  RESUME_TRANSPORT_ENVELOPE
23385
23745
  ];
23386
23746
  }
23387
- async function presentControlledFailure7(admitted, failureInput, io) {
23747
+ async function presentControlledFailure8(admitted, failureInput, io) {
23388
23748
  const hasThrown = Object.hasOwn(failureInput, "thrown");
23389
23749
  const resumeObservation = await resolveControlledFailureResumeObservation({
23390
23750
  runDirectory: admitted.runDirectory,
@@ -23437,7 +23797,7 @@ async function dispatchAdmittedReviewer(input) {
23437
23797
  env.credentials
23438
23798
  );
23439
23799
  if (missingCredential !== void 0) {
23440
- return await presentControlledFailure7(
23800
+ return await presentControlledFailure8(
23441
23801
  admitted,
23442
23802
  missingCredential,
23443
23803
  io
@@ -23469,7 +23829,7 @@ async function dispatchAdmittedReviewer(input) {
23469
23829
  ...env.piRunner === void 0 ? {} : { runner: env.piRunner }
23470
23830
  });
23471
23831
  } catch (error) {
23472
- return await presentControlledFailure7(
23832
+ return await presentControlledFailure8(
23473
23833
  admitted,
23474
23834
  {
23475
23835
  timedOut: false,
@@ -23499,7 +23859,7 @@ async function dispatchAdmittedReviewer(input) {
23499
23859
  )
23500
23860
  });
23501
23861
  } catch (error) {
23502
- return await presentControlledFailure7(
23862
+ return await presentControlledFailure8(
23503
23863
  admitted,
23504
23864
  {
23505
23865
  timedOut: false,
@@ -23544,7 +23904,7 @@ async function dispatchAdmittedReviewer(input) {
23544
23904
  credential: credentialFailure,
23545
23905
  runDirectory: admitted.runDirectory
23546
23906
  });
23547
- return await presentControlledFailure7(
23907
+ return await presentControlledFailure8(
23548
23908
  admitted,
23549
23909
  {
23550
23910
  timedOut: result2.timedOut,
@@ -23571,6 +23931,7 @@ async function runPublicReviewer(argv, env, io, parseReviewerArgv2) {
23571
23931
  instruction: parsed.instruction,
23572
23932
  attachmentPaths: parsed.attachmentPaths,
23573
23933
  baseRevision: parsed.baseRevision,
23934
+ authorityRefs: parsed.authorityRefs,
23574
23935
  ...parsed.project === void 0 ? {} : { project: parsed.project },
23575
23936
  ...env.createRunId === void 0 ? {} : { createRunId: env.createRunId }
23576
23937
  });
@@ -23597,7 +23958,7 @@ async function runPublicReviewer(argv, env, io, parseReviewerArgv2) {
23597
23958
  methodMaterial = await loadReviewerMethodMaterial(env.packageRoot);
23598
23959
  } catch (error) {
23599
23960
  await lease.release();
23600
- return await presentControlledFailure7(
23961
+ return await presentControlledFailure8(
23601
23962
  admitted,
23602
23963
  {
23603
23964
  timedOut: false,
@@ -23667,7 +24028,7 @@ async function runPublicReviewerResume(argv, env, io) {
23667
24028
  methodMaterial = await loadReviewerMethodMaterial(env.packageRoot);
23668
24029
  } catch (error) {
23669
24030
  await lease.release();
23670
- return await presentControlledFailure7(
24031
+ return await presentControlledFailure8(
23671
24032
  admitted,
23672
24033
  {
23673
24034
  timedOut: false,
@@ -23709,22 +24070,2080 @@ var init_reviewer_run = __esm({
23709
24070
  }
23710
24071
  });
23711
24072
 
23712
- // src/public-cli/cli.ts
23713
- var cli_exports = {};
23714
- __export(cli_exports, {
23715
- CliUsageError: () => CliUsageError,
23716
- PUBLIC_ROLE_ARGV: () => PUBLIC_ROLE_ARGV,
23717
- buildExplicitInternalActivationArgs: () => buildExplicitInternalActivationArgs,
23718
- helpDocument: () => helpDocument,
23719
- resolveInternalRoleEntrypoint: () => resolveInternalRoleEntrypoint,
23720
- runAkRole: () => runAkRole
23721
- });
23722
- import { realpath as realpath5 } from "node:fs/promises";
23723
- import { homedir as homedir3 } from "node:os";
23724
- import { join as join18 } from "node:path";
23725
- function takePublicGlobalFlag(argv, index) {
23726
- const token = argv[index];
23727
- if (token === void 0) return void 0;
24073
+ // src/atomic-write.ts
24074
+ import { randomUUID as randomUUID2 } from "node:crypto";
24075
+ import { rename, rm, writeFile as writeFile13 } from "node:fs/promises";
24076
+ import { dirname as dirname7, join as join18 } from "node:path";
24077
+ async function writeFileAtomically(destination, contents) {
24078
+ const parent = dirname7(destination);
24079
+ const temporary = join18(parent, `.atomic-write-${randomUUID2()}.tmp`);
24080
+ try {
24081
+ await writeFile13(temporary, contents);
24082
+ await rename(temporary, destination);
24083
+ } catch (error) {
24084
+ await rm(temporary, { force: true }).catch(() => void 0);
24085
+ throw error;
24086
+ }
24087
+ }
24088
+ var init_atomic_write = __esm({
24089
+ "src/atomic-write.ts"() {
24090
+ "use strict";
24091
+ }
24092
+ });
24093
+
24094
+ // src/taishi-index.ts
24095
+ import { open as open3, readFile as readFile10, unlink as unlink4 } from "node:fs/promises";
24096
+ import { dirname as dirname8, join as join19 } from "node:path";
24097
+ function sleep(ms) {
24098
+ return new Promise((resolve9) => {
24099
+ setTimeout(resolve9, ms);
24100
+ });
24101
+ }
24102
+ async function withTaishiLibraryIndexLock(ledgerHome, fn) {
24103
+ const indexPath = taishiLibraryIndexPath(ledgerHome);
24104
+ ensureRealDirectoryTree(ledgerHome, dirname8(indexPath));
24105
+ const lockPath = join19(dirname8(indexPath), LIBRARY_INDEX_LOCK_NAME);
24106
+ assertLedgerFileInsideHome(lockPath, ledgerHome);
24107
+ const startedAt = Date.now();
24108
+ while (true) {
24109
+ try {
24110
+ const handle = await open3(lockPath, "wx");
24111
+ try {
24112
+ await handle.writeFile(`${process.pid}
24113
+ `, "utf8");
24114
+ return await fn();
24115
+ } finally {
24116
+ await handle.close().catch(() => void 0);
24117
+ await unlink4(lockPath).catch(() => void 0);
24118
+ }
24119
+ } catch (error) {
24120
+ const code = error instanceof Error && "code" in error ? error.code : void 0;
24121
+ if (code !== "EEXIST") throw error;
24122
+ if (Date.now() - startedAt > LIBRARY_INDEX_LOCK_TIMEOUT_MS) {
24123
+ throw new Error(
24124
+ `taishi library-index lock timeout after ${LIBRARY_INDEX_LOCK_TIMEOUT_MS}ms: ${lockPath}`
24125
+ );
24126
+ }
24127
+ await sleep(LIBRARY_INDEX_LOCK_RETRY_MS);
24128
+ }
24129
+ }
24130
+ }
24131
+ function taishiLibraryIndexPath(ledgerHome) {
24132
+ return join19(ledgerHome, "taishi", "library-index.json");
24133
+ }
24134
+ function rowFromIssueMetricsPage(page) {
24135
+ return {
24136
+ projectRoot: page.projectRoot,
24137
+ // exactOptionalPropertyTypes: only materialize when page carries it.
24138
+ ...page.issueNumber === void 0 ? {} : { issueNumber: page.issueNumber },
24139
+ totalElapsedMs: page.totalElapsedMs,
24140
+ changedLines: page.changedLines,
24141
+ msPerKLines: page.msPerKLines,
24142
+ lastActivityAt: page.lastActivityAt
24143
+ };
24144
+ }
24145
+ function sortRows(rows) {
24146
+ return [...rows].sort((a, b) => {
24147
+ const byRoot = a.projectRoot.localeCompare(b.projectRoot);
24148
+ if (byRoot !== 0) return byRoot;
24149
+ const aNum = a.issueNumber;
24150
+ const bNum = b.issueNumber;
24151
+ if (aNum === void 0 && bNum === void 0) return 0;
24152
+ if (aNum === void 0) return 1;
24153
+ if (bNum === void 0) return -1;
24154
+ return aNum - bNum;
24155
+ });
24156
+ }
24157
+ function buildTaishiLibraryIndexPage(rows) {
24158
+ return {
24159
+ kind: "taishi-library-index",
24160
+ rows: sortRows(rows)
24161
+ };
24162
+ }
24163
+ function findTaishiLibraryIndexRow(index, issueNumber) {
24164
+ if (index === void 0) return void 0;
24165
+ return index.rows.find((row) => row.issueNumber === issueNumber);
24166
+ }
24167
+ function upsertTaishiLibraryIndexRows(existing, upserts) {
24168
+ const byRoot = /* @__PURE__ */ new Map();
24169
+ const rootByIssue = /* @__PURE__ */ new Map();
24170
+ const ingest = (row) => {
24171
+ if (row.issueNumber !== void 0) {
24172
+ const priorRoot = rootByIssue.get(row.issueNumber);
24173
+ if (priorRoot !== void 0 && priorRoot !== row.projectRoot) {
24174
+ byRoot.delete(priorRoot);
24175
+ }
24176
+ }
24177
+ const prior = byRoot.get(row.projectRoot);
24178
+ if (prior !== void 0 && prior.issueNumber !== void 0 && prior.issueNumber !== row.issueNumber) {
24179
+ rootByIssue.delete(prior.issueNumber);
24180
+ }
24181
+ byRoot.set(row.projectRoot, row);
24182
+ if (row.issueNumber !== void 0) {
24183
+ rootByIssue.set(row.issueNumber, row.projectRoot);
24184
+ }
24185
+ };
24186
+ if (existing !== void 0) {
24187
+ for (const row of existing.rows) {
24188
+ ingest(row);
24189
+ }
24190
+ }
24191
+ for (const row of upserts) {
24192
+ ingest(row);
24193
+ }
24194
+ return buildTaishiLibraryIndexPage([...byRoot.values()]);
24195
+ }
24196
+ async function readTaishiLibraryIndexPage(ledgerHome) {
24197
+ const path = taishiLibraryIndexPath(ledgerHome);
24198
+ let raw;
24199
+ try {
24200
+ raw = await readFile10(path, "utf8");
24201
+ } catch (error) {
24202
+ if (error instanceof Error && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR")) {
24203
+ return void 0;
24204
+ }
24205
+ throw error;
24206
+ }
24207
+ return JSON.parse(raw);
24208
+ }
24209
+ async function writeTaishiLibraryIndexPage(ledgerHome, page) {
24210
+ const path = taishiLibraryIndexPath(ledgerHome);
24211
+ ensureRealDirectoryTree(ledgerHome, dirname8(path));
24212
+ assertLedgerFileInsideHome(path, ledgerHome);
24213
+ await writeFileAtomically(path, `${JSON.stringify(page, null, 2)}
24214
+ `);
24215
+ return path;
24216
+ }
24217
+ async function mergeTaishiLibraryIndexRows(ledgerHome, upserts) {
24218
+ return withTaishiLibraryIndexLock(ledgerHome, async () => {
24219
+ const existing = await readTaishiLibraryIndexPage(ledgerHome);
24220
+ const index = upsertTaishiLibraryIndexRows(existing, upserts);
24221
+ const indexPath = await writeTaishiLibraryIndexPage(ledgerHome, index);
24222
+ return { index, indexPath };
24223
+ });
24224
+ }
24225
+ var LIBRARY_INDEX_LOCK_NAME, LIBRARY_INDEX_LOCK_TIMEOUT_MS, LIBRARY_INDEX_LOCK_RETRY_MS;
24226
+ var init_taishi_index = __esm({
24227
+ "src/taishi-index.ts"() {
24228
+ "use strict";
24229
+ init_atomic_write();
24230
+ init_activation_ledger_topology();
24231
+ LIBRARY_INDEX_LOCK_NAME = ".library-index.lock";
24232
+ LIBRARY_INDEX_LOCK_TIMEOUT_MS = 3e4;
24233
+ LIBRARY_INDEX_LOCK_RETRY_MS = 15;
24234
+ }
24235
+ });
24236
+
24237
+ // src/taishi-median.ts
24238
+ function medianNumber(values) {
24239
+ if (values.length === 0) return void 0;
24240
+ const sorted = [...values].sort((a, b) => a - b);
24241
+ const mid = Math.floor(sorted.length / 2);
24242
+ if (sorted.length % 2 === 1) {
24243
+ return sorted[mid];
24244
+ }
24245
+ return (sorted[mid - 1] + sorted[mid]) / 2;
24246
+ }
24247
+ var init_taishi_median = __esm({
24248
+ "src/taishi-median.ts"() {
24249
+ "use strict";
24250
+ }
24251
+ });
24252
+
24253
+ // src/taishi-cohort.ts
24254
+ function presentMetric(value) {
24255
+ return { status: "present", value };
24256
+ }
24257
+ function rateMetric(numerator, denominator) {
24258
+ if (denominator === 0) return ABSENT;
24259
+ return presentMetric(numerator / denominator);
24260
+ }
24261
+ function optionalMedian(values) {
24262
+ const median = medianNumber(values);
24263
+ return median === void 0 ? ABSENT : presentMetric(median);
24264
+ }
24265
+ function emptyRoleAccum() {
24266
+ return {
24267
+ convergenceRounds: [],
24268
+ firstPassLaneCount: 0,
24269
+ appearanceLaneCount: 0,
24270
+ successCount: 0,
24271
+ successEligibleCount: 0
24272
+ };
24273
+ }
24274
+ function absorbRole(accum, stats) {
24275
+ accum.convergenceRounds.push(...stats.convergenceRounds);
24276
+ accum.firstPassLaneCount += stats.firstPassLaneCount;
24277
+ accum.appearanceLaneCount += stats.appearanceLaneCount;
24278
+ accum.successCount += stats.successCount;
24279
+ accum.successEligibleCount += stats.successEligibleCount;
24280
+ }
24281
+ function finishRole(role, accum) {
24282
+ return {
24283
+ role,
24284
+ convergenceRounds: accum.convergenceRounds,
24285
+ convergenceRoundsMedian: optionalMedian(accum.convergenceRounds),
24286
+ firstPassRate: rateMetric(accum.firstPassLaneCount, accum.appearanceLaneCount),
24287
+ successRate: rateMetric(accum.successCount, accum.successEligibleCount)
24288
+ };
24289
+ }
24290
+ async function aggregateGroup(index, input, ensureIssuePage) {
24291
+ const issueEntries = [];
24292
+ const roleAccums = /* @__PURE__ */ new Map();
24293
+ let reworkWallMs = 0;
24294
+ let totalWallMs = 0;
24295
+ let hasReworkSample = false;
24296
+ const legWalls = [];
24297
+ for (const issueNumber of input.issues) {
24298
+ const row = findTaishiLibraryIndexRow(index, issueNumber);
24299
+ if (row === void 0) {
24300
+ issueEntries.push({ issueNumber, status: "absent" });
24301
+ continue;
24302
+ }
24303
+ const page = await ensureIssuePage({
24304
+ projectRoot: row.projectRoot,
24305
+ issueNumber
24306
+ });
24307
+ issueEntries.push({
24308
+ issueNumber,
24309
+ status: "present",
24310
+ projectRoot: row.projectRoot
24311
+ });
24312
+ const acceptance = page.acceptanceSuccessRework;
24313
+ if (acceptance !== void 0) {
24314
+ for (const roleStats of acceptance.byRole) {
24315
+ const accum = roleAccums.get(roleStats.role) ?? emptyRoleAccum();
24316
+ absorbRole(accum, roleStats);
24317
+ roleAccums.set(roleStats.role, accum);
24318
+ }
24319
+ reworkWallMs += acceptance.rework.reworkWallMs;
24320
+ totalWallMs += acceptance.rework.totalWallMs;
24321
+ hasReworkSample = true;
24322
+ }
24323
+ const legWallClock = page.legWallClock;
24324
+ if (legWallClock !== void 0) {
24325
+ for (const leg of legWallClock.ranking) {
24326
+ legWalls.push(leg.wallMs);
24327
+ }
24328
+ }
24329
+ }
24330
+ const byRole = [...roleAccums.keys()].sort((a, b) => a.localeCompare(b)).map((role) => finishRole(role, roleAccums.get(role)));
24331
+ return {
24332
+ groupLabel: input.groupLabel,
24333
+ issues: issueEntries,
24334
+ byRole,
24335
+ reworkRatio: hasReworkSample ? rateMetric(reworkWallMs, totalWallMs) : ABSENT,
24336
+ medianWallMs: optionalMedian(legWalls)
24337
+ };
24338
+ }
24339
+ async function runTaishiCohortMode(ledgerHome, input, ensureIssuePage) {
24340
+ const index = await readTaishiLibraryIndexPage(ledgerHome);
24341
+ const group0 = await aggregateGroup(index, input.groups[0], ensureIssuePage);
24342
+ const group1 = await aggregateGroup(index, input.groups[1], ensureIssuePage);
24343
+ return {
24344
+ mode: "cohort",
24345
+ groups: [group0, group1]
24346
+ };
24347
+ }
24348
+ var ABSENT;
24349
+ var init_taishi_cohort = __esm({
24350
+ "src/taishi-cohort.ts"() {
24351
+ "use strict";
24352
+ init_taishi_index();
24353
+ init_taishi_median();
24354
+ ABSENT = { status: "absent" };
24355
+ }
24356
+ });
24357
+
24358
+ // src/ledger-session-read.ts
24359
+ import { readFile as readFile11 } from "node:fs/promises";
24360
+ function isRecord6(value) {
24361
+ return typeof value === "object" && value !== null && !Array.isArray(value);
24362
+ }
24363
+ async function readLedgerSessionJsonl(path) {
24364
+ const text = await readFile11(path, "utf8");
24365
+ const lines = text.split("\n");
24366
+ const rows = [];
24367
+ for (let index = 0; index < lines.length; index += 1) {
24368
+ const line2 = lines[index];
24369
+ if (!line2.trim()) continue;
24370
+ let row;
24371
+ try {
24372
+ row = JSON.parse(line2);
24373
+ } catch (error) {
24374
+ if (!(error instanceof SyntaxError)) throw error;
24375
+ const completedByTerminator = index < lines.length - 1;
24376
+ if (completedByTerminator) {
24377
+ throw new LedgerSessionJsonlError(
24378
+ `malformed JSONL record in ${path} at line ${index + 1}: ${error.message}`,
24379
+ { path, line: index + 1, prefixRows: rows }
24380
+ );
24381
+ }
24382
+ break;
24383
+ }
24384
+ if (!isRecord6(row)) {
24385
+ const kind = row === null ? "null" : Array.isArray(row) ? "array" : typeof row;
24386
+ throw new LedgerSessionJsonlError(
24387
+ `complete non-object JSONL record in ${path} at line ${index + 1}: expected object, got ${kind}`,
24388
+ { path, line: index + 1, prefixRows: rows }
24389
+ );
24390
+ }
24391
+ rows.push(row);
24392
+ }
24393
+ return rows;
24394
+ }
24395
+ function extractSessionTimestampSpan(rows) {
24396
+ let startedAt;
24397
+ let endedAt;
24398
+ for (const row of rows) {
24399
+ if (typeof row.timestamp !== "string" || !row.timestamp) continue;
24400
+ if (startedAt === void 0) startedAt = row.timestamp;
24401
+ endedAt = row.timestamp;
24402
+ }
24403
+ return {
24404
+ ...startedAt !== void 0 ? { startedAt } : {},
24405
+ ...endedAt !== void 0 ? { endedAt } : {}
24406
+ };
24407
+ }
24408
+ function extractSessionModelSequence(rows) {
24409
+ const seen = /* @__PURE__ */ new Set();
24410
+ const ordered = [];
24411
+ const push = (raw) => {
24412
+ const model = raw.trim();
24413
+ if (model === "" || seen.has(model)) return;
24414
+ seen.add(model);
24415
+ ordered.push(model);
24416
+ };
24417
+ for (const row of rows) {
24418
+ if (row.type === "model_change" && typeof row.modelId === "string") {
24419
+ push(row.modelId);
24420
+ }
24421
+ const message = isRecord6(row.message) ? row.message : void 0;
24422
+ if (message?.role === "assistant" && typeof message.model === "string") {
24423
+ push(message.model);
24424
+ }
24425
+ }
24426
+ return ordered;
24427
+ }
24428
+ function bashCommandFirstLine(command) {
24429
+ const match = /^[^\r\n]*/.exec(command);
24430
+ return match?.[0] ?? "";
24431
+ }
24432
+ function extractSessionToolIntervals(rows) {
24433
+ const order = [];
24434
+ const openById = /* @__PURE__ */ new Map();
24435
+ for (const row of rows) {
24436
+ const rowTimestamp = typeof row.timestamp === "string" ? row.timestamp : void 0;
24437
+ const message = isRecord6(row.message) ? row.message : void 0;
24438
+ if (message?.role === "assistant" && Array.isArray(message.content)) {
24439
+ const callTimestamp = typeof message.timestamp === "string" && message.timestamp ? message.timestamp : rowTimestamp;
24440
+ for (const part of message.content) {
24441
+ if (!isRecord6(part) || part.type !== "toolCall") continue;
24442
+ if (typeof part.id !== "string" || part.id.length === 0) {
24443
+ throw new Error("toolCall frame missing string id");
24444
+ }
24445
+ if (typeof part.name !== "string" || part.name.length === 0) {
24446
+ throw new Error(`toolCall ${part.id} missing string name`);
24447
+ }
24448
+ if (callTimestamp === void 0 || callTimestamp.length === 0) {
24449
+ throw new Error(`toolCall ${part.id} missing timestamp`);
24450
+ }
24451
+ if (openById.has(part.id)) {
24452
+ throw new Error(`duplicate toolCall id ${part.id}`);
24453
+ }
24454
+ const args = isRecord6(part.arguments) ? part.arguments : void 0;
24455
+ const command = part.name === "bash" && args !== void 0 && typeof args.command === "string" ? bashCommandFirstLine(args.command) : void 0;
24456
+ const interval = {
24457
+ toolCallId: part.id,
24458
+ toolName: part.name,
24459
+ startedAt: callTimestamp,
24460
+ ...command !== void 0 ? { command } : {}
24461
+ };
24462
+ order.push(interval);
24463
+ openById.set(part.id, interval);
24464
+ }
24465
+ }
24466
+ if (message?.role === "toolResult") {
24467
+ if (typeof message.toolCallId !== "string" || message.toolCallId.length === 0) {
24468
+ throw new Error("toolResult frame missing string toolCallId");
24469
+ }
24470
+ const resultTimestamp = typeof message.timestamp === "string" && message.timestamp ? message.timestamp : rowTimestamp;
24471
+ if (resultTimestamp === void 0 || resultTimestamp.length === 0) {
24472
+ throw new Error(`toolResult ${message.toolCallId} missing timestamp`);
24473
+ }
24474
+ const open4 = openById.get(message.toolCallId);
24475
+ if (open4 === void 0) {
24476
+ const toolName = typeof message.toolName === "string" && message.toolName.length > 0 ? message.toolName : "unknown";
24477
+ order.push({
24478
+ toolCallId: message.toolCallId,
24479
+ toolName,
24480
+ startedAt: resultTimestamp,
24481
+ endedAt: resultTimestamp
24482
+ });
24483
+ continue;
24484
+ }
24485
+ if (open4.endedAt !== void 0) {
24486
+ throw new Error(`duplicate toolResult for toolCallId ${message.toolCallId}`);
24487
+ }
24488
+ open4.endedAt = resultTimestamp;
24489
+ }
24490
+ }
24491
+ return order.map((interval) => {
24492
+ const base = {
24493
+ toolCallId: interval.toolCallId,
24494
+ toolName: interval.toolName,
24495
+ startedAt: interval.startedAt,
24496
+ ...interval.command !== void 0 ? { command: interval.command } : {}
24497
+ };
24498
+ return interval.endedAt === void 0 ? base : { ...base, endedAt: interval.endedAt };
24499
+ });
24500
+ }
24501
+ var LedgerSessionJsonlError;
24502
+ var init_ledger_session_read = __esm({
24503
+ "src/ledger-session-read.ts"() {
24504
+ "use strict";
24505
+ LedgerSessionJsonlError = class extends Error {
24506
+ path;
24507
+ line;
24508
+ prefixRows;
24509
+ constructor(message, init) {
24510
+ super(message);
24511
+ this.name = "LedgerSessionJsonlError";
24512
+ this.path = init.path;
24513
+ this.line = init.line;
24514
+ this.prefixRows = init.prefixRows;
24515
+ }
24516
+ };
24517
+ }
24518
+ });
24519
+
24520
+ // src/run-terminal-artifacts.ts
24521
+ import { readdir as readdir4, readFile as readFile12 } from "node:fs/promises";
24522
+ import { basename as basename4, dirname as dirname9, join as join20 } from "node:path";
24523
+ function isMissingPathError3(error) {
24524
+ return error instanceof Error && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR");
24525
+ }
24526
+ function errorText2(error) {
24527
+ return error instanceof Error ? error.message : String(error);
24528
+ }
24529
+ function isRecord7(value) {
24530
+ return typeof value === "object" && value !== null && !Array.isArray(value);
24531
+ }
24532
+ function readUsableTerminalArtifactBody(body) {
24533
+ if (body === null) {
24534
+ return { ok: false, reason: "terminal artifact JSON value is null" };
24535
+ }
24536
+ if (!isRecord7(body)) {
24537
+ return {
24538
+ ok: false,
24539
+ reason: `terminal artifact JSON value is not a typed object (${Array.isArray(body) ? "array" : typeof body})`
24540
+ };
24541
+ }
24542
+ if (typeof body.role !== "string" || body.role.trim() === "") {
24543
+ return {
24544
+ ok: false,
24545
+ reason: "terminal artifact missing nonblank producer-owned role field"
24546
+ };
24547
+ }
24548
+ return { ok: true, body };
24549
+ }
24550
+ async function readTerminalArtifactAtPath(path, file) {
24551
+ let raw;
24552
+ try {
24553
+ raw = await readFile12(path, "utf8");
24554
+ } catch (error) {
24555
+ if (isMissingPathError3(error)) return void 0;
24556
+ return {
24557
+ status: "unreadable",
24558
+ file,
24559
+ path,
24560
+ reason: errorText2(error)
24561
+ };
24562
+ }
24563
+ let parsed;
24564
+ try {
24565
+ parsed = JSON.parse(raw);
24566
+ } catch (error) {
24567
+ return {
24568
+ status: "unreadable",
24569
+ file,
24570
+ path,
24571
+ reason: error instanceof Error ? error.message : `terminal artifact JSON parse failed: ${String(error)}`
24572
+ };
24573
+ }
24574
+ const usable = readUsableTerminalArtifactBody(parsed);
24575
+ if (!usable.ok) {
24576
+ return {
24577
+ status: "unreadable",
24578
+ file,
24579
+ path,
24580
+ reason: usable.reason
24581
+ };
24582
+ }
24583
+ return { status: "present", file, path, body: usable.body };
24584
+ }
24585
+ async function listUniqueErrorFallbackPaths(directories) {
24586
+ const found = [];
24587
+ for (const dir of directories) {
24588
+ let names;
24589
+ try {
24590
+ names = await readdir4(dir);
24591
+ } catch (error) {
24592
+ if (isMissingPathError3(error)) continue;
24593
+ throw error;
24594
+ }
24595
+ for (const name of names.sort((a, b) => a.localeCompare(b))) {
24596
+ if (!UNIQUE_ERROR_FALLBACK_NAME.test(name)) continue;
24597
+ found.push(join20(dir, name));
24598
+ }
24599
+ }
24600
+ return found;
24601
+ }
24602
+ function runIdFromRunDirectory(runDirectory) {
24603
+ const name = basename4(runDirectory);
24604
+ const at = name.lastIndexOf("@");
24605
+ if (at <= 0 || at === name.length - 1) return void 0;
24606
+ return name.slice(0, at);
24607
+ }
24608
+ function presentUniqueFallbackBoundToRun(body, expectedRunId) {
24609
+ if (expectedRunId === void 0) return false;
24610
+ return typeof body.runId === "string" && body.runId === expectedRunId;
24611
+ }
24612
+ async function readRunTerminalArtifact(runDirectory) {
24613
+ const artifactsDir = join20(runDirectory, "artifacts");
24614
+ for (const file of RUN_TERMINAL_ARTIFACT_FILES) {
24615
+ const path = join20(artifactsDir, file);
24616
+ const read3 = await readTerminalArtifactAtPath(path, file);
24617
+ if (read3 !== void 0) return read3;
24618
+ }
24619
+ for (const relative3 of RUN_TERMINAL_ERROR_FALLBACK_RELATIVE_PATHS) {
24620
+ const path = join20(runDirectory, relative3);
24621
+ const read3 = await readTerminalArtifactAtPath(path, "error.json");
24622
+ if (read3 !== void 0) return read3;
24623
+ }
24624
+ for (const path of await listUniqueErrorFallbackPaths([artifactsDir, runDirectory])) {
24625
+ const read3 = await readTerminalArtifactAtPath(path, "error.json");
24626
+ if (read3 !== void 0) return read3;
24627
+ }
24628
+ const expectedRunId = runIdFromRunDirectory(runDirectory);
24629
+ for (const path of await listUniqueErrorFallbackPaths([dirname9(runDirectory)])) {
24630
+ const read3 = await readTerminalArtifactAtPath(path, "error.json");
24631
+ if (read3 === void 0) continue;
24632
+ if (read3.status === "present") {
24633
+ if (!presentUniqueFallbackBoundToRun(read3.body, expectedRunId)) continue;
24634
+ return read3;
24635
+ }
24636
+ }
24637
+ return { status: "absent" };
24638
+ }
24639
+ var RUN_TERMINAL_ARTIFACT_FILES, RUN_TERMINAL_ERROR_FALLBACK_RELATIVE_PATHS, UNIQUE_ERROR_FALLBACK_NAME;
24640
+ var init_run_terminal_artifacts = __esm({
24641
+ "src/run-terminal-artifacts.ts"() {
24642
+ "use strict";
24643
+ RUN_TERMINAL_ARTIFACT_FILES = [
24644
+ "report.json",
24645
+ "error.json",
24646
+ "audit-incomplete.json"
24647
+ ];
24648
+ RUN_TERMINAL_ERROR_FALLBACK_RELATIVE_PATHS = [
24649
+ "artifacts/error.settlement.json",
24650
+ "error.settlement.json"
24651
+ ];
24652
+ UNIQUE_ERROR_FALLBACK_NAME = /^error\.[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.json$/i;
24653
+ }
24654
+ });
24655
+
24656
+ // src/taishi-ledger.ts
24657
+ import { readdir as readdir5, readFile as readFile13 } from "node:fs/promises";
24658
+ import { join as join21 } from "node:path";
24659
+ function isMissingPathError4(error) {
24660
+ return error instanceof Error && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR");
24661
+ }
24662
+ function errorText3(error) {
24663
+ return error instanceof Error ? error.message : String(error);
24664
+ }
24665
+ function isRecord8(value) {
24666
+ return typeof value === "object" && value !== null && !Array.isArray(value);
24667
+ }
24668
+ async function readExistingRunLifecycleState(runDirectory) {
24669
+ try {
24670
+ const raw = JSON.parse(
24671
+ await readFile13(join21(runDirectory, "run-state.json"), "utf8")
24672
+ );
24673
+ if (!isRecord8(raw) || typeof raw.state !== "string") return void 0;
24674
+ return raw.state;
24675
+ } catch {
24676
+ return void 0;
24677
+ }
24678
+ }
24679
+ function parseRunDirectoryName(name) {
24680
+ const at = name.lastIndexOf("@");
24681
+ if (at <= 0 || at === name.length - 1) return void 0;
24682
+ return { runId: name.slice(0, at), role: name.slice(at + 1) };
24683
+ }
24684
+ async function readInvocationScopeFields(runDirectory) {
24685
+ let raw;
24686
+ try {
24687
+ raw = await readFile13(join21(runDirectory, "invocation.json"), "utf8");
24688
+ } catch (error) {
24689
+ if (isMissingPathError4(error)) return void 0;
24690
+ throw error;
24691
+ }
24692
+ const parsed = JSON.parse(raw);
24693
+ if (!isRecord8(parsed)) return void 0;
24694
+ if (typeof parsed.projectRoot !== "string" || parsed.projectRoot.trim() === "") {
24695
+ return void 0;
24696
+ }
24697
+ const projectRoot = parsed.projectRoot;
24698
+ if (typeof parsed.ticketNumber === "number" && Number.isInteger(parsed.ticketNumber) && parsed.ticketNumber >= 1) {
24699
+ return { projectRoot, ticketNumber: parsed.ticketNumber };
24700
+ }
24701
+ return { projectRoot };
24702
+ }
24703
+ function decideIssueScope(input) {
24704
+ const projectRootMatch = input.runProjectRootIdentity === input.scopeProjectRootIdentity;
24705
+ if (input.scopeTicketNumber !== void 0 && input.runTicketNumber !== void 0) {
24706
+ if (input.runTicketNumber === input.scopeTicketNumber) {
24707
+ return { inScope: true, conflict: !projectRootMatch };
24708
+ }
24709
+ return { inScope: false, conflict: false };
24710
+ }
24711
+ return { inScope: projectRootMatch, conflict: false };
24712
+ }
24713
+ async function resolveSessionFile(runDirectory) {
24714
+ try {
24715
+ const raw = await readFile13(join21(runDirectory, "invocation.json"), "utf8");
24716
+ const parsed = JSON.parse(raw);
24717
+ if (isRecord8(parsed) && typeof parsed.sessionFile === "string" && parsed.sessionFile.trim() !== "") {
24718
+ return parsed.sessionFile;
24719
+ }
24720
+ } catch (error) {
24721
+ if (!isMissingPathError4(error)) throw error;
24722
+ }
24723
+ return join21(runDirectory, "session", "session.jsonl");
24724
+ }
24725
+ async function classifyScopedRun(input) {
24726
+ const missingSources = [];
24727
+ const reasons = [];
24728
+ let frameSpan;
24729
+ let toolIntervals;
24730
+ let terminal;
24731
+ let models = [];
24732
+ let partialFirstFrameAt = { status: "absent" };
24733
+ let partialLastFrameAt = { status: "absent" };
24734
+ const sessionFile = await resolveSessionFile(input.runDirectory);
24735
+ let rows;
24736
+ try {
24737
+ rows = await readLedgerSessionJsonl(sessionFile);
24738
+ models = extractSessionModelSequence(rows);
24739
+ const span = extractSessionTimestampSpan(rows);
24740
+ if (span.startedAt === void 0 || span.endedAt === void 0) {
24741
+ missingSources.push("session-timeline");
24742
+ reasons.push("session timeline has no usable timestamps");
24743
+ if (span.startedAt !== void 0) {
24744
+ partialFirstFrameAt = { status: "present", at: span.startedAt };
24745
+ }
24746
+ if (span.endedAt !== void 0) {
24747
+ partialLastFrameAt = { status: "present", at: span.endedAt };
24748
+ }
24749
+ } else {
24750
+ const startedMs = Date.parse(span.startedAt);
24751
+ const endedMs = Date.parse(span.endedAt);
24752
+ if (!Number.isFinite(startedMs) || !Number.isFinite(endedMs)) {
24753
+ missingSources.push("session-timeline");
24754
+ reasons.push("session timeline timestamps are not parseable instants");
24755
+ partialFirstFrameAt = { status: "present", at: span.startedAt };
24756
+ partialLastFrameAt = { status: "present", at: span.endedAt };
24757
+ } else if (endedMs < startedMs) {
24758
+ missingSources.push("session-timeline");
24759
+ reasons.push("session timeline end is earlier than start");
24760
+ partialFirstFrameAt = { status: "present", at: span.startedAt };
24761
+ partialLastFrameAt = { status: "present", at: span.endedAt };
24762
+ } else {
24763
+ frameSpan = { startedAt: span.startedAt, endedAt: span.endedAt };
24764
+ }
24765
+ }
24766
+ } catch (error) {
24767
+ missingSources.push("session-timeline");
24768
+ reasons.push(errorText3(error));
24769
+ if (error instanceof LedgerSessionJsonlError) {
24770
+ const span = extractSessionTimestampSpan(error.prefixRows);
24771
+ if (span.startedAt !== void 0) {
24772
+ partialFirstFrameAt = { status: "present", at: span.startedAt };
24773
+ }
24774
+ if (span.endedAt !== void 0) {
24775
+ partialLastFrameAt = { status: "present", at: span.endedAt };
24776
+ }
24777
+ models = extractSessionModelSequence(error.prefixRows);
24778
+ }
24779
+ }
24780
+ if (rows !== void 0 && !missingSources.includes("session-timeline")) {
24781
+ try {
24782
+ toolIntervals = extractSessionToolIntervals(rows);
24783
+ } catch (error) {
24784
+ missingSources.push("tool-association");
24785
+ reasons.push(errorText3(error));
24786
+ }
24787
+ }
24788
+ try {
24789
+ const artifact = await readRunTerminalArtifact(input.runDirectory);
24790
+ if (artifact.status === "unreadable") {
24791
+ missingSources.push("terminal-artifact");
24792
+ reasons.push(`${artifact.file}: ${artifact.reason}`);
24793
+ } else if (artifact.status === "absent") {
24794
+ const lifecycle = await readExistingRunLifecycleState(input.runDirectory);
24795
+ if (lifecycle !== void 0 && LIVE_RUN_STATES.has(lifecycle)) {
24796
+ return { kind: "live" };
24797
+ }
24798
+ terminal = { status: "absent" };
24799
+ } else {
24800
+ terminal = {
24801
+ status: "present",
24802
+ file: artifact.file,
24803
+ body: artifact.body,
24804
+ role: artifact.body.role
24805
+ };
24806
+ }
24807
+ } catch (error) {
24808
+ missingSources.push("terminal-artifact");
24809
+ reasons.push(errorText3(error));
24810
+ }
24811
+ if (missingSources.length > 0) {
24812
+ const firstFrameAt = frameSpan !== void 0 ? { status: "present", at: frameSpan.startedAt } : partialFirstFrameAt;
24813
+ const lastFrameAt = frameSpan !== void 0 ? { status: "present", at: frameSpan.endedAt } : partialLastFrameAt;
24814
+ return {
24815
+ kind: "unreadable",
24816
+ entry: {
24817
+ runId: input.runId,
24818
+ book: input.book,
24819
+ missingSources,
24820
+ reason: reasons.join("; "),
24821
+ firstFrameAt,
24822
+ lastFrameAt
24823
+ }
24824
+ };
24825
+ }
24826
+ if (frameSpan === void 0 || toolIntervals === void 0 || terminal === void 0) {
24827
+ throw new Error(
24828
+ `classifyScopedRun internal invariant: missing retained facts for ${input.runId}`
24829
+ );
24830
+ }
24831
+ return {
24832
+ kind: "readable",
24833
+ facts: {
24834
+ runId: input.runId,
24835
+ book: input.book,
24836
+ role: input.role,
24837
+ frameSpan,
24838
+ toolIntervals,
24839
+ terminal,
24840
+ models
24841
+ }
24842
+ };
24843
+ }
24844
+ async function scanTaishiIssueRuns(input) {
24845
+ const ledgerHome = resolveActivationLedgerHome();
24846
+ const scopeIdentity = physicalPathIdentity(input.projectRoot);
24847
+ const scopeTicketNumber = input.ticketNumber;
24848
+ const booksRoot = join21(ledgerHome, "books");
24849
+ let bookNames;
24850
+ try {
24851
+ const entries = await readdir5(booksRoot, { withFileTypes: true });
24852
+ bookNames = entries.filter((e) => e.isDirectory()).map((e) => e.name).sort();
24853
+ } catch (error) {
24854
+ if (isMissingPathError4(error)) {
24855
+ return { runs: [], unreadable: [], scopeConflicts: [] };
24856
+ }
24857
+ throw error;
24858
+ }
24859
+ const runs = [];
24860
+ const unreadable = [];
24861
+ const scopeConflicts = [];
24862
+ for (const book of bookNames) {
24863
+ const runsDir = join21(booksRoot, book, "runs");
24864
+ let runNames;
24865
+ try {
24866
+ const entries = await readdir5(runsDir, { withFileTypes: true });
24867
+ runNames = entries.filter((e) => e.isDirectory()).map((e) => e.name).sort();
24868
+ } catch (error) {
24869
+ if (isMissingPathError4(error)) continue;
24870
+ throw error;
24871
+ }
24872
+ for (const runName of runNames) {
24873
+ const parsed = parseRunDirectoryName(runName);
24874
+ if (parsed === void 0) continue;
24875
+ const runDirectory = join21(runsDir, runName);
24876
+ let scopeFields;
24877
+ try {
24878
+ scopeFields = await readInvocationScopeFields(runDirectory);
24879
+ } catch (error) {
24880
+ if (error instanceof SyntaxError) continue;
24881
+ throw error;
24882
+ }
24883
+ if (scopeFields === void 0) continue;
24884
+ const runProjectRootIdentity = physicalPathIdentity(scopeFields.projectRoot);
24885
+ const decision = decideIssueScope({
24886
+ scopeProjectRootIdentity: scopeIdentity,
24887
+ scopeTicketNumber,
24888
+ runProjectRootIdentity,
24889
+ runTicketNumber: scopeFields.ticketNumber
24890
+ });
24891
+ if (!decision.inScope) continue;
24892
+ if (decision.conflict) {
24893
+ scopeConflicts.push({
24894
+ runId: parsed.runId,
24895
+ ticketNumber: scopeFields.ticketNumber,
24896
+ projectRoot: runProjectRootIdentity,
24897
+ fact: "typed-ticketNumber-over-projectRoot"
24898
+ });
24899
+ }
24900
+ const classified = await classifyScopedRun({
24901
+ book,
24902
+ runId: parsed.runId,
24903
+ role: parsed.role,
24904
+ runDirectory
24905
+ });
24906
+ if (classified.kind === "readable") runs.push(classified.facts);
24907
+ else if (classified.kind === "unreadable") unreadable.push(classified.entry);
24908
+ }
24909
+ }
24910
+ return {
24911
+ runs,
24912
+ unreadable,
24913
+ scopeConflicts
24914
+ };
24915
+ }
24916
+ var LIVE_RUN_STATES;
24917
+ var init_taishi_ledger = __esm({
24918
+ "src/taishi-ledger.ts"() {
24919
+ "use strict";
24920
+ init_activation_ledger_topology();
24921
+ init_ledger_session_read();
24922
+ init_run_terminal_artifacts();
24923
+ LIVE_RUN_STATES = /* @__PURE__ */ new Set(["admitted", "running", "resumable"]);
24924
+ }
24925
+ });
24926
+
24927
+ // src/taishi-metric-families/acceptance-success-rework.ts
24928
+ function isRecord9(value) {
24929
+ return typeof value === "object" && value !== null && !Array.isArray(value);
24930
+ }
24931
+ function wallMsFromSpan(span) {
24932
+ return Date.parse(span.endedAt) - Date.parse(span.startedAt);
24933
+ }
24934
+ function findCollectorGroups(body) {
24935
+ if (Array.isArray(body.groups)) return body.groups;
24936
+ const receipt = body.receipt;
24937
+ if (isRecord9(receipt) && Array.isArray(receipt.groups)) return receipt.groups;
24938
+ const outcome = body.outcome;
24939
+ if (isRecord9(outcome)) {
24940
+ const facts = outcome.decisiveFacts;
24941
+ if (isRecord9(facts) && Array.isArray(facts.groups)) return facts.groups;
24942
+ }
24943
+ return void 0;
24944
+ }
24945
+ function extractStatus(body) {
24946
+ const outcome = body.outcome;
24947
+ if (isRecord9(outcome) && typeof outcome.status === "string" && outcome.status.trim() !== "") {
24948
+ return outcome.status;
24949
+ }
24950
+ const receipt = body.receipt;
24951
+ if (isRecord9(receipt) && typeof receipt.status === "string" && receipt.status.trim() !== "") {
24952
+ return receipt.status;
24953
+ }
24954
+ if (typeof body.status === "string" && body.status.trim() !== "") {
24955
+ return body.status;
24956
+ }
24957
+ return void 0;
24958
+ }
24959
+ function mapTerminal(role, terminal) {
24960
+ if (terminal.status === "absent") {
24961
+ return {
24962
+ terminalLabel: "no-receipt",
24963
+ accepted: false,
24964
+ success: false,
24965
+ successEligible: false,
24966
+ noReceipt: true
24967
+ };
24968
+ }
24969
+ const body = terminal.body;
24970
+ if (role === "collector") {
24971
+ const groups = findCollectorGroups(body);
24972
+ if (Array.isArray(groups)) {
24973
+ return {
24974
+ terminalLabel: "groups",
24975
+ accepted: true,
24976
+ success: true,
24977
+ successEligible: true,
24978
+ noReceipt: false
24979
+ };
24980
+ }
24981
+ return {
24982
+ terminalLabel: "non-accepted",
24983
+ accepted: false,
24984
+ success: false,
24985
+ successEligible: false,
24986
+ noReceipt: false
24987
+ };
24988
+ }
24989
+ const status = extractStatus(body);
24990
+ if (status === void 0) {
24991
+ return {
24992
+ terminalLabel: "non-accepted",
24993
+ accepted: false,
24994
+ success: false,
24995
+ successEligible: false,
24996
+ noReceipt: false
24997
+ };
24998
+ }
24999
+ const acceptedSet = ACCEPTED_STATUS[role];
25000
+ if (acceptedSet === void 0 || !acceptedSet.has(status)) {
25001
+ return {
25002
+ terminalLabel: status,
25003
+ accepted: false,
25004
+ success: false,
25005
+ successEligible: false,
25006
+ noReceipt: false
25007
+ };
25008
+ }
25009
+ const plannedDuty = WORKER_ROLES.has(role) && status === "planned";
25010
+ const successSet = SUCCESS_STATUS[role] ?? /* @__PURE__ */ new Set();
25011
+ const success = !plannedDuty && successSet.has(status);
25012
+ const successEligible = !plannedDuty;
25013
+ return {
25014
+ terminalLabel: status,
25015
+ accepted: true,
25016
+ success,
25017
+ successEligible,
25018
+ noReceipt: false
25019
+ };
25020
+ }
25021
+ function projectLegs(runs) {
25022
+ const sorted = [...runs].sort((a, b) => {
25023
+ if (a.book !== b.book) return a.book.localeCompare(b.book);
25024
+ if (a.role !== b.role) return a.role.localeCompare(b.role);
25025
+ if (a.frameSpan.startedAt !== b.frameSpan.startedAt) {
25026
+ return a.frameSpan.startedAt.localeCompare(b.frameSpan.startedAt);
25027
+ }
25028
+ return a.runId.localeCompare(b.runId);
25029
+ });
25030
+ const ordinalByKey = /* @__PURE__ */ new Map();
25031
+ const legs = [];
25032
+ for (const run of sorted) {
25033
+ const key = `${run.book}\0${run.role}`;
25034
+ const ordinal = (ordinalByKey.get(key) ?? 0) + 1;
25035
+ ordinalByKey.set(key, ordinal);
25036
+ const mapped = mapTerminal(run.role, run.terminal);
25037
+ legs.push({
25038
+ runId: run.runId,
25039
+ book: run.book,
25040
+ role: run.role,
25041
+ startedAt: run.frameSpan.startedAt,
25042
+ wallMs: wallMsFromSpan(run.frameSpan),
25043
+ terminalLabel: mapped.terminalLabel,
25044
+ accepted: mapped.accepted,
25045
+ success: mapped.success,
25046
+ successEligible: mapped.successEligible,
25047
+ noReceipt: mapped.noReceipt,
25048
+ ordinalInLaneRole: ordinal,
25049
+ rework: ordinal >= 2
25050
+ });
25051
+ }
25052
+ return legs.sort((a, b) => {
25053
+ if (a.book !== b.book) return a.book.localeCompare(b.book);
25054
+ if (a.role !== b.role) return a.role.localeCompare(b.role);
25055
+ return a.runId.localeCompare(b.runId);
25056
+ });
25057
+ }
25058
+ function aggregateByRole(legs) {
25059
+ const roles = [...new Set(legs.map((leg) => leg.role))].sort((a, b) => a.localeCompare(b));
25060
+ return roles.map((role) => {
25061
+ const roleLegs = legs.filter((leg) => leg.role === role);
25062
+ const acceptedCount = roleLegs.filter((leg) => leg.accepted).length;
25063
+ const successEligibleCount = roleLegs.filter((leg) => leg.successEligible).length;
25064
+ const successCount = roleLegs.filter((leg) => leg.success).length;
25065
+ const noReceiptCount = roleLegs.filter((leg) => leg.noReceipt).length;
25066
+ const byBook = /* @__PURE__ */ new Map();
25067
+ for (const leg of roleLegs) {
25068
+ const list = byBook.get(leg.book) ?? [];
25069
+ list.push(leg);
25070
+ byBook.set(leg.book, list);
25071
+ }
25072
+ const books = [...byBook.keys()].sort((a, b) => a.localeCompare(b));
25073
+ const convergenceRounds = [];
25074
+ let firstPassLaneCount = 0;
25075
+ for (const book of books) {
25076
+ const laneLegs = [...byBook.get(book)].sort((a, b) => {
25077
+ if (a.startedAt !== b.startedAt) return a.startedAt.localeCompare(b.startedAt);
25078
+ return a.runId.localeCompare(b.runId);
25079
+ });
25080
+ convergenceRounds.push(laneLegs.length);
25081
+ const first = laneLegs[0];
25082
+ if (first.accepted) firstPassLaneCount += 1;
25083
+ }
25084
+ const appearanceLaneCount = books.length;
25085
+ return {
25086
+ role,
25087
+ acceptedCount,
25088
+ successEligibleCount,
25089
+ successCount,
25090
+ noReceiptCount,
25091
+ successRate: successEligibleCount === 0 ? void 0 : successCount / successEligibleCount,
25092
+ appearanceLaneCount,
25093
+ firstPassLaneCount,
25094
+ firstPassRate: appearanceLaneCount === 0 ? void 0 : firstPassLaneCount / appearanceLaneCount,
25095
+ convergenceRounds,
25096
+ convergenceRoundsMedian: medianNumber(convergenceRounds)
25097
+ };
25098
+ });
25099
+ }
25100
+ function reworkLens(legs) {
25101
+ let reworkWallMs = 0;
25102
+ let totalWallMs = 0;
25103
+ let reworkLegCount = 0;
25104
+ for (const leg of legs) {
25105
+ totalWallMs += leg.wallMs;
25106
+ if (leg.rework) {
25107
+ reworkWallMs += leg.wallMs;
25108
+ reworkLegCount += 1;
25109
+ }
25110
+ }
25111
+ return {
25112
+ reworkWallMs,
25113
+ totalWallMs,
25114
+ reworkRatio: totalWallMs === 0 ? void 0 : reworkWallMs / totalWallMs,
25115
+ reworkLegCount,
25116
+ totalLegCount: legs.length
25117
+ };
25118
+ }
25119
+ function buildAcceptanceSuccessReworkSection(runs) {
25120
+ if (runs.length === 0) return void 0;
25121
+ const legs = projectLegs(runs);
25122
+ return {
25123
+ kind: "taishi-acceptance-success-rework",
25124
+ legs,
25125
+ byRole: aggregateByRole(legs),
25126
+ rework: reworkLens(legs)
25127
+ };
25128
+ }
25129
+ var WORKER_ROLES, ACCEPTED_STATUS, SUCCESS_STATUS, acceptanceSuccessReworkFamily, acceptance_success_rework_default;
25130
+ var init_acceptance_success_rework = __esm({
25131
+ "src/taishi-metric-families/acceptance-success-rework.ts"() {
25132
+ "use strict";
25133
+ init_taishi_median();
25134
+ WORKER_ROLES = /* @__PURE__ */ new Set(["coder", "fixer"]);
25135
+ ACCEPTED_STATUS = {
25136
+ coder: /* @__PURE__ */ new Set(["completed", "refused", "partially_completed", "unfinished", "planned"]),
25137
+ fixer: /* @__PURE__ */ new Set(["completed", "refused", "partially_completed", "unfinished", "planned"]),
25138
+ judge: /* @__PURE__ */ new Set(["converged", "continue", "escalate"]),
25139
+ reviewer: /* @__PURE__ */ new Set(["completed", "refused"]),
25140
+ doctor: /* @__PURE__ */ new Set(["completed", "refused"]),
25141
+ merger: /* @__PURE__ */ new Set(["completed", "escalate"])
25142
+ };
25143
+ SUCCESS_STATUS = {
25144
+ coder: /* @__PURE__ */ new Set(["completed"]),
25145
+ fixer: /* @__PURE__ */ new Set(["completed"]),
25146
+ // Judge: producing any of the three verdicts completes the duty.
25147
+ judge: /* @__PURE__ */ new Set(["converged", "continue", "escalate"]),
25148
+ reviewer: /* @__PURE__ */ new Set(["completed"]),
25149
+ doctor: /* @__PURE__ */ new Set(["completed"]),
25150
+ merger: /* @__PURE__ */ new Set(["completed"])
25151
+ };
25152
+ acceptanceSuccessReworkFamily = {
25153
+ id: "acceptance-success-rework",
25154
+ contribute(input) {
25155
+ const section = buildAcceptanceSuccessReworkSection(input.runs);
25156
+ if (section === void 0) return void 0;
25157
+ return { acceptanceSuccessRework: section };
25158
+ }
25159
+ };
25160
+ acceptance_success_rework_default = acceptanceSuccessReworkFamily;
25161
+ }
25162
+ });
25163
+
25164
+ // src/taishi-model-groups.ts
25165
+ function taishiModelGroupKey(models) {
25166
+ if (models.length === 0) return void 0;
25167
+ if (models.length === 1) return models[0];
25168
+ return `mixed:${models.join("+")}`;
25169
+ }
25170
+ function rate(numerator, denominator) {
25171
+ if (denominator === 0) return void 0;
25172
+ return numerator / denominator;
25173
+ }
25174
+ function displayNameFor(rawGroupKey, combinationMapping) {
25175
+ if (combinationMapping === void 0) return rawGroupKey;
25176
+ const aliased = combinationMapping[rawGroupKey];
25177
+ return aliased === void 0 ? rawGroupKey : aliased;
25178
+ }
25179
+ function sortUnreadable(unreadable) {
25180
+ return [...unreadable].sort((a, b) => {
25181
+ if (a.book !== b.book) return a.book.localeCompare(b.book);
25182
+ return a.runId.localeCompare(b.runId);
25183
+ });
25184
+ }
25185
+ function modelIdentityAbsentEntry(run) {
25186
+ return {
25187
+ runId: run.runId,
25188
+ book: run.book,
25189
+ missingSources: ["session-model"],
25190
+ reason: "session has no usable model identity",
25191
+ firstFrameAt: { status: "present", at: run.frameSpan.startedAt },
25192
+ // Readable legs already admitted a full span — retain end edge for lastActivityAt.
25193
+ lastFrameAt: { status: "present", at: run.frameSpan.endedAt }
25194
+ };
25195
+ }
25196
+ function buildTaishiModelGroupsPage(input) {
25197
+ const groupedRuns = [];
25198
+ const modelAbsent = [];
25199
+ for (const run of input.runs) {
25200
+ const rawGroupKey = taishiModelGroupKey(run.models);
25201
+ if (rawGroupKey === void 0) {
25202
+ modelAbsent.push(modelIdentityAbsentEntry(run));
25203
+ } else {
25204
+ groupedRuns.push({ run, rawGroupKey });
25205
+ }
25206
+ }
25207
+ const acceptance = buildAcceptanceSuccessReworkSection(
25208
+ groupedRuns.map(({ run }) => run)
25209
+ );
25210
+ const legByRunId = new Map(
25211
+ (acceptance?.legs ?? []).map((leg) => [leg.runId, leg])
25212
+ );
25213
+ const byRaw = /* @__PURE__ */ new Map();
25214
+ for (const { run, rawGroupKey } of groupedRuns) {
25215
+ const leg = legByRunId.get(run.runId);
25216
+ if (leg === void 0) {
25217
+ throw new Error(
25218
+ `taishi model-groups: missing acceptance projection for run ${run.runId}`
25219
+ );
25220
+ }
25221
+ let acc = byRaw.get(rawGroupKey);
25222
+ if (acc === void 0) {
25223
+ acc = {
25224
+ acceptedCount: 0,
25225
+ successCount: 0,
25226
+ successEligibleCount: 0,
25227
+ noReceiptCount: 0,
25228
+ walls: []
25229
+ };
25230
+ byRaw.set(rawGroupKey, acc);
25231
+ }
25232
+ if (leg.accepted) acc.acceptedCount += 1;
25233
+ if (leg.success) acc.successCount += 1;
25234
+ if (leg.successEligible) acc.successEligibleCount += 1;
25235
+ if (leg.noReceipt) acc.noReceiptCount += 1;
25236
+ acc.walls.push(leg.wallMs);
25237
+ }
25238
+ const rawKeys = [...byRaw.keys()].sort((a, b) => a.localeCompare(b));
25239
+ const groups = rawKeys.map((rawGroupKey) => {
25240
+ const acc = byRaw.get(rawGroupKey);
25241
+ const legCount = acc.walls.length;
25242
+ return {
25243
+ rawGroupKey,
25244
+ displayName: displayNameFor(rawGroupKey, input.combinationMapping),
25245
+ legCount,
25246
+ acceptedCount: acc.acceptedCount,
25247
+ acceptanceRate: rate(acc.acceptedCount, legCount),
25248
+ successCount: acc.successCount,
25249
+ successEligibleCount: acc.successEligibleCount,
25250
+ successRate: rate(acc.successCount, acc.successEligibleCount),
25251
+ noReceiptCount: acc.noReceiptCount,
25252
+ noReceiptRate: rate(acc.noReceiptCount, legCount),
25253
+ wallClockMedianMs: medianNumber(acc.walls)
25254
+ };
25255
+ });
25256
+ const unreadable = sortUnreadable([...input.unreadable, ...modelAbsent]);
25257
+ return {
25258
+ kind: "taishi-model-groups",
25259
+ mode: "model-groups",
25260
+ projectRoots: [...input.projectRoots].sort((a, b) => a.localeCompare(b)),
25261
+ groups,
25262
+ legCount: groupedRuns.length,
25263
+ unreadableCount: unreadable.length,
25264
+ unreadable
25265
+ };
25266
+ }
25267
+ var init_taishi_model_groups = __esm({
25268
+ "src/taishi-model-groups.ts"() {
25269
+ "use strict";
25270
+ init_acceptance_success_rework();
25271
+ init_taishi_median();
25272
+ }
25273
+ });
25274
+
25275
+ // src/taishi-metric-families/b2-frame-buckets-actions.ts
25276
+ function timestampMs(iso) {
25277
+ const ms = Date.parse(iso);
25278
+ if (!Number.isFinite(ms)) {
25279
+ throw new Error(`unparseable timestamp: ${iso}`);
25280
+ }
25281
+ return ms;
25282
+ }
25283
+ function toIso(ms) {
25284
+ return new Date(ms).toISOString();
25285
+ }
25286
+ function closedTools(intervals) {
25287
+ const out = [];
25288
+ for (const interval of intervals) {
25289
+ if (interval.endedAt === void 0) continue;
25290
+ const startMs = timestampMs(interval.startedAt);
25291
+ const endMs = timestampMs(interval.endedAt);
25292
+ if (endMs <= startMs) continue;
25293
+ out.push({
25294
+ toolCallId: interval.toolCallId,
25295
+ toolName: interval.toolName,
25296
+ startedAt: interval.startedAt,
25297
+ endedAt: interval.endedAt,
25298
+ startMs,
25299
+ endMs,
25300
+ ...interval.command !== void 0 ? { command: interval.command } : {}
25301
+ });
25302
+ }
25303
+ return out;
25304
+ }
25305
+ function clipToolsToFrame(tools, frameStartMs, frameEndMs) {
25306
+ if (frameEndMs <= frameStartMs) return [];
25307
+ const out = [];
25308
+ for (const tool2 of tools) {
25309
+ const startMs = Math.max(tool2.startMs, frameStartMs);
25310
+ const endMs = Math.min(tool2.endMs, frameEndMs);
25311
+ if (endMs <= startMs) continue;
25312
+ out.push({
25313
+ toolCallId: tool2.toolCallId,
25314
+ toolName: tool2.toolName,
25315
+ startMs,
25316
+ endMs,
25317
+ startedAt: startMs === tool2.startMs ? tool2.startedAt : toIso(startMs),
25318
+ endedAt: endMs === tool2.endMs ? tool2.endedAt : toIso(endMs),
25319
+ ...tool2.command !== void 0 ? { command: tool2.command } : {}
25320
+ });
25321
+ }
25322
+ return out;
25323
+ }
25324
+ function mergeUnion(intervals) {
25325
+ if (intervals.length === 0) return [];
25326
+ const sorted = [...intervals].sort(
25327
+ (a, b) => a.startMs - b.startMs || a.endMs - b.endMs
25328
+ );
25329
+ const merged = [
25330
+ { startMs: sorted[0].startMs, endMs: sorted[0].endMs }
25331
+ ];
25332
+ for (let i = 1; i < sorted.length; i += 1) {
25333
+ const cur = sorted[i];
25334
+ const last = merged[merged.length - 1];
25335
+ if (cur.startMs <= last.endMs) {
25336
+ last.endMs = Math.max(last.endMs, cur.endMs);
25337
+ } else {
25338
+ merged.push({ startMs: cur.startMs, endMs: cur.endMs });
25339
+ }
25340
+ }
25341
+ return merged;
25342
+ }
25343
+ function modelMaximalIntervals(frameStartMs, frameEndMs, toolUnion) {
25344
+ if (frameEndMs <= frameStartMs) return [];
25345
+ const gaps = [];
25346
+ let cursor = frameStartMs;
25347
+ for (const interval of toolUnion) {
25348
+ if (interval.startMs > cursor) {
25349
+ gaps.push({ startMs: cursor, endMs: interval.startMs });
25350
+ }
25351
+ cursor = Math.max(cursor, interval.endMs);
25352
+ }
25353
+ if (cursor < frameEndMs) {
25354
+ gaps.push({ startMs: cursor, endMs: frameEndMs });
25355
+ }
25356
+ return gaps;
25357
+ }
25358
+ function toolAction(tool2) {
25359
+ const action = {
25360
+ kind: "tool",
25361
+ toolCallId: tool2.toolCallId,
25362
+ toolName: tool2.toolName,
25363
+ durationMs: tool2.endMs - tool2.startMs,
25364
+ startedAt: tool2.startedAt,
25365
+ endedAt: tool2.endedAt
25366
+ };
25367
+ if (tool2.toolName === "bash" && tool2.command !== void 0) {
25368
+ return {
25369
+ ...action,
25370
+ commandSummary: tool2.command
25371
+ };
25372
+ }
25373
+ return action;
25374
+ }
25375
+ function modelAction(gap) {
25376
+ return {
25377
+ kind: "model",
25378
+ durationMs: gap.endMs - gap.startMs,
25379
+ startedAt: toIso(gap.startMs),
25380
+ endedAt: toIso(gap.endMs)
25381
+ };
25382
+ }
25383
+ function sortActionsDescending(actions) {
25384
+ return [...actions].sort((a, b) => {
25385
+ if (b.durationMs !== a.durationMs) return b.durationMs - a.durationMs;
25386
+ if (a.startedAt !== b.startedAt) return a.startedAt.localeCompare(b.startedAt);
25387
+ if (a.kind !== b.kind) return a.kind.localeCompare(b.kind);
25388
+ if (a.kind === "tool" && b.kind === "tool") {
25389
+ return a.toolCallId.localeCompare(b.toolCallId);
25390
+ }
25391
+ return 0;
25392
+ });
25393
+ }
25394
+ function computeTaishiB2RunMetrics(facts) {
25395
+ const frameStartMs = timestampMs(facts.frameSpan.startedAt);
25396
+ const frameEndMs = timestampMs(facts.frameSpan.endedAt);
25397
+ const wallMs = Math.max(0, frameEndMs - frameStartMs);
25398
+ const tools = clipToolsToFrame(closedTools(facts.toolIntervals), frameStartMs, frameEndMs);
25399
+ const toolUnion = mergeUnion(tools);
25400
+ const toolBucketMs = toolUnion.reduce(
25401
+ (sum, interval) => sum + (interval.endMs - interval.startMs),
25402
+ 0
25403
+ );
25404
+ const modelBucketMs = wallMs - toolBucketMs;
25405
+ const modelGaps = modelMaximalIntervals(frameStartMs, frameEndMs, toolUnion);
25406
+ const actions = sortActionsDescending([
25407
+ ...tools.map(toolAction),
25408
+ ...modelGaps.map(modelAction)
25409
+ ]);
25410
+ const actionDurationMedianMs = medianNumber(actions.map((action) => action.durationMs));
25411
+ return {
25412
+ runId: facts.runId,
25413
+ book: facts.book,
25414
+ role: facts.role,
25415
+ wallMs,
25416
+ toolBucketMs,
25417
+ modelBucketMs,
25418
+ actions,
25419
+ actionDurationMedianMs
25420
+ };
25421
+ }
25422
+ var b2FrameBucketsActionsFamily, b2_frame_buckets_actions_default;
25423
+ var init_b2_frame_buckets_actions = __esm({
25424
+ "src/taishi-metric-families/b2-frame-buckets-actions.ts"() {
25425
+ "use strict";
25426
+ init_taishi_median();
25427
+ b2FrameBucketsActionsFamily = {
25428
+ id: "b2-frame-buckets-actions",
25429
+ contribute(input) {
25430
+ if (input.runs.length === 0) return void 0;
25431
+ const runs = [...input.runs].map(computeTaishiB2RunMetrics).sort((a, b) => {
25432
+ if (a.book !== b.book) return a.book.localeCompare(b.book);
25433
+ if (a.role !== b.role) return a.role.localeCompare(b.role);
25434
+ return a.runId.localeCompare(b.runId);
25435
+ });
25436
+ const section = {
25437
+ kind: "taishi-b2-frame-buckets-actions",
25438
+ runs
25439
+ };
25440
+ return { b2FrameBucketsActions: section };
25441
+ }
25442
+ };
25443
+ b2_frame_buckets_actions_default = b2FrameBucketsActionsFamily;
25444
+ }
25445
+ });
25446
+
25447
+ // src/taishi-metric-families/leg-wall-clock.ts
25448
+ function frameSpanWallMs(span) {
25449
+ return Date.parse(span.endedAt) - Date.parse(span.startedAt);
25450
+ }
25451
+ function projectEntry(facts) {
25452
+ return {
25453
+ runId: facts.runId,
25454
+ book: facts.book,
25455
+ role: facts.role,
25456
+ wallMs: frameSpanWallMs(facts.frameSpan)
25457
+ };
25458
+ }
25459
+ function compareRankingDesc(a, b) {
25460
+ if (b.wallMs !== a.wallMs) return b.wallMs - a.wallMs;
25461
+ if (a.book !== b.book) return a.book.localeCompare(b.book);
25462
+ if (a.role !== b.role) return a.role.localeCompare(b.role);
25463
+ return a.runId.localeCompare(b.runId);
25464
+ }
25465
+ var legWallClockFamily, leg_wall_clock_default;
25466
+ var init_leg_wall_clock = __esm({
25467
+ "src/taishi-metric-families/leg-wall-clock.ts"() {
25468
+ "use strict";
25469
+ init_taishi_median();
25470
+ legWallClockFamily = {
25471
+ id: "leg-wall-clock",
25472
+ contribute(input) {
25473
+ if (input.runs.length === 0) {
25474
+ return void 0;
25475
+ }
25476
+ const ranking = input.runs.map(projectEntry).sort(compareRankingDesc);
25477
+ const walls = ranking.map((leg) => leg.wallMs);
25478
+ const medianWallMs = medianNumber(walls);
25479
+ if (medianWallMs === void 0) {
25480
+ return void 0;
25481
+ }
25482
+ let totalElapsedMs = 0;
25483
+ for (const wallMs of walls) totalElapsedMs += wallMs;
25484
+ const section = {
25485
+ kind: "taishi-leg-wall-clock",
25486
+ ranking,
25487
+ medianWallMs,
25488
+ totalElapsedMs
25489
+ };
25490
+ return { legWallClock: section };
25491
+ }
25492
+ };
25493
+ leg_wall_clock_default = legWallClockFamily;
25494
+ }
25495
+ });
25496
+
25497
+ // src/taishi-metric-families/round-timeline.ts
25498
+ function isRecord10(value) {
25499
+ return typeof value === "object" && value !== null && !Array.isArray(value);
25500
+ }
25501
+ function wallMsFromSpan2(startedAt, endedAt) {
25502
+ return Date.parse(endedAt) - Date.parse(startedAt);
25503
+ }
25504
+ function readOutcomeStatus(body) {
25505
+ if (!isRecord10(body.outcome)) return void 0;
25506
+ const status = body.outcome.status;
25507
+ if (typeof status !== "string" || status.trim() === "") return void 0;
25508
+ return status;
25509
+ }
25510
+ function readClassCount(body) {
25511
+ if (!isRecord10(body.outcome)) return void 0;
25512
+ if (!isRecord10(body.outcome.decisiveFacts)) return void 0;
25513
+ const classCount = body.outcome.decisiveFacts.classCount;
25514
+ if (typeof classCount !== "number" || !Number.isFinite(classCount)) {
25515
+ return void 0;
25516
+ }
25517
+ return classCount;
25518
+ }
25519
+ function projectTerminal(facts) {
25520
+ if (facts.terminal.status === "absent") {
25521
+ return { kind: "death", channel: "no-receipt" };
25522
+ }
25523
+ if (facts.terminal.file === "error.json") {
25524
+ return { kind: "death", channel: "error" };
25525
+ }
25526
+ if (facts.terminal.file === "audit-incomplete.json") {
25527
+ return { kind: "death", channel: "audit-incomplete" };
25528
+ }
25529
+ const status = readOutcomeStatus(facts.terminal.body);
25530
+ const classCount = readClassCount(facts.terminal.body);
25531
+ const receiptStatus = status ?? "unparsed";
25532
+ if (classCount === void 0) {
25533
+ return { kind: "receipt", status: receiptStatus };
25534
+ }
25535
+ return { kind: "receipt", status: receiptStatus, classCount };
25536
+ }
25537
+ function projectRunRow(facts) {
25538
+ const { startedAt, endedAt } = facts.frameSpan;
25539
+ return {
25540
+ kind: "run",
25541
+ runId: facts.runId,
25542
+ book: facts.book,
25543
+ role: facts.role,
25544
+ startedAt,
25545
+ endedAt,
25546
+ wallMs: wallMsFromSpan2(startedAt, endedAt),
25547
+ terminal: projectTerminal(facts)
25548
+ };
25549
+ }
25550
+ function projectUnreadableRow(entry) {
25551
+ return {
25552
+ kind: "unreadable",
25553
+ runId: entry.runId,
25554
+ book: entry.book,
25555
+ missingSources: entry.missingSources,
25556
+ reason: entry.reason,
25557
+ firstFrameAt: entry.firstFrameAt
25558
+ };
25559
+ }
25560
+ function rowSortStartedAt(row) {
25561
+ if (row.kind === "run") return row.startedAt;
25562
+ if (row.firstFrameAt.status === "present") return row.firstFrameAt.at;
25563
+ return void 0;
25564
+ }
25565
+ function compareRows(a, b) {
25566
+ const aStart = rowSortStartedAt(a);
25567
+ const bStart = rowSortStartedAt(b);
25568
+ if (aStart === void 0 && bStart === void 0) {
25569
+ return a.runId.localeCompare(b.runId);
25570
+ }
25571
+ if (aStart === void 0) return 1;
25572
+ if (bStart === void 0) return -1;
25573
+ if (aStart !== bStart) return aStart.localeCompare(bStart);
25574
+ return a.runId.localeCompare(b.runId);
25575
+ }
25576
+ function buildLanes(runs, unreadable) {
25577
+ const byLane = /* @__PURE__ */ new Map();
25578
+ const push = (lane, row) => {
25579
+ const list = byLane.get(lane);
25580
+ if (list === void 0) byLane.set(lane, [row]);
25581
+ else list.push(row);
25582
+ };
25583
+ for (const facts of runs) {
25584
+ push(facts.book, projectRunRow(facts));
25585
+ }
25586
+ for (const entry of unreadable) {
25587
+ push(entry.book, projectUnreadableRow(entry));
25588
+ }
25589
+ return [...byLane.keys()].sort((a, b) => a.localeCompare(b)).map((lane) => ({
25590
+ lane,
25591
+ rows: [...byLane.get(lane) ?? []].sort(compareRows)
25592
+ }));
25593
+ }
25594
+ var roundTimelineFamily, round_timeline_default;
25595
+ var init_round_timeline = __esm({
25596
+ "src/taishi-metric-families/round-timeline.ts"() {
25597
+ "use strict";
25598
+ roundTimelineFamily = {
25599
+ id: "round-timeline",
25600
+ contribute(input) {
25601
+ if (input.runs.length === 0 && input.unreadable.length === 0) {
25602
+ return void 0;
25603
+ }
25604
+ const section = {
25605
+ kind: "taishi-round-timeline",
25606
+ lanes: buildLanes(input.runs, input.unreadable)
25607
+ };
25608
+ return { roundTimeline: section };
25609
+ }
25610
+ };
25611
+ round_timeline_default = roundTimelineFamily;
25612
+ }
25613
+ });
25614
+
25615
+ // src/taishi-metric-families.ts
25616
+ async function loadTaishiIssueMetricFamilies() {
25617
+ return ISSUE_METRIC_FAMILIES;
25618
+ }
25619
+ var ISSUE_METRIC_FAMILIES;
25620
+ var init_taishi_metric_families = __esm({
25621
+ "src/taishi-metric-families.ts"() {
25622
+ "use strict";
25623
+ init_acceptance_success_rework();
25624
+ init_b2_frame_buckets_actions();
25625
+ init_leg_wall_clock();
25626
+ init_round_timeline();
25627
+ ISSUE_METRIC_FAMILIES = [
25628
+ acceptance_success_rework_default,
25629
+ b2_frame_buckets_actions_default,
25630
+ leg_wall_clock_default,
25631
+ round_timeline_default
25632
+ ].sort((a, b) => a.id.localeCompare(b.id));
25633
+ }
25634
+ });
25635
+
25636
+ // src/taishi-metric-family.ts
25637
+ function composeTaishiMetricFamilySections(families, input) {
25638
+ const sections = {};
25639
+ for (const family of families) {
25640
+ const piece = family.contribute(input);
25641
+ if (piece === void 0) continue;
25642
+ Object.assign(sections, piece);
25643
+ }
25644
+ return sections;
25645
+ }
25646
+ var init_taishi_metric_family = __esm({
25647
+ "src/taishi-metric-family.ts"() {
25648
+ "use strict";
25649
+ }
25650
+ });
25651
+
25652
+ // src/taishi-page.ts
25653
+ import { createHash as createHash4 } from "node:crypto";
25654
+ import { dirname as dirname10, join as join22 } from "node:path";
25655
+ function taishiIssuePageKey(projectRoot) {
25656
+ const identity = physicalPathIdentity(projectRoot);
25657
+ return createHash4("sha256").update(identity).digest("hex").slice(0, 32);
25658
+ }
25659
+ function taishiIssuePagePath(ledgerHome, projectRoot) {
25660
+ return join22(ledgerHome, "taishi", "issues", `${taishiIssuePageKey(projectRoot)}.json`);
25661
+ }
25662
+ function sortLegs(legs) {
25663
+ return [...legs].sort((a, b) => {
25664
+ if (a.book !== b.book) return a.book.localeCompare(b.book);
25665
+ if (a.role !== b.role) return a.role.localeCompare(b.role);
25666
+ return a.runId.localeCompare(b.runId);
25667
+ });
25668
+ }
25669
+ function sortUnreadable2(unreadable) {
25670
+ return [...unreadable].sort((a, b) => {
25671
+ if (a.book !== b.book) return a.book.localeCompare(b.book);
25672
+ return a.runId.localeCompare(b.runId);
25673
+ });
25674
+ }
25675
+ function sortScopeConflicts(conflicts) {
25676
+ return [...conflicts].sort((a, b) => {
25677
+ const aRun = a.runId ?? "";
25678
+ const bRun = b.runId ?? "";
25679
+ if (aRun !== bRun) return aRun.localeCompare(bRun);
25680
+ return a.projectRoot.localeCompare(b.projectRoot);
25681
+ });
25682
+ }
25683
+ function assertTaishiChangedLinesInput(changedLines) {
25684
+ if (changedLines === void 0) return;
25685
+ if (typeof changedLines !== "number" || !Number.isFinite(changedLines) || changedLines < 0) {
25686
+ throw new Error(
25687
+ `taishi changedLines must be a finite non-negative number, got ${String(changedLines)}`
25688
+ );
25689
+ }
25690
+ }
25691
+ function normalizeTaishiChangedLines(changedLines) {
25692
+ assertTaishiChangedLinesInput(changedLines);
25693
+ if (changedLines === void 0 || changedLines === 0) {
25694
+ return { status: "absent" };
25695
+ }
25696
+ return { status: "present", value: changedLines };
25697
+ }
25698
+ function computeTaishiMsPerKLines(totalElapsedMs, changedLines) {
25699
+ if (changedLines.status === "absent") return { status: "absent" };
25700
+ return {
25701
+ status: "present",
25702
+ value: totalElapsedMs / (changedLines.value / 1e3)
25703
+ };
25704
+ }
25705
+ function frameSpanWallMs2(span) {
25706
+ return Date.parse(span.endedAt) - Date.parse(span.startedAt);
25707
+ }
25708
+ function summarizeTaishiRunEfficiency(runs, unreadable = []) {
25709
+ let totalElapsedMs = 0;
25710
+ let latestEndedAt;
25711
+ for (const run of runs) {
25712
+ totalElapsedMs += frameSpanWallMs2(run.frameSpan);
25713
+ const endedAt = run.frameSpan.endedAt;
25714
+ if (latestEndedAt === void 0 || endedAt > latestEndedAt) {
25715
+ latestEndedAt = endedAt;
25716
+ }
25717
+ }
25718
+ for (const entry of unreadable) {
25719
+ if (entry.lastFrameAt.status !== "present") continue;
25720
+ const endedAt = entry.lastFrameAt.at;
25721
+ if (latestEndedAt === void 0 || endedAt > latestEndedAt) {
25722
+ latestEndedAt = endedAt;
25723
+ }
25724
+ }
25725
+ const lastActivityAt = latestEndedAt === void 0 ? { status: "absent" } : { status: "present", at: latestEndedAt };
25726
+ return { totalElapsedMs, lastActivityAt };
25727
+ }
25728
+ async function buildTaishiIssueMetricsPage(input) {
25729
+ const families = await loadTaishiIssueMetricFamilies();
25730
+ const legs = sortLegs(
25731
+ input.runs.map((run) => ({
25732
+ runId: run.runId,
25733
+ book: run.book,
25734
+ role: run.role
25735
+ }))
25736
+ );
25737
+ const unreadable = sortUnreadable2(input.unreadable);
25738
+ const scopeConflicts = sortScopeConflicts(input.scopeConflicts ?? []);
25739
+ const projectRoot = physicalPathIdentity(input.projectRoot);
25740
+ const { totalElapsedMs, lastActivityAt } = summarizeTaishiRunEfficiency(
25741
+ input.runs,
25742
+ unreadable
25743
+ );
25744
+ const changedLines = normalizeTaishiChangedLines(input.changedLines);
25745
+ const msPerKLines = computeTaishiMsPerKLines(totalElapsedMs, changedLines);
25746
+ const envelope = {
25747
+ kind: "taishi-issue-metrics",
25748
+ mode: "issue",
25749
+ projectRoot,
25750
+ // exactOptionalPropertyTypes: only materialize when caller supplied it.
25751
+ ...input.issueNumber === void 0 ? {} : { issueNumber: input.issueNumber },
25752
+ legs,
25753
+ unreadable,
25754
+ unreadableCount: unreadable.length,
25755
+ scopeConflicts,
25756
+ totalElapsedMs,
25757
+ changedLines,
25758
+ msPerKLines,
25759
+ lastActivityAt
25760
+ };
25761
+ const sections = composeTaishiMetricFamilySections(families, {
25762
+ projectRoot,
25763
+ runs: input.runs,
25764
+ unreadable
25765
+ });
25766
+ return { ...envelope, ...sections };
25767
+ }
25768
+ async function writeTaishiIssueMetricsPage(ledgerHome, page) {
25769
+ const path = taishiIssuePagePath(ledgerHome, page.projectRoot);
25770
+ ensureRealDirectoryTree(ledgerHome, dirname10(path));
25771
+ assertLedgerFileInsideHome(path, ledgerHome);
25772
+ await writeFileAtomically(path, `${JSON.stringify(page, null, 2)}
25773
+ `);
25774
+ return path;
25775
+ }
25776
+ var init_taishi_page = __esm({
25777
+ "src/taishi-page.ts"() {
25778
+ "use strict";
25779
+ init_atomic_write();
25780
+ init_activation_ledger_topology();
25781
+ init_taishi_metric_families();
25782
+ init_taishi_metric_family();
25783
+ }
25784
+ });
25785
+
25786
+ // src/taishi-entry.ts
25787
+ import { readFile as readFile14 } from "node:fs/promises";
25788
+ function isMissingPathError5(error) {
25789
+ return error instanceof Error && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR");
25790
+ }
25791
+ function cachedPageMatchesRequestedScope(page, input) {
25792
+ const requestedTicket = input.ticketNumber ?? input.issueNumber;
25793
+ if (requestedTicket === void 0) {
25794
+ return page.issueNumber === void 0;
25795
+ }
25796
+ return page.issueNumber === requestedTicket;
25797
+ }
25798
+ async function readOrComputeTaishiIssuePage(input) {
25799
+ const ledgerHome = resolveActivationLedgerHome();
25800
+ const projectRoot = physicalPathIdentity(input.projectRoot);
25801
+ const pagePath = taishiIssuePagePath(ledgerHome, projectRoot);
25802
+ try {
25803
+ const raw = await readFile14(pagePath, "utf8");
25804
+ const page = JSON.parse(raw);
25805
+ if (cachedPageMatchesRequestedScope(page, input)) {
25806
+ return { mode: "issue", page, pagePath };
25807
+ }
25808
+ } catch (error) {
25809
+ if (!isMissingPathError5(error)) {
25810
+ throw new TaishiIssueComputeError({
25811
+ projectRoot,
25812
+ ...input.issueNumber === void 0 ? {} : { issueNumber: input.issueNumber },
25813
+ cause: error
25814
+ });
25815
+ }
25816
+ }
25817
+ try {
25818
+ return await runTaishiIssueMode(input);
25819
+ } catch (error) {
25820
+ if (error instanceof TaishiIssueComputeError) throw error;
25821
+ throw new TaishiIssueComputeError({
25822
+ projectRoot,
25823
+ ...input.issueNumber === void 0 ? {} : { issueNumber: input.issueNumber },
25824
+ cause: error
25825
+ });
25826
+ }
25827
+ }
25828
+ async function runTaishiIssueMode(input, precomputedScan) {
25829
+ assertTaishiChangedLinesInput(input.changedLines);
25830
+ const ledgerHome = resolveActivationLedgerHome();
25831
+ const projectRoot = input.projectRoot;
25832
+ const ticketNumber = "ticketNumber" in input ? input.ticketNumber : void 0;
25833
+ const scan = precomputedScan ?? (ticketNumber === void 0 ? await scanTaishiIssueRuns({ projectRoot }) : await scanTaishiIssueRuns({ projectRoot, ticketNumber }));
25834
+ const issueNumber = "issueNumber" in input ? input.issueNumber : void 0;
25835
+ const conflictingProjectRoot = "conflictingProjectRoot" in input ? input.conflictingProjectRoot : void 0;
25836
+ const scopeConflicts = [...scan.scopeConflicts];
25837
+ if (conflictingProjectRoot !== void 0 && ticketNumber !== void 0) {
25838
+ const losingRoot = physicalPathIdentity(conflictingProjectRoot);
25839
+ const winningRoot = physicalPathIdentity(projectRoot);
25840
+ if (losingRoot !== winningRoot) {
25841
+ scopeConflicts.push({
25842
+ ticketNumber,
25843
+ projectRoot: losingRoot,
25844
+ fact: "typed-ticketNumber-over-projectRoot"
25845
+ });
25846
+ }
25847
+ }
25848
+ const page = await buildTaishiIssueMetricsPage({
25849
+ projectRoot,
25850
+ runs: scan.runs,
25851
+ unreadable: scan.unreadable,
25852
+ scopeConflicts,
25853
+ ...input.changedLines === void 0 ? {} : { changedLines: input.changedLines },
25854
+ ...issueNumber === void 0 ? {} : { issueNumber }
25855
+ });
25856
+ const pagePath = await writeTaishiIssueMetricsPage(ledgerHome, page);
25857
+ if (issueNumber !== void 0) {
25858
+ await mergeTaishiLibraryIndexRows(ledgerHome, [
25859
+ rowFromIssueMetricsPage(page)
25860
+ ]);
25861
+ }
25862
+ return { mode: "issue", page, pagePath };
25863
+ }
25864
+ async function runTaishiSweepMode(input) {
25865
+ const ledgerHome = resolveActivationLedgerHome();
25866
+ const issuePages = [];
25867
+ for (const entry of input.mergedPullRequests) {
25868
+ issuePages.push(await runTaishiIssueMode(entry));
25869
+ }
25870
+ const upserts = issuePages.map((result2) => rowFromIssueMetricsPage(result2.page));
25871
+ const { index, indexPath } = await mergeTaishiLibraryIndexRows(ledgerHome, upserts);
25872
+ return { mode: "sweep", issuePages, index, indexPath };
25873
+ }
25874
+ async function runTaishiModelGroupsMode(input) {
25875
+ const ledgerHome = resolveActivationLedgerHome();
25876
+ const runs = [];
25877
+ const unreadable = [];
25878
+ const seen = /* @__PURE__ */ new Set();
25879
+ const projectRoots = [];
25880
+ for (const root of input.projectRoots) {
25881
+ const identity = physicalPathIdentity(root);
25882
+ if (seen.has(identity)) continue;
25883
+ seen.add(identity);
25884
+ projectRoots.push(identity);
25885
+ }
25886
+ for (const projectRoot of projectRoots) {
25887
+ const scan = await scanTaishiIssueRuns({ projectRoot });
25888
+ runs.push(...scan.runs);
25889
+ unreadable.push(...scan.unreadable);
25890
+ const pagePath = taishiIssuePagePath(ledgerHome, projectRoot);
25891
+ try {
25892
+ const raw = await readFile14(pagePath, "utf8");
25893
+ JSON.parse(raw);
25894
+ } catch (error) {
25895
+ if (!isMissingPathError5(error)) {
25896
+ throw new TaishiIssueComputeError({ projectRoot, cause: error });
25897
+ }
25898
+ try {
25899
+ await runTaishiIssueMode({ mode: "issue", projectRoot }, scan);
25900
+ } catch (computeError) {
25901
+ if (computeError instanceof TaishiIssueComputeError) throw computeError;
25902
+ throw new TaishiIssueComputeError({ projectRoot, cause: computeError });
25903
+ }
25904
+ }
25905
+ }
25906
+ const page = input.combinationMapping === void 0 ? buildTaishiModelGroupsPage({ projectRoots, runs, unreadable }) : buildTaishiModelGroupsPage({
25907
+ projectRoots,
25908
+ runs,
25909
+ unreadable,
25910
+ combinationMapping: input.combinationMapping
25911
+ });
25912
+ return { mode: "model-groups", page };
25913
+ }
25914
+ async function runTaishi(input) {
25915
+ if (input.mode === "sweep") {
25916
+ return runTaishiSweepMode(input);
25917
+ }
25918
+ if (input.mode === "cohort") {
25919
+ const ledgerHome = resolveActivationLedgerHome();
25920
+ return runTaishiCohortMode(ledgerHome, input, async ({ projectRoot, issueNumber }) => {
25921
+ const ensured = await readOrComputeTaishiIssuePage({
25922
+ mode: "issue",
25923
+ projectRoot,
25924
+ issueNumber
25925
+ });
25926
+ return ensured.page;
25927
+ });
25928
+ }
25929
+ if (input.mode === "model-groups") {
25930
+ return runTaishiModelGroupsMode(input);
25931
+ }
25932
+ return runTaishiIssueMode(input);
25933
+ }
25934
+ var TaishiIssueComputeError, taishiSweepModeInputSchema;
25935
+ var init_taishi_entry = __esm({
25936
+ "src/taishi-entry.ts"() {
25937
+ "use strict";
25938
+ init_build();
25939
+ init_activation_ledger_topology();
25940
+ init_taishi_cohort();
25941
+ init_taishi_ledger();
25942
+ init_taishi_index();
25943
+ init_taishi_model_groups();
25944
+ init_taishi_page();
25945
+ TaishiIssueComputeError = class extends Error {
25946
+ code = "taishi-issue-compute-failed";
25947
+ projectRoot;
25948
+ issueNumber;
25949
+ constructor(input) {
25950
+ const root = physicalPathIdentity(input.projectRoot);
25951
+ const causeText = input.cause instanceof Error ? input.cause.message || input.cause.name : String(input.cause);
25952
+ const issueFace = input.issueNumber === void 0 ? `projectRoot ${root}` : `issue ${input.issueNumber} (projectRoot ${root})`;
25953
+ super(`taishi compute failed for ${issueFace}: ${causeText}`, {
25954
+ cause: input.cause
25955
+ });
25956
+ this.name = "TaishiIssueComputeError";
25957
+ this.projectRoot = root;
25958
+ if (input.issueNumber !== void 0) {
25959
+ this.issueNumber = input.issueNumber;
25960
+ }
25961
+ }
25962
+ };
25963
+ taishiSweepModeInputSchema = typebox_exports.Object(
25964
+ {
25965
+ mode: typebox_exports.Literal("sweep"),
25966
+ mergedPullRequests: typebox_exports.Array(
25967
+ typebox_exports.Object(
25968
+ {
25969
+ projectRoot: typebox_exports.String(),
25970
+ /** 排除后改动行数 — omit or 0 → typed 空缺; finite ≥ 0 only. */
25971
+ changedLines: typebox_exports.Optional(
25972
+ typebox_exports.Number({ minimum: 0, maximum: Number.MAX_VALUE })
25973
+ )
25974
+ },
25975
+ { additionalProperties: false }
25976
+ )
25977
+ )
25978
+ },
25979
+ { additionalProperties: false }
25980
+ );
25981
+ }
25982
+ });
25983
+
25984
+ // src/public-cli/taishi-run.ts
25985
+ import { readFile as readFile15 } from "node:fs/promises";
25986
+ import { isAbsolute as isAbsolute5, resolve as resolve8 } from "node:path";
25987
+ async function buildTaishiIssueModeInputFromPublicArgv(parsed, ledgerHome) {
25988
+ const ticket = parsed.ticket;
25989
+ const directRoot = parsed.projectRoot;
25990
+ if (ticket === void 0) {
25991
+ return {
25992
+ mode: "issue",
25993
+ projectRoot: directRoot
25994
+ };
25995
+ }
25996
+ const index = await readTaishiLibraryIndexPage(ledgerHome);
25997
+ const row = findTaishiLibraryIndexRow(index, ticket);
25998
+ let projectRoot;
25999
+ if (row !== void 0) {
26000
+ projectRoot = row.projectRoot;
26001
+ } else if (directRoot !== void 0) {
26002
+ projectRoot = directRoot;
26003
+ } else {
26004
+ throw new CliUsageError(
26005
+ `taishi library index has no row for ticket ${ticket}`
26006
+ );
26007
+ }
26008
+ const dualParamConflict = row !== void 0 && directRoot !== void 0 && physicalPathIdentity(directRoot) !== physicalPathIdentity(projectRoot);
26009
+ return {
26010
+ mode: "issue",
26011
+ projectRoot,
26012
+ ticketNumber: ticket,
26013
+ issueNumber: ticket,
26014
+ ...dualParamConflict ? { conflictingProjectRoot: directRoot } : {}
26015
+ };
26016
+ }
26017
+ function parseTaishiSweepModeInputFromJsonValue(value) {
26018
+ if (!value_exports.Check(taishiSweepModeInputSchema, value)) {
26019
+ throw new CliUsageError(
26020
+ "taishi sweep attachment must match TaishiSweepModeInput"
26021
+ );
26022
+ }
26023
+ return value;
26024
+ }
26025
+ async function buildTaishiSweepModeInputFromAttachmentPaths(attachmentPaths) {
26026
+ if (attachmentPaths.length !== 1) {
26027
+ throw new CliUsageError(
26028
+ "taishi sweep requires exactly one --attach typed JSON attachment"
26029
+ );
26030
+ }
26031
+ const sourcePath = attachmentPaths[0];
26032
+ const absolute = isAbsolute5(sourcePath) ? sourcePath : resolve8(sourcePath);
26033
+ let bytes;
26034
+ try {
26035
+ bytes = await readFile15(absolute);
26036
+ } catch (error) {
26037
+ throw new CliUsageError(
26038
+ `taishi sweep attachment is not a readable regular file: ${sourcePath}`,
26039
+ { cause: error }
26040
+ );
26041
+ }
26042
+ let text;
26043
+ try {
26044
+ text = exactUtf8(bytes, "taishi sweep attachment");
26045
+ } catch (error) {
26046
+ const detail = error instanceof Error ? error.message : String(error);
26047
+ throw new CliUsageError(detail, { cause: error });
26048
+ }
26049
+ let parsed;
26050
+ try {
26051
+ parsed = JSON.parse(text);
26052
+ } catch (error) {
26053
+ throw new CliUsageError(
26054
+ "taishi sweep attachment is not valid JSON",
26055
+ { cause: error }
26056
+ );
26057
+ }
26058
+ return parseTaishiSweepModeInputFromJsonValue(parsed);
26059
+ }
26060
+ async function runPublicTaishi(argv, _env, io, parseTaishiArgv2) {
26061
+ try {
26062
+ const parsed = parseTaishiArgv2(argv);
26063
+ const ledgerHome = resolveActivationLedgerHome();
26064
+ if (parsed.query === "sweep") {
26065
+ const input2 = await buildTaishiSweepModeInputFromAttachmentPaths(
26066
+ parsed.attachmentPaths
26067
+ );
26068
+ const result3 = await runTaishi(input2);
26069
+ io.stdout(`${JSON.stringify(result3, null, 2)}
26070
+ `);
26071
+ return { exitCode: 0 };
26072
+ }
26073
+ if (parsed.query === "cohort") {
26074
+ const result3 = await runTaishi({
26075
+ mode: "cohort",
26076
+ groups: parsed.groups
26077
+ });
26078
+ io.stdout(`${JSON.stringify(result3, null, 2)}
26079
+ `);
26080
+ return { exitCode: 0 };
26081
+ }
26082
+ if (parsed.query === "model-groups") {
26083
+ const result3 = await runTaishi({
26084
+ mode: "model-groups",
26085
+ projectRoots: parsed.projectRoots
26086
+ });
26087
+ io.stdout(`${JSON.stringify(result3, null, 2)}
26088
+ `);
26089
+ return { exitCode: 0 };
26090
+ }
26091
+ const input = await buildTaishiIssueModeInputFromPublicArgv(parsed, ledgerHome);
26092
+ const result2 = await readOrComputeTaishiIssuePage(input);
26093
+ io.stdout(`${JSON.stringify(result2, null, 2)}
26094
+ `);
26095
+ return { exitCode: 0 };
26096
+ } catch (error) {
26097
+ if (error instanceof CliUsageError) {
26098
+ presentStructuralRejection(error, io);
26099
+ return { exitCode: 2 };
26100
+ }
26101
+ if (error instanceof TaishiIssueComputeError) {
26102
+ const code = errnoCode(error.cause);
26103
+ presentControlledFailure({
26104
+ cause: "output",
26105
+ diagnostic: error.message,
26106
+ ...code === void 0 ? {} : { identity: { code } },
26107
+ details: {
26108
+ code: error.code,
26109
+ projectRoot: error.projectRoot,
26110
+ ...error.issueNumber === void 0 ? {} : { issueNumber: error.issueNumber }
26111
+ }
26112
+ }, io);
26113
+ return { exitCode: 1 };
26114
+ }
26115
+ throw error;
26116
+ }
26117
+ }
26118
+ var init_taishi_run = __esm({
26119
+ "src/public-cli/taishi-run.ts"() {
26120
+ "use strict";
26121
+ init_value2();
26122
+ init_activation_ledger_topology();
26123
+ init_exact_utf8();
26124
+ init_taishi_index();
26125
+ init_taishi_entry();
26126
+ init_cli_errors();
26127
+ init_settlement();
26128
+ }
26129
+ });
26130
+
26131
+ // src/public-cli/cli.ts
26132
+ var cli_exports = {};
26133
+ __export(cli_exports, {
26134
+ CliUsageError: () => CliUsageError,
26135
+ PUBLIC_ROLE_ARGV: () => PUBLIC_ROLE_ARGV,
26136
+ buildExplicitInternalActivationArgs: () => buildExplicitInternalActivationArgs,
26137
+ helpDocument: () => helpDocument,
26138
+ resolveInternalRoleEntrypoint: () => resolveInternalRoleEntrypoint,
26139
+ runAkRole: () => runAkRole
26140
+ });
26141
+ import { realpath as realpath5 } from "node:fs/promises";
26142
+ import { homedir as homedir3 } from "node:os";
26143
+ import { join as join23 } from "node:path";
26144
+ function takePublicGlobalFlag(argv, index) {
26145
+ const token = argv[index];
26146
+ if (token === void 0) return void 0;
23728
26147
  if (token === "--help" || token === "-h") {
23729
26148
  return { flag: "help", consume: 1 };
23730
26149
  }
@@ -23772,7 +26191,7 @@ function resolveHome(env) {
23772
26191
  return env.home ?? process.env.HOME ?? homedir3();
23773
26192
  }
23774
26193
  function resolveAgentDir(env, home) {
23775
- return env.agentDir ?? process.env.PI_CODING_AGENT_DIR ?? join18(home, ".pi", "agent");
26194
+ return env.agentDir ?? process.env.PI_CODING_AGENT_DIR ?? join23(home, ".pi", "agent");
23776
26195
  }
23777
26196
  function parseThinking(value) {
23778
26197
  if (!THINKING_LEVELS2.has(value)) {
@@ -23858,6 +26277,12 @@ function renderHelp() {
23858
26277
  lines.push(` ${cap.name} \u2014 ${phaseText}`);
23859
26278
  }
23860
26279
  }
26280
+ lines.push("", "Deterministic commands:");
26281
+ for (const cap of doc.capabilities) {
26282
+ if (cap.kind === "deterministic") {
26283
+ lines.push(` ${cap.name}`);
26284
+ }
26285
+ }
23861
26286
  lines.push(
23862
26287
  "",
23863
26288
  "Global options: --model provider/model --thinking level",
@@ -23955,6 +26380,9 @@ async function runAkRole(argv, env) {
23955
26380
  }
23956
26381
  if (match.kind === "support") {
23957
26382
  io.stdout(`command ${match.name} kind support
26383
+ `);
26384
+ } else if (match.kind === "deterministic") {
26385
+ io.stdout(`command ${match.name} kind deterministic
23958
26386
  `);
23959
26387
  } else {
23960
26388
  io.stdout(
@@ -24358,6 +26786,15 @@ async function runAkRole(argv, env) {
24358
26786
  ...result2.terminal === void 0 ? {} : { terminal: result2.terminal }
24359
26787
  };
24360
26788
  }
26789
+ if (parsed.command === "taishi") {
26790
+ const result2 = await runPublicTaishi(
26791
+ parsed.args,
26792
+ { home },
26793
+ io,
26794
+ PUBLIC_ROLE_ARGV.taishi.parse
26795
+ );
26796
+ return { exitCode: result2.exitCode };
26797
+ }
24361
26798
  throw new CliUsageError(`unknown command: ${parsed.command}`);
24362
26799
  } catch (error) {
24363
26800
  if (error instanceof CliUsageError) {
@@ -24388,6 +26825,7 @@ var init_cli = __esm({
24388
26825
  init_judge_run();
24389
26826
  init_merger_run();
24390
26827
  init_reviewer_run();
26828
+ init_taishi_run();
24391
26829
  init_run_lifecycle();
24392
26830
  init_registry2();
24393
26831
  init_settlement();
@@ -24400,7 +26838,9 @@ var init_cli = __esm({
24400
26838
  collector: { parse: parseCollectorArgv },
24401
26839
  doctor: { parse: parseDoctorArgv },
24402
26840
  merger: { parse: parseMergerArgv },
24403
- reviewer: { parse: parseReviewerArgv }
26841
+ reviewer: { parse: parseReviewerArgv },
26842
+ /** Deterministic analysis seat (#336) — argv parse only; no LLM admission. */
26843
+ taishi: { parse: parseTaishiArgv }
24404
26844
  };
24405
26845
  THINKING_LEVELS2 = /* @__PURE__ */ new Set([
24406
26846
  "off",
@@ -24415,7 +26855,8 @@ var init_cli = __esm({
24415
26855
  });
24416
26856
 
24417
26857
  // src/public-cli/main.ts
24418
- import { dirname as dirname7, join as join19 } from "node:path";
26858
+ import { existsSync as existsSync2 } from "node:fs";
26859
+ import { dirname as dirname11, join as join24 } from "node:path";
24419
26860
  import { fileURLToPath as fileURLToPath2 } from "node:url";
24420
26861
 
24421
26862
  // src/public-cli/host-pi-runtime.ts
@@ -24502,8 +26943,15 @@ function linkPackage(packageRoot2, name, targetDir) {
24502
26943
  }
24503
26944
 
24504
26945
  // src/public-cli/main.ts
24505
- var here = dirname7(fileURLToPath2(import.meta.url));
24506
- var packageRoot = join19(here, "..", "..");
26946
+ var here = dirname11(fileURLToPath2(import.meta.url));
26947
+ function resolvePackageRoot(binDir) {
26948
+ const canonical = join24(binDir, "..", "..");
26949
+ if (existsSync2(join24(canonical, "package.json"))) {
26950
+ return canonical;
26951
+ }
26952
+ return binDir;
26953
+ }
26954
+ var packageRoot = resolvePackageRoot(here);
24507
26955
  ensureHostPiRuntimeResolvable(packageRoot);
24508
26956
  var { runAkRole: runAkRole2 } = await Promise.resolve().then(() => (init_cli(), cli_exports));
24509
26957
  var result = await runAkRole2(process.argv.slice(2), { packageRoot });