oasis_test 0.1.56 → 0.1.57

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 (2) hide show
  1. package/dist/index.js +747 -299
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -911,8 +911,8 @@ function deriveArtifactId(type, workspace, title, usedIds) {
911
911
  usedIds.add(id);
912
912
  return id;
913
913
  }
914
- function resolveNodeRef(ref, candidates) {
915
- const r = ref.trim();
914
+ function resolveNodeRef(ref2, candidates) {
915
+ const r = ref2.trim();
916
916
  if (r.startsWith("artifact:")) {
917
917
  const hit = candidates.find((n) => n.id === r);
918
918
  return hit ? { ok: true, id: hit.id } : { ok: false, reason: "not_found" };
@@ -1068,16 +1068,16 @@ var init_content_type_handler = __esm({
1068
1068
  const short = (s2) => s2.slice(0, 12);
1069
1069
  const versionLine = (() => {
1070
1070
  if (!(ctx.hasHead && ctx.headExternalRef)) return [];
1071
- const ref = ctx.headExternalRef;
1072
- if (ref.trim().startsWith("{")) {
1071
+ const ref2 = ctx.headExternalRef;
1072
+ if (ref2.trim().startsWith("{")) {
1073
1073
  try {
1074
- const m2 = JSON.parse(ref);
1074
+ const m2 = JSON.parse(ref2);
1075
1075
  const parts = Object.entries(m2).map(([id, sha2]) => `\`${id}\` @ \`${short(sha2)}\``);
1076
1076
  return [`> **\u5F53\u524D\u7248\u672C**\uFF08\u4F60\u4E0A\u4E00\u7248\uFF0C\u5DF2\u5E76\u5165\u5404\u4ED3\u4E3B\u5E72\uFF09\uFF1A${parts.join("\uFF0C")}\u2014\u2014clone \u4E3B\u5E72\u5373\u5728\u5B83\u4E4B\u4E0A\u6539\uFF0C\u522B\u4ECE\u5934\u5199\u3002`];
1077
1077
  } catch {
1078
1078
  }
1079
1079
  }
1080
- return [`> **\u5F53\u524D\u7248\u672C**\uFF08\u4F60\u4E0A\u4E00\u7248\uFF0C\u5DF2\u5E76\u5165\u4E3B\u5E72\uFF09\uFF1A\`${repos[0]?.id ?? "<\u4E3B\u4ED3>"}\` @ \`${short(ref)}\`\u2014\u2014clone \u4E3B\u5E72\u5373\u5728\u5B83\u4E4B\u4E0A\u6539\uFF0C\u522B\u4ECE\u5934\u5199\u3002`];
1080
+ return [`> **\u5F53\u524D\u7248\u672C**\uFF08\u4F60\u4E0A\u4E00\u7248\uFF0C\u5DF2\u5E76\u5165\u4E3B\u5E72\uFF09\uFF1A\`${repos[0]?.id ?? "<\u4E3B\u4ED3>"}\` @ \`${short(ref2)}\`\u2014\u2014clone \u4E3B\u5E72\u5373\u5728\u5B83\u4E4B\u4E0A\u6539\uFF0C\u522B\u4ECE\u5934\u5199\u3002`];
1081
1081
  })();
1082
1082
  return [
1083
1083
  `\u4F60\u4EA7\u51FA\u7684\u662F\u9879\u76EE **${ctx.projectName ?? "?"}** \u7684\u4EE3\u7801\u2014\u2014**\u5185\u5BB9\u76F4\u63A5\u6D3B\u5728 git \u4ED3\u5E93\u91CC**\uFF0C\u4F60\u50CF\u5F00\u53D1\u8005\u4E00\u6837\u5728 git \u91CC\u5E72\uFF0C\u4EA7\u7269\u4E0D\u8FDB Oasis \u6863\u6848\u67DC\u3002`,
@@ -1405,6 +1405,68 @@ var init_collab_view = __esm({
1405
1405
  }
1406
1406
  });
1407
1407
 
1408
+ // ../contract/src/workorder-quality.ts
1409
+ function record(value) {
1410
+ return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
1411
+ }
1412
+ function requiredString(value, field) {
1413
+ if (typeof value !== "string" || !value.trim()) {
1414
+ throw new Error(`invalid qa_quality_metrics payload: ${field} must be a non-empty string`);
1415
+ }
1416
+ return value.trim();
1417
+ }
1418
+ function count(value, field) {
1419
+ if (!Number.isInteger(value) || value < 0) {
1420
+ throw new Error(`invalid qa_quality_metrics payload: ${field} must be a non-negative integer`);
1421
+ }
1422
+ return value;
1423
+ }
1424
+ function counts(value, field) {
1425
+ const input = record(value);
1426
+ if (!input) throw new Error(`invalid qa_quality_metrics payload: ${field} must be an object`);
1427
+ const passed = count(input["passed"], `${field}.passed`);
1428
+ const total = count(input["total"], `${field}.total`);
1429
+ if (passed > total) throw new Error(`invalid qa_quality_metrics payload: ${field}.passed cannot exceed total`);
1430
+ return { passed, total };
1431
+ }
1432
+ function testCounts(value, field) {
1433
+ const input = record(value);
1434
+ if (!input) throw new Error(`invalid qa_quality_metrics payload: ${field} must be an object`);
1435
+ const base = counts(input, field);
1436
+ const failed = count(input["failed"] ?? 0, `${field}.failed`);
1437
+ const blocked = count(input["blocked"] ?? 0, `${field}.blocked`);
1438
+ if (base.passed + failed + blocked > base.total) {
1439
+ throw new Error(`invalid qa_quality_metrics payload: ${field} passed + failed + blocked cannot exceed total`);
1440
+ }
1441
+ return { ...base, failed, blocked };
1442
+ }
1443
+ function parseWorkorderQualityMetricsPayload(value) {
1444
+ const input = record(value);
1445
+ if (!input || input["kind"] !== "qa_quality_metrics") return null;
1446
+ const schemaVersion = input["schema_version"] ?? input["schemaVersion"];
1447
+ if (schemaVersion !== 1) {
1448
+ throw new Error("invalid qa_quality_metrics payload: schema_version must be 1");
1449
+ }
1450
+ const checklistRefRaw = input["checklist_ref"] ?? input["checklistRef"];
1451
+ if (checklistRefRaw !== void 0 && (typeof checklistRefRaw !== "string" || !checklistRefRaw.trim())) {
1452
+ throw new Error("invalid qa_quality_metrics payload: checklist_ref must be a non-empty string when provided");
1453
+ }
1454
+ return {
1455
+ kind: "qa_quality_metrics",
1456
+ schemaVersion: 1,
1457
+ suiteRunId: requiredString(input["suite_run_id"] ?? input["suiteRunId"], "suite_run_id"),
1458
+ ...typeof checklistRefRaw === "string" ? { checklistRef: checklistRefRaw.trim() } : {},
1459
+ functionalCoverage: counts(input["functional_coverage"] ?? input["functionalCoverage"], "functional_coverage"),
1460
+ p0Tests: testCounts(input["p0_tests"] ?? input["p0Tests"], "p0_tests"),
1461
+ p1Tests: testCounts(input["p1_tests"] ?? input["p1Tests"], "p1_tests")
1462
+ };
1463
+ }
1464
+ var init_workorder_quality = __esm({
1465
+ "../contract/src/workorder-quality.ts"() {
1466
+ "use strict";
1467
+ }
1468
+ });
1469
+
1408
1470
  // ../contract/src/schema.ts
1409
1471
  var init_schema = __esm({
1410
1472
  "../contract/src/schema.ts"() {
@@ -1462,9 +1524,9 @@ var init_storage = __esm({
1462
1524
  });
1463
1525
 
1464
1526
  // ../contract/src/avatar.ts
1465
- function isAgentAvatarPresetRef(ref) {
1466
- if (typeof ref !== "string" || !ref.startsWith(AGENT_AVATAR_PRESET_PREFIX)) return false;
1467
- const id = ref.slice(AGENT_AVATAR_PRESET_PREFIX.length);
1527
+ function isAgentAvatarPresetRef(ref2) {
1528
+ if (typeof ref2 !== "string" || !ref2.startsWith(AGENT_AVATAR_PRESET_PREFIX)) return false;
1529
+ const id = ref2.slice(AGENT_AVATAR_PRESET_PREFIX.length);
1468
1530
  return AGENT_AVATAR_PRESET_IDS.includes(id);
1469
1531
  }
1470
1532
  var AGENT_AVATAR_PRESET_PREFIX, AGENT_AVATAR_PRESET_IDS;
@@ -1576,6 +1638,7 @@ var init_src = __esm({
1576
1638
  init_company();
1577
1639
  init_annotation();
1578
1640
  init_collab_view();
1641
+ init_workorder_quality();
1579
1642
  init_schema();
1580
1643
  init_errors();
1581
1644
  init_storage();
@@ -1636,13 +1699,13 @@ async function reachableBlobs(oplog, blobs) {
1636
1699
  const reachable = /* @__PURE__ */ new Set();
1637
1700
  for await (const { op } of oplog.readAll()) {
1638
1701
  const payload = op.payload;
1639
- const ref = payload.contentRef;
1640
- if (typeof ref !== "string") continue;
1702
+ const ref2 = payload.contentRef;
1703
+ if (typeof ref2 !== "string") continue;
1641
1704
  if (payload.contentKind === "external-pin") continue;
1642
1705
  if (payload.contentKind === "manifest") {
1643
- for (const h of await manifestRefs(blobs, ref)) reachable.add(h);
1706
+ for (const h of await manifestRefs(blobs, ref2)) reachable.add(h);
1644
1707
  } else {
1645
- reachable.add(ref);
1708
+ reachable.add(ref2);
1646
1709
  }
1647
1710
  }
1648
1711
  return reachable;
@@ -1664,10 +1727,10 @@ async function checkCitationExists(input) {
1664
1727
  if (input.revision.contentKind && input.revision.contentKind !== "inline-blob") return [];
1665
1728
  const text = new TextDecoder().decode(await input.blobs.get(input.revision.contentRef));
1666
1729
  const findings = [];
1667
- for (const ref of new Set(text.match(CITATION_RE) ?? [])) {
1668
- const exists = ref.startsWith("artifact:") ? input.model.artifacts.has(ref) : input.model.revisions.has(ref);
1730
+ for (const ref2 of new Set(text.match(CITATION_RE) ?? [])) {
1731
+ const exists = ref2.startsWith("artifact:") ? input.model.artifacts.has(ref2) : input.model.revisions.has(ref2);
1669
1732
  if (!exists) {
1670
- findings.push({ check: "citation_exists", detail: `\u51ED\u7A7A/\u60AC\u7A7A\u5F15\u7528\uFF1A${ref}` });
1733
+ findings.push({ check: "citation_exists", detail: `\u51ED\u7A7A/\u60AC\u7A7A\u5F15\u7528\uFF1A${ref2}` });
1671
1734
  }
1672
1735
  }
1673
1736
  return findings;
@@ -2802,7 +2865,7 @@ var init_kernel = __esm({
2802
2865
  return id;
2803
2866
  });
2804
2867
  const candidates = [...existing, ...batch];
2805
- const ref = (r, what) => {
2868
+ const ref2 = (r, what) => {
2806
2869
  if (r === void 0) return void 0;
2807
2870
  if (!ws) return r;
2808
2871
  const res = resolveNodeRef(r, candidates);
@@ -2815,15 +2878,15 @@ ${res.candidates.map((c) => ` - ${c.type}:${c.title ?? "(\u65E0title)"} \u2192
2815
2878
  const ops = plan.ops.map((op, i) => {
2816
2879
  switch (op.action) {
2817
2880
  case "spawn":
2818
- return { ...op, id: spawnIds[i], ...op.workspace === void 0 && ws ? { workspace: ws } : {}, ...op.inputs ? { inputs: op.inputs.map((e) => ({ to: ref(e.to, "spawn \u4F9D\u8D56"), ...e.required !== void 0 ? { required: e.required } : {} })) } : {} };
2881
+ return { ...op, id: spawnIds[i], ...op.workspace === void 0 && ws ? { workspace: ws } : {}, ...op.inputs ? { inputs: op.inputs.map((e) => ({ to: ref2(e.to, "spawn \u4F9D\u8D56"), ...e.required !== void 0 ? { required: e.required } : {} })) } : {} };
2819
2882
  case "link":
2820
2883
  case "unlink":
2821
2884
  case "pin":
2822
- return { ...op, artifactId: ref(op.artifactId, op.action), to: ref(op.to, `${op.action} \u4E0A\u6E38`) };
2885
+ return { ...op, artifactId: ref2(op.artifactId, op.action), to: ref2(op.to, `${op.action} \u4E0A\u6E38`) };
2823
2886
  case "annotate":
2824
- return { ...op, artifactId: ref(op.artifactId, "annotate"), ...op.raisedFrom ? { raisedFrom: ref(op.raisedFrom, "annotate raisedFrom") } : {} };
2887
+ return { ...op, artifactId: ref2(op.artifactId, "annotate"), ...op.raisedFrom ? { raisedFrom: ref2(op.raisedFrom, "annotate raisedFrom") } : {} };
2825
2888
  default:
2826
- return { ...op, artifactId: ref(op.artifactId, op.action) };
2889
+ return { ...op, artifactId: ref2(op.artifactId, op.action) };
2827
2890
  }
2828
2891
  });
2829
2892
  return { ...plan, ops };
@@ -4069,7 +4132,7 @@ var init_dispatcher = __esm({
4069
4132
  } catch {
4070
4133
  }
4071
4134
  }
4072
- /** 熔断中的 job(B3 表面化:/api/view dispatches 的 fused 区) */
4135
+ /** 熔断中的 job(B3 表面化:/api/view dispatches 的 fused 区;lastReason 供自动分诊做诊断上下文) */
4073
4136
  fusedJobs() {
4074
4137
  return [...this.strikes.entries()].filter(([, st]) => st.fused).map(([jobKey, st]) => ({
4075
4138
  jobKey,
@@ -4077,7 +4140,8 @@ var init_dispatcher = __esm({
4077
4140
  actor: st.actor,
4078
4141
  action: st.action,
4079
4142
  consecutiveFailures: st.count,
4080
- fusedAt: st.fusedAt
4143
+ fusedAt: st.fusedAt,
4144
+ ...st.lastReason ? { lastReason: st.lastReason } : {}
4081
4145
  }));
4082
4146
  }
4083
4147
  /**
@@ -5006,22 +5070,22 @@ var init_ci_provider = __esm({
5006
5070
  const { stdout } = await execFile("git", args, { cwd: this.repoDir(repo), env: process.env });
5007
5071
  return stdout.trim();
5008
5072
  }
5009
- async ensurePr(ref, meta) {
5010
- if (!ref.repo.remote) throw new Error(`repo ${ref.repo.id} \u65E0 remote\uFF0C\u65E0\u6CD5\u5F00 PR`);
5011
- await this.git(ref.repo, ["fetch", "--quiet", "--prune", "origin"]);
5012
- await this.git(ref.repo, ["push", "--quiet", "--force-with-lease", "origin", `${ref.sha}:refs/heads/${ref.branch}`]);
5013
- const existing = await this.gh(ref.repo, ["pr", "list", "--head", ref.branch, "--base", ref.repo.develop, "--state", "open", "--json", "number,url"]);
5073
+ async ensurePr(ref2, meta) {
5074
+ if (!ref2.repo.remote) throw new Error(`repo ${ref2.repo.id} \u65E0 remote\uFF0C\u65E0\u6CD5\u5F00 PR`);
5075
+ await this.git(ref2.repo, ["fetch", "--quiet", "--prune", "origin"]);
5076
+ await this.git(ref2.repo, ["push", "--quiet", "--force-with-lease", "origin", `${ref2.sha}:refs/heads/${ref2.branch}`]);
5077
+ const existing = await this.gh(ref2.repo, ["pr", "list", "--head", ref2.branch, "--base", ref2.repo.develop, "--state", "open", "--json", "number,url"]);
5014
5078
  const list = JSON.parse(existing || "[]");
5015
5079
  if (list[0]) return list[0];
5016
- const url = await this.gh(ref.repo, ["pr", "create", "--base", ref.repo.develop, "--head", ref.branch, "--title", meta.title, "--body", meta.body]);
5017
- const created = JSON.parse(await this.gh(ref.repo, ["pr", "view", ref.branch, "--json", "number,url"]));
5018
- this.opts.log?.(`[ci] opened PR ${created.url} (${ref.branch} \u2192 ${ref.repo.develop})`);
5080
+ const url = await this.gh(ref2.repo, ["pr", "create", "--base", ref2.repo.develop, "--head", ref2.branch, "--title", meta.title, "--body", meta.body]);
5081
+ const created = JSON.parse(await this.gh(ref2.repo, ["pr", "view", ref2.branch, "--json", "number,url"]));
5082
+ this.opts.log?.(`[ci] opened PR ${created.url} (${ref2.branch} \u2192 ${ref2.repo.develop})`);
5019
5083
  return created.url ? created : { number: created.number, url };
5020
5084
  }
5021
- async status(ref) {
5085
+ async status(ref2) {
5022
5086
  let raw;
5023
5087
  try {
5024
- raw = await this.gh(ref.repo, ["pr", "view", ref.branch, "--json", "statusCheckRollup,createdAt"]);
5088
+ raw = await this.gh(ref2.repo, ["pr", "view", ref2.branch, "--json", "statusCheckRollup,createdAt"]);
5025
5089
  } catch (e) {
5026
5090
  return { state: "pending", summary: `\u8BFB PR \u72B6\u6001\u5931\u8D25\uFF08\u4E0B\u8F6E\u91CD\u8BD5\uFF09\uFF1A${String(e)}` };
5027
5091
  }
@@ -5032,7 +5096,7 @@ var init_ci_provider = __esm({
5032
5096
  const ageMs = parsed.createdAt ? Date.now() - Date.parse(parsed.createdAt) : Infinity;
5033
5097
  if (ageMs < grace) return { state: "pending" };
5034
5098
  if (this.opts.failClosedWhenNoChecks) return { state: "failure", summary: "\u8BE5\u4ED3\u672A\u914D\u4EFB\u4F55 Actions check\uFF08fail-closed\uFF09\u2014\u2014\u8BF7\u8865 CI \u6216\u6539\u914D\u7F6E" };
5035
- this.opts.log?.(`[ci] ${ref.repo.id} PR ${ref.branch} \u5F00\u4E86 ${Math.round(ageMs / 1e3)}s \u4ECD\u65E0 check\uFF0C\u5224\u65E0 CI\u3001\u95F8\u7A7A\u8FC7\uFF08\u544A\u8B66\uFF09`);
5099
+ this.opts.log?.(`[ci] ${ref2.repo.id} PR ${ref2.branch} \u5F00\u4E86 ${Math.round(ageMs / 1e3)}s \u4ECD\u65E0 check\uFF0C\u5224\u65E0 CI\u3001\u95F8\u7A7A\u8FC7\uFF08\u544A\u8B66\uFF09`);
5036
5100
  return { state: "success", summary: "\u65E0 CI check\uFF0C\u95F8\u7A7A\u8FC7" };
5037
5101
  }
5038
5102
  const failed = [];
@@ -5054,7 +5118,7 @@ var init_ci_provider = __esm({
5054
5118
  const url = c.detailsUrl ?? c.targetUrl ?? "";
5055
5119
  let block = ` - ${name} \u2192 ${concl}${url ? `
5056
5120
  ${url}` : ""}`;
5057
- const tail = await this.failedLogTail(ref.repo, url);
5121
+ const tail = await this.failedLogTail(ref2.repo, url);
5058
5122
  if (tail) block += `
5059
5123
  \u5931\u8D25\u65E5\u5FD7\uFF08\u672B\u5C3E\uFF09\uFF1A
5060
5124
  ${tail.split("\n").map((l) => " " + l).join("\n")}`;
@@ -5077,20 +5141,20 @@ ${blocks.join("\n")}` };
5077
5141
  return "";
5078
5142
  }
5079
5143
  }
5080
- async merge(ref) {
5144
+ async merge(ref2) {
5081
5145
  try {
5082
- await this.gh(ref.repo, ["pr", "merge", ref.branch, "--merge", "--delete-branch"]);
5083
- this.opts.log?.(`[ci] merged PR ${ref.branch} \u2192 ${ref.repo.develop}`);
5146
+ await this.gh(ref2.repo, ["pr", "merge", ref2.branch, "--merge", "--delete-branch"]);
5147
+ this.opts.log?.(`[ci] merged PR ${ref2.branch} \u2192 ${ref2.repo.develop}`);
5084
5148
  return { merged: true };
5085
5149
  } catch (e) {
5086
5150
  return { merged: false, reason: String(e) };
5087
5151
  }
5088
5152
  }
5089
- async isMerged(ref) {
5090
- if (!ref.repo.remote) return false;
5153
+ async isMerged(ref2) {
5154
+ if (!ref2.repo.remote) return false;
5091
5155
  try {
5092
- await this.git(ref.repo, ["fetch", "--quiet", "origin", ref.repo.develop]);
5093
- await this.git(ref.repo, ["merge-base", "--is-ancestor", ref.sha, `origin/${ref.repo.develop}`]);
5156
+ await this.git(ref2.repo, ["fetch", "--quiet", "origin", ref2.repo.develop]);
5157
+ await this.git(ref2.repo, ["merge-base", "--is-ancestor", ref2.sha, `origin/${ref2.repo.develop}`]);
5094
5158
  return true;
5095
5159
  } catch {
5096
5160
  return false;
@@ -5117,8 +5181,8 @@ function collectUmbrellaCommits(repos, featBranch, env) {
5117
5181
  const refs = /* @__PURE__ */ new Map();
5118
5182
  for (const line of ls.trim().split("\n")) {
5119
5183
  if (!line) continue;
5120
- const [sha2, ref] = line.split(" ");
5121
- if (sha2 && ref) refs.set(ref, sha2);
5184
+ const [sha2, ref2] = line.split(" ");
5185
+ if (sha2 && ref2) refs.set(ref2, sha2);
5122
5186
  }
5123
5187
  const featSha = refs.get(`refs/heads/${featBranch}`);
5124
5188
  const devSha = refs.get(`refs/heads/${r.develop}`);
@@ -5193,9 +5257,9 @@ function autoMergeWorkIntoFeat(args) {
5193
5257
  }
5194
5258
  }
5195
5259
  }
5196
- const has = (ref) => {
5260
+ const has = (ref2) => {
5197
5261
  try {
5198
- git(["rev-parse", "--verify", "--quiet", ref]);
5262
+ git(["rev-parse", "--verify", "--quiet", ref2]);
5199
5263
  return true;
5200
5264
  } catch {
5201
5265
  return false;
@@ -12687,7 +12751,7 @@ function intersection(left, right) {
12687
12751
  right
12688
12752
  });
12689
12753
  }
12690
- function record(keyType, valueType, params) {
12754
+ function record2(keyType, valueType, params) {
12691
12755
  return new ZodRecord2({
12692
12756
  type: "record",
12693
12757
  keyType,
@@ -13496,7 +13560,7 @@ var init_types2 = __esm({
13496
13560
  });
13497
13561
  FormElicitationCapabilitySchema = intersection(object({
13498
13562
  applyDefaults: boolean2().optional()
13499
- }), record(string2(), unknown()));
13563
+ }), record2(string2(), unknown()));
13500
13564
  ElicitationCapabilitySchema = preprocess((value) => {
13501
13565
  if (value && typeof value === "object" && !Array.isArray(value)) {
13502
13566
  if (Object.keys(value).length === 0) {
@@ -13507,7 +13571,7 @@ var init_types2 = __esm({
13507
13571
  }, intersection(object({
13508
13572
  form: FormElicitationCapabilitySchema.optional(),
13509
13573
  url: AssertObjectSchema.optional()
13510
- }), record(string2(), unknown()).optional()));
13574
+ }), record2(string2(), unknown()).optional()));
13511
13575
  ClientTasksCapabilitySchema = looseObject({
13512
13576
  /**
13513
13577
  * Present if the client supports listing tasks.
@@ -13560,7 +13624,7 @@ var init_types2 = __esm({
13560
13624
  /**
13561
13625
  * Experimental, non-standard capabilities that the client supports.
13562
13626
  */
13563
- experimental: record(string2(), AssertObjectSchema).optional(),
13627
+ experimental: record2(string2(), AssertObjectSchema).optional(),
13564
13628
  /**
13565
13629
  * Present if the client supports sampling from an LLM.
13566
13630
  */
@@ -13595,7 +13659,7 @@ var init_types2 = __esm({
13595
13659
  /**
13596
13660
  * Extensions that the client supports. Keys are extension identifiers (vendor-prefix/extension-name).
13597
13661
  */
13598
- extensions: record(string2(), AssertObjectSchema).optional()
13662
+ extensions: record2(string2(), AssertObjectSchema).optional()
13599
13663
  });
13600
13664
  InitializeRequestParamsSchema = BaseRequestParamsSchema.extend({
13601
13665
  /**
@@ -13613,7 +13677,7 @@ var init_types2 = __esm({
13613
13677
  /**
13614
13678
  * Experimental, non-standard capabilities that the server supports.
13615
13679
  */
13616
- experimental: record(string2(), AssertObjectSchema).optional(),
13680
+ experimental: record2(string2(), AssertObjectSchema).optional(),
13617
13681
  /**
13618
13682
  * Present if the server supports sending log messages to the client.
13619
13683
  */
@@ -13660,7 +13724,7 @@ var init_types2 = __esm({
13660
13724
  /**
13661
13725
  * Extensions that the server supports. Keys are extension identifiers (vendor-prefix/extension-name).
13662
13726
  */
13663
- extensions: record(string2(), AssertObjectSchema).optional()
13727
+ extensions: record2(string2(), AssertObjectSchema).optional()
13664
13728
  });
13665
13729
  InitializeResultSchema = ResultSchema.extend({
13666
13730
  /**
@@ -13798,7 +13862,7 @@ var init_types2 = __esm({
13798
13862
  * See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields)
13799
13863
  * for notes on _meta usage.
13800
13864
  */
13801
- _meta: record(string2(), unknown()).optional()
13865
+ _meta: record2(string2(), unknown()).optional()
13802
13866
  });
13803
13867
  TextResourceContentsSchema = ResourceContentsSchema.extend({
13804
13868
  /**
@@ -13992,7 +14056,7 @@ var init_types2 = __esm({
13992
14056
  /**
13993
14057
  * Arguments to use for templating the prompt.
13994
14058
  */
13995
- arguments: record(string2(), string2()).optional()
14059
+ arguments: record2(string2(), string2()).optional()
13996
14060
  });
13997
14061
  GetPromptRequestSchema = RequestSchema.extend({
13998
14062
  method: literal("prompts/get"),
@@ -14012,7 +14076,7 @@ var init_types2 = __esm({
14012
14076
  * See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields)
14013
14077
  * for notes on _meta usage.
14014
14078
  */
14015
- _meta: record(string2(), unknown()).optional()
14079
+ _meta: record2(string2(), unknown()).optional()
14016
14080
  });
14017
14081
  ImageContentSchema = object({
14018
14082
  type: literal("image"),
@@ -14032,7 +14096,7 @@ var init_types2 = __esm({
14032
14096
  * See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields)
14033
14097
  * for notes on _meta usage.
14034
14098
  */
14035
- _meta: record(string2(), unknown()).optional()
14099
+ _meta: record2(string2(), unknown()).optional()
14036
14100
  });
14037
14101
  AudioContentSchema = object({
14038
14102
  type: literal("audio"),
@@ -14052,7 +14116,7 @@ var init_types2 = __esm({
14052
14116
  * See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields)
14053
14117
  * for notes on _meta usage.
14054
14118
  */
14055
- _meta: record(string2(), unknown()).optional()
14119
+ _meta: record2(string2(), unknown()).optional()
14056
14120
  });
14057
14121
  ToolUseContentSchema = object({
14058
14122
  type: literal("tool_use"),
@@ -14070,12 +14134,12 @@ var init_types2 = __esm({
14070
14134
  * Arguments to pass to the tool.
14071
14135
  * Must conform to the tool's inputSchema.
14072
14136
  */
14073
- input: record(string2(), unknown()),
14137
+ input: record2(string2(), unknown()),
14074
14138
  /**
14075
14139
  * See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields)
14076
14140
  * for notes on _meta usage.
14077
14141
  */
14078
- _meta: record(string2(), unknown()).optional()
14142
+ _meta: record2(string2(), unknown()).optional()
14079
14143
  });
14080
14144
  EmbeddedResourceSchema = object({
14081
14145
  type: literal("resource"),
@@ -14088,7 +14152,7 @@ var init_types2 = __esm({
14088
14152
  * See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields)
14089
14153
  * for notes on _meta usage.
14090
14154
  */
14091
- _meta: record(string2(), unknown()).optional()
14155
+ _meta: record2(string2(), unknown()).optional()
14092
14156
  });
14093
14157
  ResourceLinkSchema = ResourceSchema.extend({
14094
14158
  type: literal("resource_link")
@@ -14178,7 +14242,7 @@ var init_types2 = __esm({
14178
14242
  */
14179
14243
  inputSchema: object({
14180
14244
  type: literal("object"),
14181
- properties: record(string2(), AssertObjectSchema).optional(),
14245
+ properties: record2(string2(), AssertObjectSchema).optional(),
14182
14246
  required: array(string2()).optional()
14183
14247
  }).catchall(unknown()),
14184
14248
  /**
@@ -14188,7 +14252,7 @@ var init_types2 = __esm({
14188
14252
  */
14189
14253
  outputSchema: object({
14190
14254
  type: literal("object"),
14191
- properties: record(string2(), AssertObjectSchema).optional(),
14255
+ properties: record2(string2(), AssertObjectSchema).optional(),
14192
14256
  required: array(string2()).optional()
14193
14257
  }).catchall(unknown()).optional(),
14194
14258
  /**
@@ -14203,7 +14267,7 @@ var init_types2 = __esm({
14203
14267
  * See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields)
14204
14268
  * for notes on _meta usage.
14205
14269
  */
14206
- _meta: record(string2(), unknown()).optional()
14270
+ _meta: record2(string2(), unknown()).optional()
14207
14271
  });
14208
14272
  ListToolsRequestSchema = PaginatedRequestSchema.extend({
14209
14273
  method: literal("tools/list")
@@ -14224,7 +14288,7 @@ var init_types2 = __esm({
14224
14288
  *
14225
14289
  * If the Tool defines an outputSchema, this field MUST be present in the result, and contain a JSON object that matches the schema.
14226
14290
  */
14227
- structuredContent: record(string2(), unknown()).optional(),
14291
+ structuredContent: record2(string2(), unknown()).optional(),
14228
14292
  /**
14229
14293
  * Whether the tool call ended in an error.
14230
14294
  *
@@ -14252,7 +14316,7 @@ var init_types2 = __esm({
14252
14316
  /**
14253
14317
  * Arguments to pass to the tool.
14254
14318
  */
14255
- arguments: record(string2(), unknown()).optional()
14319
+ arguments: record2(string2(), unknown()).optional()
14256
14320
  });
14257
14321
  CallToolRequestSchema = RequestSchema.extend({
14258
14322
  method: literal("tools/call"),
@@ -14354,7 +14418,7 @@ var init_types2 = __esm({
14354
14418
  * See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields)
14355
14419
  * for notes on _meta usage.
14356
14420
  */
14357
- _meta: record(string2(), unknown()).optional()
14421
+ _meta: record2(string2(), unknown()).optional()
14358
14422
  });
14359
14423
  SamplingContentSchema = discriminatedUnion("type", [TextContentSchema, ImageContentSchema, AudioContentSchema]);
14360
14424
  SamplingMessageContentBlockSchema = discriminatedUnion("type", [
@@ -14371,7 +14435,7 @@ var init_types2 = __esm({
14371
14435
  * See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields)
14372
14436
  * for notes on _meta usage.
14373
14437
  */
14374
- _meta: record(string2(), unknown()).optional()
14438
+ _meta: record2(string2(), unknown()).optional()
14375
14439
  });
14376
14440
  CreateMessageRequestParamsSchema = TaskAugmentedRequestParamsSchema.extend({
14377
14441
  messages: array(SamplingMessageSchema),
@@ -14559,7 +14623,7 @@ var init_types2 = __esm({
14559
14623
  */
14560
14624
  requestedSchema: object({
14561
14625
  type: literal("object"),
14562
- properties: record(string2(), PrimitiveSchemaDefinitionSchema),
14626
+ properties: record2(string2(), PrimitiveSchemaDefinitionSchema),
14563
14627
  required: array(string2()).optional()
14564
14628
  })
14565
14629
  });
@@ -14611,7 +14675,7 @@ var init_types2 = __esm({
14611
14675
  * Per MCP spec, content is "typically omitted" for decline/cancel actions.
14612
14676
  * We normalize null to undefined for leniency while maintaining type compatibility.
14613
14677
  */
14614
- content: preprocess((val) => val === null ? void 0 : val, record(string2(), union([string2(), number2(), boolean2(), array(string2())])).optional())
14678
+ content: preprocess((val) => val === null ? void 0 : val, record2(string2(), union([string2(), number2(), boolean2(), array(string2())])).optional())
14615
14679
  });
14616
14680
  ResourceTemplateReferenceSchema = object({
14617
14681
  type: literal("ref/resource"),
@@ -14646,7 +14710,7 @@ var init_types2 = __esm({
14646
14710
  /**
14647
14711
  * Previously-resolved variables in a URI template or prompt.
14648
14712
  */
14649
- arguments: record(string2(), string2()).optional()
14713
+ arguments: record2(string2(), string2()).optional()
14650
14714
  }).optional()
14651
14715
  });
14652
14716
  CompleteRequestSchema = RequestSchema.extend({
@@ -14682,7 +14746,7 @@ var init_types2 = __esm({
14682
14746
  * See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields)
14683
14747
  * for notes on _meta usage.
14684
14748
  */
14685
- _meta: record(string2(), unknown()).optional()
14749
+ _meta: record2(string2(), unknown()).optional()
14686
14750
  });
14687
14751
  ListRootsRequestSchema = RequestSchema.extend({
14688
14752
  method: literal("roots/list"),
@@ -17331,20 +17395,20 @@ var require_resolve = __commonJS({
17331
17395
  return false;
17332
17396
  }
17333
17397
  function countKeys(schema) {
17334
- let count = 0;
17398
+ let count2 = 0;
17335
17399
  for (const key in schema) {
17336
17400
  if (key === "$ref")
17337
17401
  return Infinity;
17338
- count++;
17402
+ count2++;
17339
17403
  if (SIMPLE_INLINED.has(key))
17340
17404
  continue;
17341
17405
  if (typeof schema[key] == "object") {
17342
- (0, util_1.eachItem)(schema[key], (sch) => count += countKeys(sch));
17406
+ (0, util_1.eachItem)(schema[key], (sch) => count2 += countKeys(sch));
17343
17407
  }
17344
- if (count === Infinity)
17408
+ if (count2 === Infinity)
17345
17409
  return Infinity;
17346
17410
  }
17347
- return count;
17411
+ return count2;
17348
17412
  }
17349
17413
  function getFullPath(resolver, id = "", normalize) {
17350
17414
  if (normalize !== false)
@@ -17388,26 +17452,26 @@ var require_resolve = __commonJS({
17388
17452
  addAnchor.call(this, sch.$anchor);
17389
17453
  addAnchor.call(this, sch.$dynamicAnchor);
17390
17454
  baseIds[jsonPtr] = innerBaseId;
17391
- function addRef(ref) {
17455
+ function addRef(ref2) {
17392
17456
  const _resolve = this.opts.uriResolver.resolve;
17393
- ref = normalizeId(innerBaseId ? _resolve(innerBaseId, ref) : ref);
17394
- if (schemaRefs.has(ref))
17395
- throw ambiguos(ref);
17396
- schemaRefs.add(ref);
17397
- let schOrRef = this.refs[ref];
17457
+ ref2 = normalizeId(innerBaseId ? _resolve(innerBaseId, ref2) : ref2);
17458
+ if (schemaRefs.has(ref2))
17459
+ throw ambiguos(ref2);
17460
+ schemaRefs.add(ref2);
17461
+ let schOrRef = this.refs[ref2];
17398
17462
  if (typeof schOrRef == "string")
17399
17463
  schOrRef = this.refs[schOrRef];
17400
17464
  if (typeof schOrRef == "object") {
17401
- checkAmbiguosRef(sch, schOrRef.schema, ref);
17402
- } else if (ref !== normalizeId(fullPath)) {
17403
- if (ref[0] === "#") {
17404
- checkAmbiguosRef(sch, localRefs[ref], ref);
17405
- localRefs[ref] = sch;
17465
+ checkAmbiguosRef(sch, schOrRef.schema, ref2);
17466
+ } else if (ref2 !== normalizeId(fullPath)) {
17467
+ if (ref2[0] === "#") {
17468
+ checkAmbiguosRef(sch, localRefs[ref2], ref2);
17469
+ localRefs[ref2] = sch;
17406
17470
  } else {
17407
- this.refs[ref] = fullPath;
17471
+ this.refs[ref2] = fullPath;
17408
17472
  }
17409
17473
  }
17410
- return ref;
17474
+ return ref2;
17411
17475
  }
17412
17476
  function addAnchor(anchor) {
17413
17477
  if (typeof anchor == "string") {
@@ -17418,12 +17482,12 @@ var require_resolve = __commonJS({
17418
17482
  }
17419
17483
  });
17420
17484
  return localRefs;
17421
- function checkAmbiguosRef(sch1, sch2, ref) {
17485
+ function checkAmbiguosRef(sch1, sch2, ref2) {
17422
17486
  if (sch2 !== void 0 && !equal(sch1, sch2))
17423
- throw ambiguos(ref);
17487
+ throw ambiguos(ref2);
17424
17488
  }
17425
- function ambiguos(ref) {
17426
- return new Error(`reference "${ref}" resolves to more than one schema`);
17489
+ function ambiguos(ref2) {
17490
+ return new Error(`reference "${ref2}" resolves to more than one schema`);
17427
17491
  }
17428
17492
  }
17429
17493
  exports2.getSchemaRefs = getSchemaRefs;
@@ -17961,9 +18025,9 @@ var require_ref_error = __commonJS({
17961
18025
  Object.defineProperty(exports2, "__esModule", { value: true });
17962
18026
  var resolve_1 = require_resolve();
17963
18027
  var MissingRefError = class extends Error {
17964
- constructor(resolver, baseId, ref, msg) {
17965
- super(msg || `can't resolve reference ${ref} from id ${baseId}`);
17966
- this.missingRef = (0, resolve_1.resolveUrl)(resolver, baseId, ref);
18028
+ constructor(resolver, baseId, ref2, msg) {
18029
+ super(msg || `can't resolve reference ${ref2} from id ${baseId}`);
18030
+ this.missingRef = (0, resolve_1.resolveUrl)(resolver, baseId, ref2);
17967
18031
  this.missingSchema = (0, resolve_1.normalizeId)((0, resolve_1.getFullPath)(resolver, this.missingRef));
17968
18032
  }
17969
18033
  };
@@ -18089,22 +18153,22 @@ var require_compile = __commonJS({
18089
18153
  }
18090
18154
  }
18091
18155
  exports2.compileSchema = compileSchema;
18092
- function resolveRef2(root, baseId, ref) {
18156
+ function resolveRef2(root, baseId, ref2) {
18093
18157
  var _a;
18094
- ref = (0, resolve_1.resolveUrl)(this.opts.uriResolver, baseId, ref);
18095
- const schOrFunc = root.refs[ref];
18158
+ ref2 = (0, resolve_1.resolveUrl)(this.opts.uriResolver, baseId, ref2);
18159
+ const schOrFunc = root.refs[ref2];
18096
18160
  if (schOrFunc)
18097
18161
  return schOrFunc;
18098
- let _sch = resolve5.call(this, root, ref);
18162
+ let _sch = resolve5.call(this, root, ref2);
18099
18163
  if (_sch === void 0) {
18100
- const schema = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref];
18164
+ const schema = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref2];
18101
18165
  const { schemaId } = this.opts;
18102
18166
  if (schema)
18103
18167
  _sch = new SchemaEnv({ schema, schemaId, root, baseId });
18104
18168
  }
18105
18169
  if (_sch === void 0)
18106
18170
  return;
18107
- return root.refs[ref] = inlineOrCompile.call(this, _sch);
18171
+ return root.refs[ref2] = inlineOrCompile.call(this, _sch);
18108
18172
  }
18109
18173
  exports2.resolveRef = resolveRef2;
18110
18174
  function inlineOrCompile(sch) {
@@ -18122,14 +18186,14 @@ var require_compile = __commonJS({
18122
18186
  function sameSchemaEnv(s1, s2) {
18123
18187
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
18124
18188
  }
18125
- function resolve5(root, ref) {
18189
+ function resolve5(root, ref2) {
18126
18190
  let sch;
18127
- while (typeof (sch = this.refs[ref]) == "string")
18128
- ref = sch;
18129
- return sch || this.schemas[ref] || resolveSchema.call(this, root, ref);
18191
+ while (typeof (sch = this.refs[ref2]) == "string")
18192
+ ref2 = sch;
18193
+ return sch || this.schemas[ref2] || resolveSchema.call(this, root, ref2);
18130
18194
  }
18131
- function resolveSchema(root, ref) {
18132
- const p2 = this.opts.uriResolver.parse(ref);
18195
+ function resolveSchema(root, ref2) {
18196
+ const p2 = this.opts.uriResolver.parse(ref2);
18133
18197
  const refPath = (0, resolve_1._getFullPath)(this.opts.uriResolver, p2);
18134
18198
  let baseId = (0, resolve_1.getFullPath)(this.opts.uriResolver, root.baseId, void 0);
18135
18199
  if (Object.keys(root.schema).length > 0 && refPath === baseId) {
@@ -18147,7 +18211,7 @@ var require_compile = __commonJS({
18147
18211
  return;
18148
18212
  if (!schOrRef.validate)
18149
18213
  compileSchema.call(this, schOrRef);
18150
- if (id === (0, resolve_1.normalizeId)(ref)) {
18214
+ if (id === (0, resolve_1.normalizeId)(ref2)) {
18151
18215
  const { schema } = schOrRef;
18152
18216
  const { schemaId } = this.opts;
18153
18217
  const schId = schema[schemaId];
@@ -19234,26 +19298,26 @@ var require_core = __commonJS({
19234
19298
  return _compileAsync.call(this, sch);
19235
19299
  }
19236
19300
  }
19237
- function checkLoaded({ missingSchema: ref, missingRef }) {
19238
- if (this.refs[ref]) {
19239
- throw new Error(`AnySchema ${ref} is loaded but ${missingRef} cannot be resolved`);
19301
+ function checkLoaded({ missingSchema: ref2, missingRef }) {
19302
+ if (this.refs[ref2]) {
19303
+ throw new Error(`AnySchema ${ref2} is loaded but ${missingRef} cannot be resolved`);
19240
19304
  }
19241
19305
  }
19242
- async function loadMissingSchema(ref) {
19243
- const _schema = await _loadSchema.call(this, ref);
19244
- if (!this.refs[ref])
19306
+ async function loadMissingSchema(ref2) {
19307
+ const _schema = await _loadSchema.call(this, ref2);
19308
+ if (!this.refs[ref2])
19245
19309
  await loadMetaSchema.call(this, _schema.$schema);
19246
- if (!this.refs[ref])
19247
- this.addSchema(_schema, ref, meta);
19310
+ if (!this.refs[ref2])
19311
+ this.addSchema(_schema, ref2, meta);
19248
19312
  }
19249
- async function _loadSchema(ref) {
19250
- const p2 = this._loading[ref];
19313
+ async function _loadSchema(ref2) {
19314
+ const p2 = this._loading[ref2];
19251
19315
  if (p2)
19252
19316
  return p2;
19253
19317
  try {
19254
- return await (this._loading[ref] = loadSchema(ref));
19318
+ return await (this._loading[ref2] = loadSchema(ref2));
19255
19319
  } finally {
19256
- delete this._loading[ref];
19320
+ delete this._loading[ref2];
19257
19321
  }
19258
19322
  }
19259
19323
  }
@@ -20516,8 +20580,8 @@ var require_contains = __commonJS({
20516
20580
  cxt.result(valid, () => cxt.reset());
20517
20581
  function validateItemsWithCount() {
20518
20582
  const schValid = gen.name("_valid");
20519
- const count = gen.let("count", 0);
20520
- validateItems(schValid, () => gen.if(schValid, () => checkLimits(count)));
20583
+ const count2 = gen.let("count", 0);
20584
+ validateItems(schValid, () => gen.if(schValid, () => checkLimits(count2)));
20521
20585
  }
20522
20586
  function validateItems(_valid, block) {
20523
20587
  gen.forRange("i", 0, len, (i) => {
@@ -20530,16 +20594,16 @@ var require_contains = __commonJS({
20530
20594
  block();
20531
20595
  });
20532
20596
  }
20533
- function checkLimits(count) {
20534
- gen.code((0, codegen_1._)`${count}++`);
20597
+ function checkLimits(count2) {
20598
+ gen.code((0, codegen_1._)`${count2}++`);
20535
20599
  if (max === void 0) {
20536
- gen.if((0, codegen_1._)`${count} >= ${min2}`, () => gen.assign(valid, true).break());
20600
+ gen.if((0, codegen_1._)`${count2} >= ${min2}`, () => gen.assign(valid, true).break());
20537
20601
  } else {
20538
- gen.if((0, codegen_1._)`${count} > ${max}`, () => gen.assign(valid, false).break());
20602
+ gen.if((0, codegen_1._)`${count2} > ${max}`, () => gen.assign(valid, false).break());
20539
20603
  if (min2 === 1)
20540
20604
  gen.assign(valid, true);
20541
20605
  else
20542
- gen.if((0, codegen_1._)`${count} >= ${min2}`, () => gen.assign(valid, true));
20606
+ gen.if((0, codegen_1._)`${count2} >= ${min2}`, () => gen.assign(valid, true));
20543
20607
  }
20544
20608
  }
20545
20609
  }
@@ -21412,12 +21476,12 @@ var require_discriminator = __commonJS({
21412
21476
  for (let i = 0; i < oneOf.length; i++) {
21413
21477
  let sch = oneOf[i];
21414
21478
  if ((sch === null || sch === void 0 ? void 0 : sch.$ref) && !(0, util_1.schemaHasRulesButRef)(sch, it.self.RULES)) {
21415
- const ref = sch.$ref;
21416
- sch = compile_1.resolveRef.call(it.self, it.schemaEnv.root, it.baseId, ref);
21479
+ const ref2 = sch.$ref;
21480
+ sch = compile_1.resolveRef.call(it.self, it.schemaEnv.root, it.baseId, ref2);
21417
21481
  if (sch instanceof compile_1.SchemaEnv)
21418
21482
  sch = sch.schema;
21419
21483
  if (sch === void 0)
21420
- throw new ref_error_1.default(it.opts.uriResolver, it.baseId, ref);
21484
+ throw new ref_error_1.default(it.opts.uriResolver, it.baseId, ref2);
21421
21485
  }
21422
21486
  const propSch = (_a = sch === null || sch === void 0 ? void 0 : sch.properties) === null || _a === void 0 ? void 0 : _a[tagName];
21423
21487
  if (typeof propSch != "object") {
@@ -22341,12 +22405,12 @@ var init_workorder_drafts = __esm({
22341
22405
  });
22342
22406
 
22343
22407
  // ../server/src/governance/draft-edit.ts
22344
- function resolveRef(ref, draft) {
22345
- const res = resolveNodeRef(ref, candidatesOf(draft));
22408
+ function resolveRef(ref2, draft) {
22409
+ const res = resolveNodeRef(ref2, candidatesOf(draft));
22346
22410
  if (res.ok) return res.id;
22347
22411
  if (res.reason === "ambiguous")
22348
- throw new Error(`\u300C${ref}\u300D\u5728\u672C\u8349\u6848\u5339\u914D\u5230\u591A\u4E2A\u8282\u70B9\uFF0C\u8BF7\u66F4\u5177\u4F53\uFF08type:title \u6216 id\uFF09\uFF1A${res.candidates.map((c) => `${c.type}:${c.title ?? "?"}`).join("\u3001")}`);
22349
- throw new Error(`\u300C${ref}\u300D\u5728\u672C\u8349\u6848\u91CC\u627E\u4E0D\u5230\u5BF9\u5E94\u8282\u70B9\uFF08\u53EF\u7528 type / type:title / id\uFF09`);
22412
+ throw new Error(`\u300C${ref2}\u300D\u5728\u672C\u8349\u6848\u5339\u914D\u5230\u591A\u4E2A\u8282\u70B9\uFF0C\u8BF7\u66F4\u5177\u4F53\uFF08type:title \u6216 id\uFF09\uFF1A${res.candidates.map((c) => `${c.type}:${c.title ?? "?"}`).join("\u3001")}`);
22413
+ throw new Error(`\u300C${ref2}\u300D\u5728\u672C\u8349\u6848\u91CC\u627E\u4E0D\u5230\u5BF9\u5E94\u8282\u70B9\uFF08\u53EF\u7528 type / type:title / id\uFF09`);
22350
22414
  }
22351
22415
  function editDraftPlan(draft, op) {
22352
22416
  switch (op.action) {
@@ -23091,7 +23155,7 @@ function buildWorkorderSummaries(model, resolveActor, resolveProject, dispatchPa
23091
23155
  arr.push(a);
23092
23156
  byWorkspace.set(a.workspace, arr);
23093
23157
  }
23094
- const ref = (id) => {
23158
+ const ref2 = (id) => {
23095
23159
  const extra = resolveActor?.(id);
23096
23160
  return {
23097
23161
  id,
@@ -23119,8 +23183,8 @@ function buildWorkorderSummaries(model, resolveActor, resolveProject, dispatchPa
23119
23183
  // 一句话目标:优先取结构化 spec.goal;缺省时前端回退 description 首段(投影不替前端做回退,只给真值)
23120
23184
  ...spec?.goal ? { goal: spec.goal } : {},
23121
23185
  stage,
23122
- owner: ref(seed.owner),
23123
- participants: participantIds.map(ref),
23186
+ owner: ref2(seed.owner),
23187
+ participants: participantIds.map(ref2),
23124
23188
  artifactCount: arts.length,
23125
23189
  progress: { concluded, total: arts.length },
23126
23190
  updatedAt: lastOps[lastOps.length - 1] ?? "",
@@ -23182,7 +23246,7 @@ function buildWorkorderDetail(model, workspaceId, resolveActor, resolveProject,
23182
23246
  if (arts.length === 0) return null;
23183
23247
  const summary = buildWorkorderSummaries(model, resolveActor, resolveProject, dispatchPausedOf).find((w2) => w2.id === workspaceId);
23184
23248
  if (!summary) return null;
23185
- const ref = (id) => {
23249
+ const ref2 = (id) => {
23186
23250
  const extra = resolveActor?.(id);
23187
23251
  return {
23188
23252
  id,
@@ -23191,7 +23255,7 @@ function buildWorkorderDetail(model, workspaceId, resolveActor, resolveProject,
23191
23255
  ...extra?.avatar ? { avatar: extra.avatar } : {}
23192
23256
  };
23193
23257
  };
23194
- const runtimeByArtifact = buildRuntimeByArtifact(dispatchJournal, ref);
23258
+ const runtimeByArtifact = buildRuntimeByArtifact(dispatchJournal, ref2);
23195
23259
  const nodes = arts.map((a) => {
23196
23260
  const info = nodeInfo(model, a);
23197
23261
  const observedRuntime = runtimeByArtifact.get(a.id);
@@ -23209,7 +23273,7 @@ function buildWorkorderDetail(model, workspaceId, resolveActor, resolveProject,
23209
23273
  const stallRaw = stallOf(model, a.id, runtime);
23210
23274
  const stall = stallRaw ? (() => {
23211
23275
  const { actorId, ...rest } = stallRaw;
23212
- return { ...rest, ...actorId ? { actor: ref(actorId) } : {} };
23276
+ return { ...rest, ...actorId ? { actor: ref2(actorId) } : {} };
23213
23277
  })() : void 0;
23214
23278
  return {
23215
23279
  id: a.id,
@@ -23219,11 +23283,11 @@ function buildWorkorderDetail(model, workspaceId, resolveActor, resolveProject,
23219
23283
  currentRev: a.currentRev,
23220
23284
  queue: info.queueLen,
23221
23285
  blocked: blockedOf(model, a.id).blocked,
23222
- owner: ref(a.owner),
23286
+ owner: ref2(a.owner),
23223
23287
  // 封存原因透出:stage 只到 "sealed" 粒度,原因(accepted/cancelled/frozen)另给,供前端区分展示。
23224
23288
  ...lifecycle !== "active" ? { sealedReason: lifecycle.slice("sealed:".length) } : {},
23225
23289
  ...runtime ? { runtime } : {},
23226
- ...pv ? { reviewers: pv.reviewers.map((r) => ({ actor: ref(r.actor), source: r.source })), quorum: pv.quorum, typeName: pv.typeName } : {},
23290
+ ...pv ? { reviewers: pv.reviewers.map((r) => ({ actor: ref2(r.actor), source: r.source })), quorum: pv.quorum, typeName: pv.typeName } : {},
23227
23291
  // 过期事实(提案 rework-cascade-rollout):无条件透出,前端 DAG 挂「上游已更新」徽标。
23228
23292
  ...outdated.length > 0 ? { outdated } : {},
23229
23293
  // 停滞四态(看得清):为什么不动 + 谁欠什么 + 去处理锚;null 时不带。
@@ -23234,28 +23298,28 @@ function buildWorkorderDetail(model, workspaceId, resolveActor, resolveProject,
23234
23298
  (a) => a.inputs.map((e) => ({ from: a.id, to: e.to, pinned: e.pinned, required: e.required }))
23235
23299
  );
23236
23300
  const stallSummary = (() => {
23237
- const counts = { running: 0, held: 0, failed: 0, waitingHuman: 0, waitingAgent: 0, waitingSystem: 0 };
23301
+ const counts2 = { running: 0, held: 0, failed: 0, waitingHuman: 0, waitingAgent: 0, waitingSystem: 0 };
23238
23302
  const sev = { failed: 5, held: 4, waiting_human: 3, waiting_agent: 2, waiting_system: 1, running: 0 };
23239
23303
  const stuck = [];
23240
23304
  for (const n of nodes) {
23241
23305
  const st = n.stall;
23242
23306
  if (!st) continue;
23243
- if (st.kind === "running") counts.running++;
23244
- else if (st.kind === "held") counts.held++;
23245
- else if (st.kind === "failed") counts.failed++;
23246
- else if (st.kind === "waiting_human") counts.waitingHuman++;
23247
- else if (st.kind === "waiting_agent") counts.waitingAgent++;
23248
- else counts.waitingSystem++;
23307
+ if (st.kind === "running") counts2.running++;
23308
+ else if (st.kind === "held") counts2.held++;
23309
+ else if (st.kind === "failed") counts2.failed++;
23310
+ else if (st.kind === "waiting_human") counts2.waitingHuman++;
23311
+ else if (st.kind === "waiting_agent") counts2.waitingAgent++;
23312
+ else counts2.waitingSystem++;
23249
23313
  if (st.kind !== "running") {
23250
23314
  stuck.push({ id: n.id, label: n.label, kind: st.kind, ...st.action ? { action: st.action } : {}, ...st.ref ? { ref: st.ref } : {}, detail: st.detail, ...st.actor ? { actor: st.actor } : {} });
23251
23315
  }
23252
23316
  }
23253
23317
  stuck.sort((a, b2) => sev[b2.kind] - sev[a.kind]);
23254
- const total = counts.running + counts.held + counts.failed + counts.waitingHuman + counts.waitingAgent + counts.waitingSystem;
23255
- return total > 0 ? { counts, stuck } : void 0;
23318
+ const total = counts2.running + counts2.held + counts2.failed + counts2.waitingHuman + counts2.waitingAgent + counts2.waitingSystem;
23319
+ return total > 0 ? { counts: counts2, stuck } : void 0;
23256
23320
  })();
23257
- const activity = buildActivity(model, arts, ref);
23258
- const coordinatorActivity = buildCoordinatorActivity(arts, ops, ref);
23321
+ const activity = buildActivity(model, arts, ref2);
23322
+ const coordinatorActivity = buildCoordinatorActivity(arts, ops, ref2);
23259
23323
  const acceptance = buildAcceptance(model, arts);
23260
23324
  const planning = planningStatusOf(model, arts);
23261
23325
  const spec = workorderSpecOf(model, arts);
@@ -23274,7 +23338,7 @@ function buildWorkorderDetail(model, workspaceId, resolveActor, resolveProject,
23274
23338
  };
23275
23339
  }
23276
23340
  function buildWorkorderDraftDetail(draft, resolveActor) {
23277
- const ref = (id) => {
23341
+ const ref2 = (id) => {
23278
23342
  const extra = resolveActor?.(id);
23279
23343
  return { id, ...extra?.name ? { name: extra.name } : {}, ...extra?.role ? { role: extra.role } : {}, ...extra?.avatar ? { avatar: extra.avatar } : {} };
23280
23344
  };
@@ -23287,7 +23351,7 @@ function buildWorkorderDraftDetail(draft, resolveActor) {
23287
23351
  currentRev: null,
23288
23352
  queue: 0,
23289
23353
  blocked: false,
23290
- owner: ref(op.owner ?? draft.draftedBy)
23354
+ owner: ref2(op.owner ?? draft.draftedBy)
23291
23355
  }));
23292
23356
  const edges = [
23293
23357
  ...spawns.flatMap((op) => (op.inputs ?? []).map((inp) => ({ from: op.id, to: inp.to, pinned: null, required: inp.required ?? true }))),
@@ -23302,8 +23366,8 @@ function buildWorkorderDraftDetail(draft, resolveActor) {
23302
23366
  ...draft.seed.brief && draft.seed.brief !== title ? { description: draft.seed.brief } : {},
23303
23367
  ...draft.seed.goal ? { goal: draft.seed.goal } : {},
23304
23368
  stage: "draft",
23305
- owner: ref(draft.draftedBy),
23306
- participants: participantIds.map((id) => ref(id)),
23369
+ owner: ref2(draft.draftedBy),
23370
+ participants: participantIds.map((id) => ref2(id)),
23307
23371
  artifactCount: nodes.length,
23308
23372
  progress: { concluded: 0, total: nodes.length },
23309
23373
  updatedAt: draft.at,
@@ -23351,7 +23415,7 @@ function withRuntimeActivity(model, artifactId, runtime) {
23351
23415
  );
23352
23416
  return lastActivityAt ? { ...runtime, lastActivityAt } : runtime;
23353
23417
  }
23354
- function buildRuntimeByArtifact(entries, ref) {
23418
+ function buildRuntimeByArtifact(entries, ref2) {
23355
23419
  const byJob = /* @__PURE__ */ new Map();
23356
23420
  for (const entry of entries) {
23357
23421
  if (entry.kind === "dispatched") {
@@ -23359,7 +23423,7 @@ function buildRuntimeByArtifact(entries, ref) {
23359
23423
  artifactId: entry.artifactId,
23360
23424
  status: "running",
23361
23425
  action: entry.action,
23362
- actor: ref(entry.actor),
23426
+ actor: ref2(entry.actor),
23363
23427
  startedAt: entry.at,
23364
23428
  at: entry.at
23365
23429
  });
@@ -23369,7 +23433,7 @@ function buildRuntimeByArtifact(entries, ref) {
23369
23433
  artifactId: entry.artifactId,
23370
23434
  status: "running",
23371
23435
  action: entry.action,
23372
- actor: ref(entry.actor),
23436
+ actor: ref2(entry.actor),
23373
23437
  startedAt: prev?.startedAt ?? entry.at,
23374
23438
  ...entry.interruptedAt ? { interruptedAt: entry.interruptedAt } : {},
23375
23439
  recoveredAt: entry.recoveredAt,
@@ -23381,7 +23445,7 @@ function buildRuntimeByArtifact(entries, ref) {
23381
23445
  artifactId: entry.artifactId,
23382
23446
  status: entry.progressed ? "completed" : "failed",
23383
23447
  action: entry.action,
23384
- actor: ref(entry.actor),
23448
+ actor: ref2(entry.actor),
23385
23449
  finishedAt: entry.at,
23386
23450
  durationMs: entry.durationMs,
23387
23451
  ...entry.reason ? { reason: entry.reason } : {},
@@ -23393,7 +23457,7 @@ function buildRuntimeByArtifact(entries, ref) {
23393
23457
  artifactId: entry.artifactId,
23394
23458
  status: "fused",
23395
23459
  action: entry.action,
23396
- actor: ref(entry.actor),
23460
+ actor: ref2(entry.actor),
23397
23461
  finishedAt: entry.at,
23398
23462
  consecutiveFailures: entry.consecutiveFailures,
23399
23463
  at: entry.at
@@ -23402,7 +23466,7 @@ function buildRuntimeByArtifact(entries, ref) {
23402
23466
  byJob.set(`escalated::${entry.artifactId}`, {
23403
23467
  artifactId: entry.artifactId,
23404
23468
  status: "escalated",
23405
- actor: ref(entry.to),
23469
+ actor: ref2(entry.to),
23406
23470
  finishedAt: entry.at,
23407
23471
  reason: entry.reason,
23408
23472
  at: entry.at
@@ -23431,7 +23495,7 @@ function buildRuntimeByArtifact(entries, ref) {
23431
23495
  function activitySummaryNote(note) {
23432
23496
  return note.length <= ACTIVITY_NOTE_MAX_CHARS ? note : `${note.slice(0, ACTIVITY_NOTE_MAX_CHARS)}\u2026\uFF08\u5DF2\u622A\u65AD\uFF0C\u539F\u6587 ${note.length} \u5B57\uFF0C\u5168\u6587\u89C1 oplog\uFF09`;
23433
23497
  }
23434
- function buildActivity(model, arts, ref) {
23498
+ function buildActivity(model, arts, ref2) {
23435
23499
  const events = [];
23436
23500
  for (const a of arts) {
23437
23501
  for (const r of revisionsOf(model, a.id)) {
@@ -23439,7 +23503,7 @@ function buildActivity(model, arts, ref) {
23439
23503
  events.push({
23440
23504
  seq: model.proposeSeq.get(r.id) ?? 0,
23441
23505
  at: r.createdAt,
23442
- actor: ref(r.author),
23506
+ actor: ref2(r.author),
23443
23507
  kind: "propose",
23444
23508
  artifactId: a.id,
23445
23509
  revisionId: r.id,
@@ -23452,7 +23516,7 @@ function buildActivity(model, arts, ref) {
23452
23516
  events.push({
23453
23517
  seq: vote.seq,
23454
23518
  at: vote.at,
23455
- actor: ref(vote.author),
23519
+ actor: ref2(vote.author),
23456
23520
  kind: vote.verdict === "approve" ? "review-approve" : "review-request-changes",
23457
23521
  artifactId: a.id,
23458
23522
  revisionId: r.id,
@@ -23464,7 +23528,7 @@ function buildActivity(model, arts, ref) {
23464
23528
  events.push({
23465
23529
  seq: m2.seq,
23466
23530
  at: m2.at,
23467
- actor: ref(m2.forced?.by ?? a.owner),
23531
+ actor: ref2(m2.forced?.by ?? a.owner),
23468
23532
  kind: "conclude",
23469
23533
  artifactId: a.id,
23470
23534
  revisionId: m2.head,
@@ -23475,7 +23539,7 @@ function buildActivity(model, arts, ref) {
23475
23539
  events.push({
23476
23540
  seq: 0,
23477
23541
  at: annotation.thread[0]?.ts ?? "",
23478
- actor: ref(annotation.author),
23542
+ actor: ref2(annotation.author),
23479
23543
  kind: "annotate",
23480
23544
  artifactId: a.id,
23481
23545
  summary: annotation.body.split("\n").find((line) => line.trim() && !line.startsWith("OASIS_PLANNING_ISSUES ")) ?? "\u6279\u6CE8"
@@ -23484,7 +23548,7 @@ function buildActivity(model, arts, ref) {
23484
23548
  }
23485
23549
  return events.sort((x2, y) => x2.at < y.at ? -1 : x2.at > y.at ? 1 : x2.seq - y.seq);
23486
23550
  }
23487
- function buildCoordinatorActivity(arts, ops, ref) {
23551
+ function buildCoordinatorActivity(arts, ops, ref2) {
23488
23552
  const inWorkspace = new Set(arts.map((a) => a.id));
23489
23553
  const managerRaw = arts.find((a) => a.type === "brief")?.fields?.["manager"];
23490
23554
  const managerActor = typeof managerRaw === "string" ? managerRaw : null;
@@ -23499,11 +23563,11 @@ function buildCoordinatorActivity(arts, ops, ref) {
23499
23563
  if ((kind === "spawn_artifact" || kind === "link_input") && (!firstRevisionAt || op.timestamp < firstRevisionAt)) {
23500
23564
  continue;
23501
23565
  }
23502
- const detail = coordinatorEditDetail(kind, op.payload, ref);
23566
+ const detail = coordinatorEditDetail(kind, op.payload, ref2);
23503
23567
  edits.push({
23504
23568
  seq: op.seq,
23505
23569
  at: op.timestamp,
23506
- actor: ref(op.actor),
23570
+ actor: ref2(op.actor),
23507
23571
  kind,
23508
23572
  artifactId: op.artifactId,
23509
23573
  label: COORDINATOR_EDIT_LABEL[kind],
@@ -23512,7 +23576,7 @@ function buildCoordinatorActivity(arts, ops, ref) {
23512
23576
  }
23513
23577
  return edits.sort((x2, y) => x2.at < y.at ? -1 : x2.at > y.at ? 1 : x2.seq - y.seq);
23514
23578
  }
23515
- function coordinatorEditDetail(kind, payload, ref) {
23579
+ function coordinatorEditDetail(kind, payload, ref2) {
23516
23580
  const str2 = (v2) => typeof v2 === "string" && v2.trim() ? v2 : void 0;
23517
23581
  switch (kind) {
23518
23582
  case "link_input":
@@ -23522,7 +23586,7 @@ function coordinatorEditDetail(kind, payload, ref) {
23522
23586
  return str2(payload.title) ?? str2(payload.type);
23523
23587
  case "assign_owner": {
23524
23588
  const owner = str2(payload.owner);
23525
- return owner ? ref(owner).name ?? owner : void 0;
23589
+ return owner ? ref2(owner).name ?? owner : void 0;
23526
23590
  }
23527
23591
  case "bump_pin": {
23528
23592
  const to = str2(payload.to);
@@ -25308,7 +25372,7 @@ async function startOasisServer(opts) {
25308
25372
  const chatStore = opts.chatSession;
25309
25373
  const ws = review.workspace ?? engine.kernel.model.artifacts.get(review.anchor)?.workspace ?? null;
25310
25374
  let target = review.origin ?? discussSessions.get(`draft:${review.draftId}`) ?? void 0;
25311
- let record5 = target && chatStore ? await chatStore.getSession(target).catch(() => null) : null;
25375
+ let record6 = target && chatStore ? await chatStore.getSession(target).catch(() => null) : null;
25312
25376
  if (!target && chatStore && ws) {
25313
25377
  const brief = [...engine.kernel.model.artifacts.values()].find((x2) => x2.type === "brief" && x2.workspace === ws);
25314
25378
  if (brief) {
@@ -25317,7 +25381,7 @@ async function startOasisServer(opts) {
25317
25381
  const wos = await chatStore.listWorkOrdersForSession(s2.id).catch(() => []);
25318
25382
  if (wos.includes(ws)) {
25319
25383
  target = s2.id;
25320
- record5 = s2;
25384
+ record6 = s2;
25321
25385
  break;
25322
25386
  }
25323
25387
  }
@@ -25328,7 +25392,7 @@ async function startOasisServer(opts) {
25328
25392
  if (chatStore) {
25329
25393
  await chatStore.appendMessage({ id: randomUUID18(), sessionId: target, role: "user", content: message, createdAt: (/* @__PURE__ */ new Date()).toISOString() }).catch(() => void 0);
25330
25394
  }
25331
- const rt = record5?.runtimeSessionId ?? opts.retainedSession?.({ draftId: review.draftId });
25395
+ const rt = record6?.runtimeSessionId ?? opts.retainedSession?.({ draftId: review.draftId });
25332
25396
  const session = await opts.dispatchChat({
25333
25397
  actorId: review.proposedBy,
25334
25398
  message,
@@ -25511,9 +25575,9 @@ async function startOasisServer(opts) {
25511
25575
  if (opts.workorderDrafts) {
25512
25576
  let ws = typeof workspace === "string" && workspace.trim() ? workspace.trim() : void 0;
25513
25577
  if (!ws) {
25514
- const ref = op.artifactId;
25515
- if (typeof ref === "string" && ref.startsWith("artifact:"))
25516
- ws = opts.workorderDrafts.list().find((d) => d.plan.ops.some((o) => o.action === "spawn" && o.id === ref))?.workspace;
25578
+ const ref2 = op.artifactId;
25579
+ if (typeof ref2 === "string" && ref2.startsWith("artifact:"))
25580
+ ws = opts.workorderDrafts.list().find((d) => d.plan.ops.some((o) => o.action === "spawn" && o.id === ref2))?.workspace;
25517
25581
  }
25518
25582
  const draft = ws ? opts.workorderDrafts.forWorkspace(ws) : void 0;
25519
25583
  if (draft) {
@@ -26574,14 +26638,14 @@ var init_tokens = __esm({
26574
26638
  };
26575
26639
  isTokenClaims = (value) => {
26576
26640
  if (value === null || typeof value !== "object") return false;
26577
- const record5 = value;
26578
- if (typeof record5["actor"] !== "string" || !record5["actor"].startsWith("actor:")) return false;
26579
- if (typeof record5["issuedAt"] !== "number" || !Number.isFinite(record5["issuedAt"])) return false;
26580
- if (record5["expiresAt"] !== void 0 && (typeof record5["expiresAt"] !== "number" || !Number.isFinite(record5["expiresAt"]))) return false;
26581
- if (record5["dispatchSeq"] !== void 0 && (typeof record5["dispatchSeq"] !== "number" || !Number.isFinite(record5["dispatchSeq"]))) return false;
26582
- if (record5["scopes"] !== void 0 && (!Array.isArray(record5["scopes"]) || record5["scopes"].some((scope) => typeof scope !== "string"))) return false;
26641
+ const record6 = value;
26642
+ if (typeof record6["actor"] !== "string" || !record6["actor"].startsWith("actor:")) return false;
26643
+ if (typeof record6["issuedAt"] !== "number" || !Number.isFinite(record6["issuedAt"])) return false;
26644
+ if (record6["expiresAt"] !== void 0 && (typeof record6["expiresAt"] !== "number" || !Number.isFinite(record6["expiresAt"]))) return false;
26645
+ if (record6["dispatchSeq"] !== void 0 && (typeof record6["dispatchSeq"] !== "number" || !Number.isFinite(record6["dispatchSeq"]))) return false;
26646
+ if (record6["scopes"] !== void 0 && (!Array.isArray(record6["scopes"]) || record6["scopes"].some((scope) => typeof scope !== "string"))) return false;
26583
26647
  for (const key of ["sessionId", "artifactId", "action", "nodeId", "runtimeKind", "companyId", "chatSessionId"]) {
26584
- if (record5[key] !== void 0 && typeof record5[key] !== "string") return false;
26648
+ if (record6[key] !== void 0 && typeof record6[key] !== "string") return false;
26585
26649
  }
26586
26650
  return true;
26587
26651
  };
@@ -27175,14 +27239,14 @@ var init_memory_trace_store = __esm({
27175
27239
  this.usageAggregates.delete(key);
27176
27240
  }
27177
27241
  }
27178
- let count = 0;
27242
+ let count2 = 0;
27179
27243
  for (const run of this.runs.values()) {
27180
27244
  if (run.usage == null) continue;
27181
27245
  if (run.startedAt < from || run.startedAt >= to) continue;
27182
27246
  await this.updateUsageAggregates(run);
27183
- count++;
27247
+ count2++;
27184
27248
  }
27185
- return count;
27249
+ return count2;
27186
27250
  }
27187
27251
  /** day 滚动:把 hourly 聚合(已存在)按日再汇总——内存版直接从 hourly 行重算 day 行。 */
27188
27252
  async rollupHourlyToDaily(day) {
@@ -27555,6 +27619,19 @@ var init_src3 = __esm({
27555
27619
  }
27556
27620
  });
27557
27621
 
27622
+ // ../contract/src/chat-session.ts
27623
+ function deriveLastTurnQuality(lastAssistant) {
27624
+ const status = lastAssistant?.status;
27625
+ if (status === void 0 || status === "running") return void 0;
27626
+ if (status === "error") return "abnormal";
27627
+ return lastAssistant && lastAssistant.content.trim().length > 0 ? "clean" : "abnormal";
27628
+ }
27629
+ var init_chat_session = __esm({
27630
+ "../contract/src/chat-session.ts"() {
27631
+ "use strict";
27632
+ }
27633
+ });
27634
+
27558
27635
  // ../server/src/domains/projects/projection.ts
27559
27636
  function decodeDocumentDescription(description) {
27560
27637
  if (description === void 0) return {};
@@ -28129,6 +28206,7 @@ var DEFAULT_AGENT_ACTOR, MemoryProjectStateStore, MemoryArtifactStateStore, Memo
28129
28206
  var init_service = __esm({
28130
28207
  "../server/src/domains/projects/service.ts"() {
28131
28208
  "use strict";
28209
+ init_src();
28132
28210
  init_src2();
28133
28211
  init_projection();
28134
28212
  init_workorders();
@@ -28792,9 +28870,9 @@ var init_service = __esm({
28792
28870
  ...input.revision.continuation ? { continuation: input.revision.continuation } : {}
28793
28871
  });
28794
28872
  await this.syncProjection();
28795
- const record5 = await this.artifacts.getRevision(kernelRevision.id);
28796
- if (!record5) throw new Error(`revision projection missing after register: ${kernelRevision.id}`);
28797
- return record5;
28873
+ const record6 = await this.artifacts.getRevision(kernelRevision.id);
28874
+ if (!record6) throw new Error(`revision projection missing after register: ${kernelRevision.id}`);
28875
+ return record6;
28798
28876
  }
28799
28877
  async approveArtifactRevision(input) {
28800
28878
  if (input.actorKind !== "human") throw namedError("AgentReviewForbidden", "agents cannot approve artifact revisions");
@@ -28897,9 +28975,9 @@ var init_service = __esm({
28897
28975
  ...input.revisionId ? { revisionId: input.revisionId } : {}
28898
28976
  });
28899
28977
  await this.syncProjection();
28900
- const record5 = await this.artifacts.getAnnotation(kernelAnnotation.id);
28901
- if (!record5) throw new Error(`annotation projection missing after create: ${kernelAnnotation.id}`);
28902
- return record5;
28978
+ const record6 = await this.artifacts.getAnnotation(kernelAnnotation.id);
28979
+ if (!record6) throw new Error(`annotation projection missing after create: ${kernelAnnotation.id}`);
28980
+ return record6;
28903
28981
  }
28904
28982
  async resolveArtifactAnnotation(input) {
28905
28983
  const artifact = await this.artifacts.getArtifact(input.artifactId);
@@ -28915,11 +28993,16 @@ var init_service = __esm({
28915
28993
  ...input.comment?.trim() ? { note: input.comment.trim() } : {}
28916
28994
  });
28917
28995
  await this.syncProjection();
28918
- const record5 = await this.artifacts.getAnnotation(input.annotationId);
28919
- if (!record5) throw new Error(`annotation projection missing after resolve: ${input.annotationId}`);
28920
- return record5;
28996
+ const record6 = await this.artifacts.getAnnotation(input.annotationId);
28997
+ if (!record6) throw new Error(`annotation projection missing after resolve: ${input.annotationId}`);
28998
+ return record6;
28921
28999
  }
28922
29000
  async registerNodeOutput(input) {
29001
+ const status = input.status ?? "completed";
29002
+ const qualityMetrics = parseWorkorderQualityMetricsPayload(input.payload);
29003
+ if (qualityMetrics && status !== "completed") {
29004
+ throw new Error("invalid qa_quality_metrics payload: quality metrics require status=completed");
29005
+ }
28923
29006
  await this.assertProjectExecutable(input.projectId);
28924
29007
  if (!input.outputId.trim()) throw new Error("output_id is required");
28925
29008
  if (!input.workOrderId.trim()) throw new Error("work_order_id is required");
@@ -28933,7 +29016,7 @@ var init_service = __esm({
28933
29016
  workOrderId: input.workOrderId,
28934
29017
  nodeId: input.nodeId,
28935
29018
  projectId: input.projectId,
28936
- status: input.status ?? "completed",
29019
+ status,
28937
29020
  documents,
28938
29021
  ...input.error ? { error: input.error } : {},
28939
29022
  payload: { ...input.payload ?? {} },
@@ -29155,6 +29238,7 @@ var init_dev_store = __esm({
29155
29238
  path4 = __toESM(require("node:path"), 1);
29156
29239
  init_src();
29157
29240
  init_src3();
29241
+ init_chat_session();
29158
29242
  init_src3();
29159
29243
  init_service();
29160
29244
  NdjsonOplogStore = class _NdjsonOplogStore {
@@ -29577,7 +29661,13 @@ var init_dev_store = __esm({
29577
29661
  this.sessions.set(s2.id, s2);
29578
29662
  }
29579
29663
  async listSessions(humanActorId) {
29580
- return [...this.sessions.values()].filter((s2) => s2.humanActorId === humanActorId).sort((a, b2) => b2.touchedAt.localeCompare(a.touchedAt));
29664
+ return [...this.sessions.values()].filter((s2) => s2.humanActorId === humanActorId).sort((a, b2) => b2.touchedAt.localeCompare(a.touchedAt)).map((s2) => {
29665
+ const msgs = this.messages.get(s2.id) ?? [];
29666
+ let lastAssistant;
29667
+ for (const m2 of msgs) if (m2.role === "assistant" && (!lastAssistant || m2.seq > lastAssistant.seq)) lastAssistant = m2;
29668
+ const quality = deriveLastTurnQuality(lastAssistant);
29669
+ return quality ? { ...s2, lastTurnQuality: quality } : s2;
29670
+ });
29581
29671
  }
29582
29672
  async getSession(id) {
29583
29673
  return this.sessions.get(id) ?? null;
@@ -29594,10 +29684,10 @@ var init_dev_store = __esm({
29594
29684
  async appendMessage(m2) {
29595
29685
  const list = this.messages.get(m2.sessionId) ?? [];
29596
29686
  const seq = (list.length ? Math.max(...list.map((x2) => x2.seq)) : 0) + 1;
29597
- const record5 = { ...m2, seq };
29598
- list.push(record5);
29687
+ const record6 = { ...m2, seq };
29688
+ list.push(record6);
29599
29689
  this.messages.set(m2.sessionId, list);
29600
- return record5;
29690
+ return record6;
29601
29691
  }
29602
29692
  async updateMessage(id, patch) {
29603
29693
  for (const list of this.messages.values()) {
@@ -29655,9 +29745,9 @@ var init_dev_store = __esm({
29655
29745
  this.save();
29656
29746
  }
29657
29747
  async appendMessage(m2) {
29658
- const record5 = await super.appendMessage(m2);
29748
+ const record6 = await super.appendMessage(m2);
29659
29749
  this.save();
29660
- return record5;
29750
+ return record6;
29661
29751
  }
29662
29752
  async updateMessage(id, patch) {
29663
29753
  await super.updateMessage(id, patch);
@@ -34348,19 +34438,19 @@ var init_service2 = __esm({
34348
34438
  async upsertActor(a, by) {
34349
34439
  const existing = await this.opts.store.getActor(a.id);
34350
34440
  const roles = a.roles ?? existing?.roles ?? [];
34351
- const record5 = { ...a, roles, createdAt: existing?.createdAt ?? a.createdAt ?? this.now() };
34352
- if (isActiveCoordinatorAgent(record5)) {
34353
- const existingCoordinator = (await this.opts.store.listActors({ kind: "agent", status: "active" })).find((actor) => actor.id !== record5.id && isActiveCoordinatorAgent(actor));
34441
+ const record6 = { ...a, roles, createdAt: existing?.createdAt ?? a.createdAt ?? this.now() };
34442
+ if (isActiveCoordinatorAgent(record6)) {
34443
+ const existingCoordinator = (await this.opts.store.listActors({ kind: "agent", status: "active" })).find((actor) => actor.id !== record6.id && isActiveCoordinatorAgent(actor));
34354
34444
  if (existingCoordinator) {
34355
34445
  throw new Error(
34356
- `\u7CFB\u7EDF\u53EA\u80FD\u6709\u4E00\u4E2A\u534F\u8C03\u8005\u667A\u80FD\u4F53\uFF1A\u5DF2\u5B58\u5728 ${existingCoordinator.name}\uFF08${existingCoordinator.id}\uFF09\uFF0C\u4E0D\u80FD\u518D\u521B\u5EFA\u6216\u542F\u7528 ${record5.name}\uFF08${record5.id}\uFF09\u3002`
34446
+ `\u7CFB\u7EDF\u53EA\u80FD\u6709\u4E00\u4E2A\u534F\u8C03\u8005\u667A\u80FD\u4F53\uFF1A\u5DF2\u5B58\u5728 ${existingCoordinator.name}\uFF08${existingCoordinator.id}\uFF09\uFF0C\u4E0D\u80FD\u518D\u521B\u5EFA\u6216\u542F\u7528 ${record6.name}\uFF08${record6.id}\uFF09\u3002`
34357
34447
  );
34358
34448
  }
34359
34449
  }
34360
- await this.opts.store.upsertActor(record5);
34361
- this.opts.onRolesChanged?.(record5.id, record5.status === "active" ? roles : []);
34450
+ await this.opts.store.upsertActor(record6);
34451
+ this.opts.onRolesChanged?.(record6.id, record6.status === "active" ? roles : []);
34362
34452
  await this.audit({ kind: "actor_upsert", actorId: a.id, by, at: this.now(), detail: { status: a.status, roles } });
34363
- return record5;
34453
+ return record6;
34364
34454
  }
34365
34455
  /** 删除即停用(2.1 完成标准) */
34366
34456
  async disableActor(id, by) {
@@ -34372,21 +34462,21 @@ var init_service2 = __esm({
34372
34462
  return this.opts.store.getActor(id);
34373
34463
  }
34374
34464
  /** 设置/清除头像引用("blob:<哈希>";null = 回到默认生成的插画头像) */
34375
- async setActorAvatar(id, ref, by) {
34465
+ async setActorAvatar(id, ref2, by) {
34376
34466
  const a = await this.opts.store.getActor(id);
34377
34467
  if (!a) throw new Error(`actor not found: ${id}`);
34378
34468
  const { avatar: _drop, ...rest } = a;
34379
- const record5 = ref === null ? rest : { ...rest, avatar: ref };
34380
- await this.opts.store.upsertActor(record5);
34381
- await this.audit({ kind: "actor_upsert", actorId: id, by, at: this.now(), detail: { avatar: ref ?? "cleared" } });
34382
- return record5;
34469
+ const record6 = ref2 === null ? rest : { ...rest, avatar: ref2 };
34470
+ await this.opts.store.upsertActor(record6);
34471
+ await this.audit({ kind: "actor_upsert", actorId: id, by, at: this.now(), detail: { avatar: ref2 ?? "cleared" } });
34472
+ return record6;
34383
34473
  }
34384
34474
  /** 设置/清除团队图标引用(同头像约定;不接受 emoji,只接受 blob 引用) */
34385
- async setTeamIcon(teamId, ref) {
34475
+ async setTeamIcon(teamId, ref2) {
34386
34476
  const t = (await this.opts.store.listTeams()).find((x2) => x2.id === teamId);
34387
34477
  if (!t) throw new Error(`team not found: ${teamId}`);
34388
34478
  const { icon: _drop, ...rest } = t;
34389
- await this.opts.store.upsertTeam(ref === null ? rest : { ...rest, icon: ref });
34479
+ await this.opts.store.upsertTeam(ref2 === null ? rest : { ...rest, icon: ref2 });
34390
34480
  }
34391
34481
  listActors(filter) {
34392
34482
  return this.opts.store.listActors(filter);
@@ -34792,13 +34882,13 @@ ${input.description}
34792
34882
  this.opts.store.listConnectors()
34793
34883
  ]);
34794
34884
  const globalConnected = new Set(connectors.filter((c) => c.status === "connected").map((c) => c.id));
34795
- const record5 = new Map(connections.map((c) => [c.connectorId, c.enabled]));
34885
+ const record6 = new Map(connections.map((c) => [c.connectorId, c.enabled]));
34796
34886
  const legacy = new Set(config2?.connectorIds ?? []);
34797
- const ids = /* @__PURE__ */ new Set([...record5.keys(), ...legacy, ...globalConnected]);
34887
+ const ids = /* @__PURE__ */ new Set([...record6.keys(), ...legacy, ...globalConnected]);
34798
34888
  const effective = /* @__PURE__ */ new Set();
34799
34889
  for (const id of ids) {
34800
- if (record5.has(id)) {
34801
- if (record5.get(id)) effective.add(id);
34890
+ if (record6.has(id)) {
34891
+ if (record6.get(id)) effective.add(id);
34802
34892
  } else if (legacy.has(id)) effective.add(id);
34803
34893
  else if (globalConnected.has(id)) effective.add(id);
34804
34894
  }
@@ -35699,8 +35789,8 @@ function actorsDomain(opts) {
35699
35789
  router.post("/api/actors/:id/avatar", async (req) => {
35700
35790
  const { service, blobs } = await resolveCtx(req.auth.companyId);
35701
35791
  if (!blobs) throw new ApiError(501, "NOT_IMPLEMENTED", "blob \u5B58\u50A8\u672A\u63A5\u5165");
35702
- const ref = await storeImageBlob(blobs, req.body?.data);
35703
- const actor = await service.setActorAvatar(req.params.id, ref, req.auth.actor);
35792
+ const ref2 = await storeImageBlob(blobs, req.body?.data);
35793
+ const actor = await service.setActorAvatar(req.params.id, ref2, req.auth.actor);
35704
35794
  return { status: 201, body: { avatar: actor.avatar } };
35705
35795
  });
35706
35796
  router.delete("/api/actors/:id/avatar", async (req) => {
@@ -35711,9 +35801,9 @@ function actorsDomain(opts) {
35711
35801
  router.post("/api/teams/:id/icon", async (req) => {
35712
35802
  const { service, blobs } = await resolveCtx(req.auth.companyId);
35713
35803
  if (!blobs) throw new ApiError(501, "NOT_IMPLEMENTED", "blob \u5B58\u50A8\u672A\u63A5\u5165");
35714
- const ref = await storeImageBlob(blobs, req.body?.data);
35715
- await service.setTeamIcon(req.params.id, ref);
35716
- return { status: 201, body: { icon: ref } };
35804
+ const ref2 = await storeImageBlob(blobs, req.body?.data);
35805
+ await service.setTeamIcon(req.params.id, ref2);
35806
+ return { status: 201, body: { icon: ref2 } };
35717
35807
  });
35718
35808
  router.delete("/api/teams/:id/icon", async (req) => {
35719
35809
  const { service } = await resolveCtx(req.auth.companyId);
@@ -36567,6 +36657,9 @@ function parseResolveArtifactAnnotation(req) {
36567
36657
  };
36568
36658
  }
36569
36659
  function mapProjectError(err) {
36660
+ if (err instanceof Error && err.message.startsWith("invalid qa_quality_metrics payload:")) {
36661
+ return new ApiError(400, "INVALID_QA_QUALITY_METRICS", err.message);
36662
+ }
36570
36663
  if (err instanceof Error && err.name === "ProjectDocumentSystemNotReady") {
36571
36664
  return new ApiError(409, "PROJECT_DOCUMENT_SYSTEM_NOT_READY", err.message);
36572
36665
  }
@@ -37011,10 +37104,10 @@ var init_service3 = __esm({
37011
37104
  return this.store.getCompany(id);
37012
37105
  }
37013
37106
  /** 设置/清除公司头像引用("blob:<哈希>";null = 回到默认首字母标识)。 */
37014
- async setAvatar(id, ref) {
37107
+ async setAvatar(id, ref2) {
37015
37108
  const company = await this.requireCompany(id);
37016
- await this.store.updateCompany(id, { avatar: ref });
37017
- const next = ref === null ? (({ avatar: _drop, ...rest }) => rest)(company) : { ...company, avatar: ref };
37109
+ await this.store.updateCompany(id, { avatar: ref2 });
37110
+ const next = ref2 === null ? (({ avatar: _drop, ...rest }) => rest)(company) : { ...company, avatar: ref2 };
37018
37111
  return next;
37019
37112
  }
37020
37113
  /**
@@ -37252,8 +37345,8 @@ function companiesDomain(opts) {
37252
37345
  });
37253
37346
  router.post("/api/companies/:id/avatar", async (req) => {
37254
37347
  if (!blobs) throw new ApiError(501, "NOT_IMPLEMENTED", "blob \u5B58\u50A8\u672A\u63A5\u5165");
37255
- const ref = await storeImageBlob(blobs, req.body?.data);
37256
- const company = await service.setAvatar(req.params.id, ref).catch(mapErr);
37348
+ const ref2 = await storeImageBlob(blobs, req.body?.data);
37349
+ const company = await service.setAvatar(req.params.id, ref2).catch(mapErr);
37257
37350
  return { status: 201, body: { avatar: company.avatar } };
37258
37351
  });
37259
37352
  router.delete("/api/companies/:id/avatar", async (req) => {
@@ -39050,13 +39143,13 @@ function scanCodexTelemetry(workdir, sinceMs, sessionsRoot = codexSessionsRoot()
39050
39143
  function createCodexNormalizeState() {
39051
39144
  return { toolUseIds: /* @__PURE__ */ new Set(), previousAgentMessage: false, lastAgentMessageEndedWithNewline: false };
39052
39145
  }
39053
- function record2(value) {
39146
+ function record3(value) {
39054
39147
  return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
39055
39148
  }
39056
39149
  function textOf3(value) {
39057
39150
  if (typeof value === "string") return value;
39058
39151
  if (Array.isArray(value)) return value.map(textOf3).filter(Boolean).join("\n");
39059
- const obj = record2(value);
39152
+ const obj = record3(value);
39060
39153
  if (!obj) return void 0;
39061
39154
  if (typeof obj.text === "string") return obj.text;
39062
39155
  if (typeof obj.content === "string") return obj.content;
@@ -39120,7 +39213,7 @@ ${text}` : text;
39120
39213
  resetAgentMessageBoundary(state);
39121
39214
  const id = item.id;
39122
39215
  const name = typeof item.name === "string" ? item.name : "mcp_tool_call";
39123
- const input = record2(item.arguments) ?? record2(item.input) ?? {};
39216
+ const input = record3(item.arguments) ?? record3(item.input) ?? {};
39124
39217
  const events = toolUseOnce(state, id, name, input);
39125
39218
  if (phase === "completed" || phase === "direct") {
39126
39219
  events.push({
@@ -39165,7 +39258,7 @@ function normalizeCodexStreamLine(line, state = createCodexNormalizeState()) {
39165
39258
  } catch {
39166
39259
  return line ? [{ kind: "message", payload: { text: line }, outputText: line }] : [];
39167
39260
  }
39168
- const item = record2(obj.item);
39261
+ const item = record3(obj.item);
39169
39262
  if (obj.type === "item.started" && item) return normalizeCodexItem(item, "started", state);
39170
39263
  if (obj.type === "item.completed" && item) return normalizeCodexItem(item, "completed", state);
39171
39264
  if (typeof obj.type === "string") return normalizeCodexItem(obj, "direct", state);
@@ -39424,7 +39517,7 @@ function addToken(acc, value, field) {
39424
39517
  acc[field] += value;
39425
39518
  }
39426
39519
  }
39427
- function record3(value) {
39520
+ function record4(value) {
39428
39521
  return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
39429
39522
  }
39430
39523
  function firstNumber(src, keys) {
@@ -39486,23 +39579,23 @@ function accumulateTokenFields(acc, src) {
39486
39579
  "cache_write_tokens",
39487
39580
  "cacheWriteTokens"
39488
39581
  ], "cacheCreationTokens") || changed;
39489
- const promptDetails = record3(src["prompt_tokens_details"]) ?? record3(src["promptTokensDetails"]);
39582
+ const promptDetails = record4(src["prompt_tokens_details"]) ?? record4(src["promptTokensDetails"]);
39490
39583
  if (promptDetails) {
39491
39584
  changed = addFirstToken(acc, promptDetails, ["cached_tokens", "cachedTokens"], "cacheReadTokens") || changed;
39492
39585
  }
39493
39586
  return changed;
39494
39587
  }
39495
39588
  function accumulateUsage(acc, value) {
39496
- const root = record3(value);
39589
+ const root = record4(value);
39497
39590
  if (!root) return false;
39498
39591
  const candidates = [
39499
39592
  root,
39500
- record3(root["usage"]),
39501
- record3(root["token_usage"]),
39502
- record3(root["tokenUsage"]),
39503
- record3(root["tokens"]),
39504
- record3(root["usageMetadata"]),
39505
- record3(root["usage_metadata"])
39593
+ record4(root["usage"]),
39594
+ record4(root["token_usage"]),
39595
+ record4(root["tokenUsage"]),
39596
+ record4(root["tokens"]),
39597
+ record4(root["usageMetadata"]),
39598
+ record4(root["usage_metadata"])
39506
39599
  ];
39507
39600
  const seen = /* @__PURE__ */ new Set();
39508
39601
  let changed = false;
@@ -39694,7 +39787,7 @@ var init_pricing = __esm({
39694
39787
  });
39695
39788
 
39696
39789
  // ../adapters/src/_core/acp.ts
39697
- function record4(value) {
39790
+ function record5(value) {
39698
39791
  return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
39699
39792
  }
39700
39793
  function firstString(...values) {
@@ -39709,11 +39802,11 @@ function textFromUnknown(value) {
39709
39802
  const parts = value.map(textFromUnknown).filter((x2) => Boolean(x2));
39710
39803
  return parts.length ? parts.join("") : void 0;
39711
39804
  }
39712
- const obj = record4(value);
39805
+ const obj = record5(value);
39713
39806
  if (!obj) return void 0;
39714
- const direct = firstString(obj["text"], obj["delta"], obj["message"], record4(obj["error"])?.["message"]);
39807
+ const direct = firstString(obj["text"], obj["delta"], obj["message"], record5(obj["error"])?.["message"]);
39715
39808
  if (direct) return direct;
39716
- return textFromUnknown(obj["content"]) ?? textFromUnknown(record4(obj["result"])?.["content"]) ?? textFromUnknown(obj["result"]);
39809
+ return textFromUnknown(obj["content"]) ?? textFromUnknown(record5(obj["result"])?.["content"]) ?? textFromUnknown(obj["result"]);
39717
39810
  }
39718
39811
  function jsonLike(value) {
39719
39812
  if (typeof value !== "string") return value;
@@ -39728,15 +39821,15 @@ function jsonLike(value) {
39728
39821
  return { text: value };
39729
39822
  }
39730
39823
  function toolPayload(data) {
39731
- const d = record4(data) ?? {};
39732
- const nested = record4(d["toolCall"]) ?? record4(d["tool_call"]) ?? record4(d["call"]) ?? record4(d["tool"]) ?? record4(d["data"]) ?? {};
39824
+ const d = record5(data) ?? {};
39825
+ const nested = record5(d["toolCall"]) ?? record5(d["tool_call"]) ?? record5(d["call"]) ?? record5(d["tool"]) ?? record5(d["data"]) ?? {};
39733
39826
  return { ...nested, ...d };
39734
39827
  }
39735
39828
  function toolCallIdOf(d) {
39736
39829
  return firstString(d["toolCallId"], d["tool_call_id"], d["callId"], d["call_id"], d["id"]);
39737
39830
  }
39738
39831
  function toolNameOf(d) {
39739
- return firstString(d["name"], d["toolName"], d["tool_name"], record4(d["tool"])?.["name"]) ?? toolNameFromTitle(firstString(d["title"]) ?? "", firstString(d["kind"]) ?? "");
39832
+ return firstString(d["name"], d["toolName"], d["tool_name"], record5(d["tool"])?.["name"]) ?? toolNameFromTitle(firstString(d["title"]) ?? "", firstString(d["kind"]) ?? "");
39740
39833
  }
39741
39834
  function inputFromTitle(title, toolName) {
39742
39835
  const colon = title.indexOf(":");
@@ -39778,7 +39871,7 @@ function argsTextOf(d) {
39778
39871
  return typeof value === "string" ? value : void 0;
39779
39872
  }
39780
39873
  function toolOutputOf(d) {
39781
- const error2 = record4(d["error"]);
39874
+ const error2 = record5(d["error"]);
39782
39875
  if (error2) return error2["message"] ?? error2;
39783
39876
  const raw = d["rawOutput"] ?? d["raw_output"] ?? d["output"] ?? d["result"] ?? d["results"] ?? d["response"] ?? d["data"] ?? d["content"];
39784
39877
  const stream = compactRecord({
@@ -39816,7 +39909,7 @@ function parseJsonString(value) {
39816
39909
  function locationsOf(d) {
39817
39910
  const locations = d["locations"];
39818
39911
  if (!Array.isArray(locations)) return void 0;
39819
- const out = locations.filter((item) => Boolean(record4(item)));
39912
+ const out = locations.filter((item) => Boolean(record5(item)));
39820
39913
  return out.length ? out : void 0;
39821
39914
  }
39822
39915
  function statusOf(d) {
@@ -39921,8 +40014,8 @@ function extractSessionID(result) {
39921
40014
  return result?.sessionId ?? "";
39922
40015
  }
39923
40016
  function extractCurrentModelID(result) {
39924
- const r = record4(result);
39925
- const models = record4(r?.["models"]);
40017
+ const r = record5(result);
40018
+ const models = record5(r?.["models"]);
39926
40019
  return firstString(
39927
40020
  models?.["currentModelId"],
39928
40021
  models?.["current_model_id"],
@@ -40380,11 +40473,11 @@ var init_acp = __esm({
40380
40473
  this.flushTextBuffer("message");
40381
40474
  }
40382
40475
  handleAgentMessage(data) {
40383
- const text = textFromUnknown(record4(data)?.["content"] ?? data);
40476
+ const text = textFromUnknown(record5(data)?.["content"] ?? data);
40384
40477
  if (text) this.appendText("message", text);
40385
40478
  }
40386
40479
  handleAgentThought(data) {
40387
- const text = textFromUnknown(record4(data)?.["content"] ?? data);
40480
+ const text = textFromUnknown(record5(data)?.["content"] ?? data);
40388
40481
  if (text) this.appendText("thought", text);
40389
40482
  }
40390
40483
  handleToolCallStart(data) {
@@ -42427,6 +42520,207 @@ var init_dashboard = __esm({
42427
42520
  }
42428
42521
  });
42429
42522
 
42523
+ // ../server/src/domains/collab/workorder-metrics.ts
42524
+ function rate(passed, total, source) {
42525
+ return { passed, total, rate: total > 0 ? passed / total : null, source };
42526
+ }
42527
+ function ref(actorId, resolveActor) {
42528
+ const extra = resolveActor?.(actorId);
42529
+ return {
42530
+ id: actorId,
42531
+ ...extra?.name ? { name: extra.name } : {},
42532
+ ...extra?.role ? { role: extra.role } : {},
42533
+ ...extra?.avatar ? { avatar: extra.avatar } : {}
42534
+ };
42535
+ }
42536
+ function firstReviewPassRate(model, artifactIds) {
42537
+ let passed = 0;
42538
+ let total = 0;
42539
+ for (const artifactId of artifactIds) {
42540
+ const first = (model.concludeAttempts.get(artifactId) ?? []).find((attempt) => attempt.gate !== null);
42541
+ if (!first) continue;
42542
+ total += 1;
42543
+ if (attemptStatus(model, first) === "satisfied") passed += 1;
42544
+ }
42545
+ return rate(passed, total, "oplog");
42546
+ }
42547
+ function qualitySnapshot(outputs) {
42548
+ const completed = outputs.filter((output) => output.status === "completed").sort((a, b2) => b2.updatedAt.localeCompare(a.updatedAt) || b2.outputId.localeCompare(a.outputId));
42549
+ for (const output of completed) {
42550
+ try {
42551
+ const payload = parseWorkorderQualityMetricsPayload(output.payload);
42552
+ if (!payload) continue;
42553
+ return {
42554
+ source: "qa",
42555
+ schemaVersion: 1,
42556
+ suiteRunId: payload.suiteRunId,
42557
+ ...payload.checklistRef ? { checklistRef: payload.checklistRef } : {},
42558
+ reportedAt: output.updatedAt,
42559
+ functionalCoverage: rate(payload.functionalCoverage.passed, payload.functionalCoverage.total, "qa"),
42560
+ p0Tests: {
42561
+ ...rate(payload.p0Tests.passed, payload.p0Tests.total, "qa"),
42562
+ failed: payload.p0Tests.failed,
42563
+ blocked: payload.p0Tests.blocked
42564
+ },
42565
+ p1Tests: {
42566
+ ...rate(payload.p1Tests.passed, payload.p1Tests.total, "qa"),
42567
+ failed: payload.p1Tests.failed,
42568
+ blocked: payload.p1Tests.blocked
42569
+ }
42570
+ };
42571
+ } catch {
42572
+ }
42573
+ }
42574
+ return null;
42575
+ }
42576
+ function earliestIso(values) {
42577
+ let earliest = null;
42578
+ for (const raw of values) {
42579
+ if (!raw) continue;
42580
+ const time3 = Date.parse(raw);
42581
+ if (!Number.isFinite(time3)) continue;
42582
+ if (!earliest || time3 < earliest.time) earliest = { raw, time: time3 };
42583
+ }
42584
+ return earliest?.raw ?? null;
42585
+ }
42586
+ function latestIso(values) {
42587
+ let latest = null;
42588
+ for (const raw of values) {
42589
+ if (!raw) continue;
42590
+ const time3 = Date.parse(raw);
42591
+ if (!Number.isFinite(time3)) continue;
42592
+ if (!latest || time3 > latest.time) latest = { raw, time: time3 };
42593
+ }
42594
+ return latest?.raw ?? null;
42595
+ }
42596
+ function journalIdentity(entry) {
42597
+ return entry.sessionId ?? entry.dispatchId;
42598
+ }
42599
+ function executionMetrics(journal, artifactIds, resolveActor, nowMs) {
42600
+ const sessions = /* @__PURE__ */ new Map();
42601
+ const activeByJob = /* @__PURE__ */ new Map();
42602
+ let fallbackSeq = 0;
42603
+ for (const entry of journal) {
42604
+ if (!("artifactId" in entry) || !artifactIds.has(entry.artifactId)) continue;
42605
+ if (entry.kind !== "dispatched" && entry.kind !== "recovered" && entry.kind !== "exited") continue;
42606
+ const identity = journalIdentity(entry);
42607
+ const active = activeByJob.get(entry.jobKey);
42608
+ const key = (identity && sessions.has(identity) ? identity : active) ?? identity ?? `${entry.jobKey}#${fallbackSeq++}`;
42609
+ const previous = sessions.get(key);
42610
+ if (entry.kind === "dispatched") {
42611
+ sessions.set(key, {
42612
+ key,
42613
+ artifactId: entry.artifactId,
42614
+ actor: entry.actor,
42615
+ startedAt: entry.at,
42616
+ failed: false
42617
+ });
42618
+ activeByJob.set(entry.jobKey, key);
42619
+ } else if (entry.kind === "recovered") {
42620
+ sessions.set(key, {
42621
+ key,
42622
+ artifactId: entry.artifactId,
42623
+ actor: entry.actor,
42624
+ startedAt: previous?.startedAt ?? entry.at,
42625
+ durationMs: previous?.durationMs,
42626
+ failed: previous?.failed ?? false
42627
+ });
42628
+ activeByJob.set(entry.jobKey, key);
42629
+ } else {
42630
+ sessions.set(key, {
42631
+ key,
42632
+ artifactId: entry.artifactId,
42633
+ actor: entry.actor,
42634
+ startedAt: previous?.startedAt,
42635
+ durationMs: entry.durationMs,
42636
+ failed: !entry.progressed
42637
+ });
42638
+ activeByJob.delete(entry.jobKey);
42639
+ }
42640
+ }
42641
+ const actorTotals = /* @__PURE__ */ new Map();
42642
+ let executionDurationMs = 0;
42643
+ let executionFailures = 0;
42644
+ for (const session of sessions.values()) {
42645
+ const started = session.startedAt ? Date.parse(session.startedAt) : Number.NaN;
42646
+ const duration3 = session.durationMs ?? (Number.isFinite(started) ? Math.max(0, nowMs - started) : 0);
42647
+ executionDurationMs += duration3;
42648
+ if (session.failed) executionFailures += 1;
42649
+ const current = actorTotals.get(session.actor) ?? { sessionCount: 0, executionDurationMs: 0 };
42650
+ current.sessionCount += 1;
42651
+ current.executionDurationMs += duration3;
42652
+ actorTotals.set(session.actor, current);
42653
+ }
42654
+ const byActor = [...actorTotals.entries()].map(([actor, totals]) => ({ actor: ref(actor, resolveActor), ...totals })).sort((a, b2) => b2.executionDurationMs - a.executionDurationMs || a.actor.id.localeCompare(b2.actor.id));
42655
+ return { sessionCount: sessions.size, executionDurationMs, byActor, executionFailures };
42656
+ }
42657
+ function workorderDuration(ops, journal, artifactIds) {
42658
+ const createdAt = earliestIso(
42659
+ ops.filter((op) => op.kind === "spawn_artifact" && artifactIds.has(op.artifactId)).map((op) => op.timestamp)
42660
+ );
42661
+ const latestExecutionFinishedAt = latestIso(
42662
+ journal.filter((entry) => entry.kind === "exited" && artifactIds.has(entry.artifactId)).map((entry) => entry.at)
42663
+ );
42664
+ const createdMs = createdAt ? Date.parse(createdAt) : Number.NaN;
42665
+ const finishedMs = latestExecutionFinishedAt ? Date.parse(latestExecutionFinishedAt) : Number.NaN;
42666
+ return {
42667
+ createdAt,
42668
+ latestExecutionFinishedAt,
42669
+ durationMs: Number.isFinite(createdMs) && Number.isFinite(finishedMs) ? Math.max(0, finishedMs - createdMs) : null
42670
+ };
42671
+ }
42672
+ function downstreamAnnotationCount(model, artifactIds) {
42673
+ let total = 0;
42674
+ for (const annotation of model.annotations.values()) {
42675
+ if (!annotation.raisedFrom || !artifactIds.has(annotation.raisedFrom)) continue;
42676
+ const target = annotation.anchor.target;
42677
+ const targetArtifact = model.artifacts.has(target) ? target : model.revisions.get(target)?.artifactId;
42678
+ if (targetArtifact && artifactIds.has(targetArtifact)) total += 1;
42679
+ }
42680
+ return total;
42681
+ }
42682
+ function reportedGapCount(model, artifactIds) {
42683
+ let total = 0;
42684
+ for (const artifactId of artifactIds) total += (model.gaps.get(artifactId) ?? []).length;
42685
+ return total;
42686
+ }
42687
+ function buildWorkorderMetrics(input) {
42688
+ const nowMs = input.nowMs ?? Date.now();
42689
+ return input.workorders.map((workorder) => {
42690
+ const artifactIds = new Set(
42691
+ [...input.model.artifacts.values()].filter((artifact) => artifact.workspace === workorder.id).map((artifact) => artifact.id)
42692
+ );
42693
+ const execution = executionMetrics(input.dispatchJournal, artifactIds, input.resolveActor, nowMs);
42694
+ const reportedGaps = reportedGapCount(input.model, artifactIds);
42695
+ return {
42696
+ workorder,
42697
+ sessionCount: execution.sessionCount,
42698
+ executionDurationMs: execution.executionDurationMs,
42699
+ workorderDuration: workorderDuration(
42700
+ input.opsByWorkorder?.get(workorder.id) ?? [],
42701
+ input.dispatchJournal,
42702
+ artifactIds
42703
+ ),
42704
+ byActor: execution.byActor,
42705
+ firstReviewPassRate: firstReviewPassRate(input.model, artifactIds),
42706
+ qualityMetrics: qualitySnapshot(input.nodeOutputsByWorkorder?.get(workorder.id) ?? []),
42707
+ annotationCount: downstreamAnnotationCount(input.model, artifactIds),
42708
+ blockage: {
42709
+ total: execution.executionFailures + reportedGaps,
42710
+ executionFailures: execution.executionFailures,
42711
+ reportedGaps
42712
+ }
42713
+ };
42714
+ });
42715
+ }
42716
+ var init_workorder_metrics = __esm({
42717
+ "../server/src/domains/collab/workorder-metrics.ts"() {
42718
+ "use strict";
42719
+ init_src2();
42720
+ init_src();
42721
+ }
42722
+ });
42723
+
42430
42724
  // ../server/src/domains/collab/organization-usage.ts
42431
42725
  function emptyUsage() {
42432
42726
  return {
@@ -42672,6 +42966,43 @@ function collabDomain(opts) {
42672
42966
  const dispatchPausedOf = await buildDispatchPausedResolver(artifacts);
42673
42967
  return { status: 200, body: { items: buildWorkorderSummaries(kernel.model, resolve5, resolveProject, dispatchPausedOf) } };
42674
42968
  });
42969
+ router.get("/api/workorder-metrics", async (req) => {
42970
+ const { kernel, oplog, registry: registry2, artifacts } = await resolveCtx(req.auth.companyId);
42971
+ const resolve5 = await buildResolver(registry2);
42972
+ const resolveProject = await buildProjectResolver(artifacts);
42973
+ const dispatchPausedOf = await buildDispatchPausedResolver(artifacts);
42974
+ const workorders = buildWorkorderSummaries(kernel.model, resolve5, resolveProject, dispatchPausedOf);
42975
+ const nodeOutputsByWorkorder = /* @__PURE__ */ new Map();
42976
+ const artifactIdsByWorkorder = /* @__PURE__ */ new Map();
42977
+ for (const artifact of kernel.model.artifacts.values()) {
42978
+ const ids = artifactIdsByWorkorder.get(artifact.workspace) ?? [];
42979
+ ids.push(artifact.id);
42980
+ artifactIdsByWorkorder.set(artifact.workspace, ids);
42981
+ }
42982
+ const opsByWorkorder = /* @__PURE__ */ new Map();
42983
+ await Promise.all(workorders.map(async (workorder) => {
42984
+ const artifactIds = artifactIdsByWorkorder.get(workorder.id) ?? [];
42985
+ const [nodeOutputs, opGroups] = await Promise.all([
42986
+ artifacts ? artifacts.listNodeOutputs({ workOrderId: workorder.id }) : Promise.resolve([]),
42987
+ Promise.all(artifactIds.map((artifactId) => oplog.read(artifactId)))
42988
+ ]);
42989
+ nodeOutputsByWorkorder.set(workorder.id, nodeOutputs);
42990
+ opsByWorkorder.set(workorder.id, opGroups.flat());
42991
+ }));
42992
+ return {
42993
+ status: 200,
42994
+ body: {
42995
+ items: buildWorkorderMetrics({
42996
+ model: kernel.model,
42997
+ workorders,
42998
+ dispatchJournal: opts.metricsDispatchJournal?.() ?? opts.dispatchJournal?.() ?? [],
42999
+ opsByWorkorder,
43000
+ nodeOutputsByWorkorder,
43001
+ ...resolve5 ? { resolveActor: resolve5 } : {}
43002
+ })
43003
+ }
43004
+ };
43005
+ });
42675
43006
  router.get("/api/workorders/:id", async (req) => {
42676
43007
  const { kernel, oplog, registry: registry2, artifacts } = await resolveCtx(req.auth.companyId);
42677
43008
  const resolve5 = await buildResolver(registry2);
@@ -42799,10 +43130,12 @@ var init_collab = __esm({
42799
43130
  init_inbox();
42800
43131
  init_audit();
42801
43132
  init_dashboard();
43133
+ init_workorder_metrics();
42802
43134
  init_organization_usage();
42803
43135
  init_node_state();
42804
43136
  init_workorders();
42805
43137
  init_workorder_detail();
43138
+ init_workorder_metrics();
42806
43139
  init_inbox();
42807
43140
  init_audit();
42808
43141
  init_dashboard();
@@ -42839,8 +43172,8 @@ function makeSeededWorkorderCreator(deps) {
42839
43172
  await deps.kernel.applyIntervention(planned.plan, preview2.baseSeqs, input.actor);
42840
43173
  const briefId = planned.rootArtifactId;
42841
43174
  if (input.brief.trim()) {
42842
- const ref = await deps.blobs.put(enc2(input.brief));
42843
- await deps.kernel.proposeRevision({ artifactId: briefId, actor: input.actor, contentRef: ref, reason: "\u5267\u672C\u5EFA\u5355\uFF1A\u843D\u5B9A brief \u9996\u7248" });
43175
+ const ref2 = await deps.blobs.put(enc2(input.brief));
43176
+ await deps.kernel.proposeRevision({ artifactId: briefId, actor: input.actor, contentRef: ref2, reason: "\u5267\u672C\u5EFA\u5355\uFF1A\u843D\u5B9A brief \u9996\u7248" });
42844
43177
  await deps.kernel.advanceQueue(briefId, input.actor);
42845
43178
  await deps.kernel.conclude({ artifactId: briefId, actor: input.actor, note: "\u5267\u672C\u5EFA\u5355\u65F6\u5B9A\u7A3F" });
42846
43179
  }
@@ -43139,18 +43472,18 @@ var init_sink = __esm({
43139
43472
  end(sessionId, update) {
43140
43473
  const captured = this.sessions.get(sessionId);
43141
43474
  this.enqueue(sessionId, async (st) => {
43142
- for (const ref of update.opRefs) {
43475
+ for (const ref2 of update.opRefs) {
43143
43476
  await this.store.appendEvents(st.runId, [{
43144
43477
  seq: ++st.seq,
43145
43478
  eventType: "oplog.appended",
43146
43479
  stream: "oasis",
43147
- message: ref.kind,
43148
- payload: { opId: ref.id, kind: ref.kind, target: ref.target, oplogSeq: ref.seq }
43480
+ message: ref2.kind,
43481
+ payload: { opId: ref2.id, kind: ref2.kind, target: ref2.target, oplogSeq: ref2.seq }
43149
43482
  }]);
43150
43483
  await this.store.putRunLink({
43151
43484
  runId: st.runId,
43152
43485
  refType: "op",
43153
- refId: ref.id,
43486
+ refId: ref2.id,
43154
43487
  relation: "produced",
43155
43488
  createdAt: update.exit.at
43156
43489
  });
@@ -43447,8 +43780,8 @@ var init_service4 = __esm({
43447
43780
  totalRuns: items.length,
43448
43781
  runningRuns: byStatus.get("running") ?? 0,
43449
43782
  failedRuns: (byStatus.get("failed") ?? 0) + (byStatus.get("timeout") ?? 0) + (byStatus.get("killed") ?? 0) + (byStatus.get("orphaned") ?? 0),
43450
- byStatus: [...byStatus].map(([status, count]) => ({ status, count })),
43451
- byRuntimeKind: [...byKind].map(([runtimeKind, count]) => ({ runtimeKind, count }))
43783
+ byStatus: [...byStatus].map(([status, count2]) => ({ status, count: count2 })),
43784
+ byRuntimeKind: [...byKind].map(([runtimeKind, count2]) => ({ runtimeKind, count: count2 }))
43452
43785
  };
43453
43786
  }
43454
43787
  };
@@ -44043,18 +44376,18 @@ var init_chat_sessions = __esm({
44043
44376
  });
44044
44377
 
44045
44378
  // ../server/src/domains/automations/playbooks.ts
44046
- function isKnownPlaybook(ref) {
44047
- return ref in BUILTIN;
44379
+ function isKnownPlaybook(ref2) {
44380
+ return ref2 in BUILTIN;
44048
44381
  }
44049
- function resolvePlaybook(ref, ctx) {
44050
- const def = BUILTIN[ref];
44382
+ function resolvePlaybook(ref2, ctx) {
44383
+ const def = BUILTIN[ref2];
44051
44384
  if (def) {
44052
44385
  return { artifactType: def.artifactType, title: def.title(ctx), brief: def.brief(ctx) };
44053
44386
  }
44054
44387
  return {
44055
44388
  artifactType: "document",
44056
44389
  title: `\u81EA\u52A8\u5316\u7ACB\u9879\uFF1A${ctx.automation.name}\uFF08${isoDate(ctx.now)}\uFF09`,
44057
- brief: `\u7531\u81EA\u52A8\u5316\u300C${ctx.automation.name}\u300D\uFF08\u5267\u672C ${ref}\uFF09\u53D1\u8D77\u7684\u534F\u4F5C\u3002`
44390
+ brief: `\u7531\u81EA\u52A8\u5316\u300C${ctx.automation.name}\u300D\uFF08\u5267\u672C ${ref2}\uFF09\u53D1\u8D77\u7684\u534F\u4F5C\u3002`
44058
44391
  };
44059
44392
  }
44060
44393
  var isoDate, BUILTIN, BUILTIN_PLAYBOOK_REFS;
@@ -45243,8 +45576,8 @@ ${body || "\uFF08\u672A\u586B\u5199\uFF09"}`;
45243
45576
  plan
45244
45577
  };
45245
45578
  }
45246
- function isKnownPlaybook2(ref) {
45247
- return ref in BUILTIN2;
45579
+ function isKnownPlaybook2(ref2) {
45580
+ return ref2 in BUILTIN2;
45248
45581
  }
45249
45582
  function listPlaybooks() {
45250
45583
  return Object.values(BUILTIN2).map((d) => ({
@@ -45256,8 +45589,8 @@ function listPlaybooks() {
45256
45589
  ...d.graph ? { graph: d.graph } : {}
45257
45590
  }));
45258
45591
  }
45259
- function resolvePlaybook2(ref, ctx) {
45260
- const def = BUILTIN2[ref];
45592
+ function resolvePlaybook2(ref2, ctx) {
45593
+ const def = BUILTIN2[ref2];
45261
45594
  return def ? def.resolve(ctx) : null;
45262
45595
  }
45263
45596
  var BUG_FIX_INPUTS, BUG_FIX_STRUCTURE, BUILTIN2, PLAYBOOK_REFS;
@@ -45327,15 +45660,15 @@ function playbooksDomain(opts) {
45327
45660
  return { status: 200, body };
45328
45661
  });
45329
45662
  router.post("/api/playbooks/:ref/run", async (req) => {
45330
- const ref = req.params.ref;
45331
- if (!ref || !isKnownPlaybook2(ref)) {
45332
- throw new ApiError(400, "UNKNOWN_PLAYBOOK", `\u672A\u77E5\u5267\u672C ${ref}\uFF08\u5185\u7F6E\uFF1A${PLAYBOOK_REFS.join(", ")}\uFF09`);
45663
+ const ref2 = req.params.ref;
45664
+ if (!ref2 || !isKnownPlaybook2(ref2)) {
45665
+ throw new ApiError(400, "UNKNOWN_PLAYBOOK", `\u672A\u77E5\u5267\u672C ${ref2}\uFF08\u5185\u7F6E\uFF1A${PLAYBOOK_REFS.join(", ")}\uFF09`);
45333
45666
  }
45334
45667
  const payload = (req.body ?? null)?.payload ?? null;
45335
- const resolved = resolvePlaybook2(ref, { now: now(), ...payload !== null ? { payload } : {} });
45336
- if (!resolved) throw new ApiError(400, "UNKNOWN_PLAYBOOK", `\u672A\u77E5\u5267\u672C ${ref}`);
45668
+ const resolved = resolvePlaybook2(ref2, { now: now(), ...payload !== null ? { payload } : {} });
45669
+ if (!resolved) throw new ApiError(400, "UNKNOWN_PLAYBOOK", `\u672A\u77E5\u5267\u672C ${ref2}`);
45337
45670
  if (resolved.produces !== "workorder" || !resolved.plan) {
45338
- throw new ApiError(400, "PLAYBOOK_NOT_RUNNABLE", `\u5267\u672C ${ref} \u6682\u4E0D\u652F\u6301\u76F4\u63A5\u8FD0\u884C\u5EFA\u5355`);
45671
+ throw new ApiError(400, "PLAYBOOK_NOT_RUNNABLE", `\u5267\u672C ${ref2} \u6682\u4E0D\u652F\u6301\u76F4\u63A5\u8FD0\u884C\u5EFA\u5355`);
45339
45672
  }
45340
45673
  const projectId = readProjectId(payload);
45341
45674
  if (projectId && opts.projectExists && !await opts.projectExists(projectId)) {
@@ -45351,7 +45684,7 @@ function playbooksDomain(opts) {
45351
45684
  actor: req.auth.actor
45352
45685
  });
45353
45686
  const body = {
45354
- playbookRef: ref,
45687
+ playbookRef: ref2,
45355
45688
  produces: resolved.produces,
45356
45689
  workspaceId: result.workspace,
45357
45690
  rootArtifactId: result.rootArtifactId,
@@ -46172,7 +46505,7 @@ var init_resolve = __esm({
46172
46505
  });
46173
46506
 
46174
46507
  // ../server/src/coordinator/worker.ts
46175
- var import_node_crypto21, AUTONOMOUS_ETHOS, CONVERSATIONAL_ETHOS, SHARED_GRAPH_BODY, COORDINATOR_SYSTEM_PROMPT, CONVERSATIONAL_MANAGER_BODY, CoordinatorWorker;
46508
+ var import_node_crypto21, AUTONOMOUS_ETHOS, CONVERSATIONAL_ETHOS, SHARED_GRAPH_BODY, COORDINATOR_SYSTEM_PROMPT, CONVERSATIONAL_RECOVERY_TOOLS, CONVERSATIONAL_MANAGER_BODY, CoordinatorWorker;
46176
46509
  var init_worker = __esm({
46177
46510
  "../server/src/coordinator/worker.ts"() {
46178
46511
  "use strict";
@@ -46226,9 +46559,15 @@ var init_worker = __esm({
46226
46559
  COORDINATOR_SYSTEM_PROMPT = `${AUTONOMOUS_ETHOS}
46227
46560
 
46228
46561
  ${SHARED_GRAPH_BODY}`;
46562
+ CONVERSATIONAL_RECOVERY_TOOLS = `\u3010\u6062\u590D\u52A8\u4F5C\uFF08\u5BF9\u8BDD\u4E13\u5C5E\uFF0C\u4EBA\u5728\u573A\u65F6\u624D\u7528\uFF09\uFF1A\u6682\u505C / \u6062\u590D\u8282\u70B9\u6D3E\u53D1\u2014\u2014\u53EA\u6321 agent \u6D3E\u53D1\u3001\u4E0D\u9501\u5185\u5BB9\uFF08\u2260 freeze/cancel\uFF09\uFF0C\u5373\u65F6\u751F\u6548\u3001\u4E0D\u8FDB\u6539\u56FE\u7F13\u51B2\u3011\uFF1A
46563
+ - \`oasis hold <id> --reason "<\u4E3A\u4EC0\u4E48\u5148\u51BB>"\` \u2014\u2014 \u6682\u505C\u8BE5\u8282\u70B9\u7684 agent \u6D3E\u53D1\u3002\u53CD\u590D\u5931\u8D25\u3001\u6216\u4EBA\u8981\u5148\u67E5/\u5148\u624B\u52A8\u6539\u73AF\u5883\uFF08\u6362 runtime\u3001\u8865\u51ED\u8BC1\uFF09\u65F6\uFF0C\u5148\u628A\u5B83\u51BB\u4F4F\u522B\u518D\u7A7A\u8F6C\u91CD\u6D3E\uFF1Bowner \u4E0D\u53D8\u3001\u5185\u5BB9\u4ECD\u53EF\u6539\u3002
46564
+ - \`oasis release <id>\` \u2014\u2014 \u6062\u590D\u6D3E\u53D1\uFF1A\u89E3\u963B\u540E\u7CFB\u7EDF\u91CD\u63A8\u8BE5\u8282\u70B9**\u5F53\u4E0B\u771F\u6B63\u6B20\u7684\u6D3B**\uFF08\u5BF9\u88AB\u5347\u7EA7\u51BB\u7ED3\u7684\u8282\u70B9\uFF0C\u8FD9\u5C31\u662F"\u8BA9\u5B83\u91CD\u65B0\u8DD1"\uFF09\u3002**\u53EA\u5728\u786E\u8BA4\u6839\u56E0\u5DF2\u5904\u7406\u540E\u624D\u653E**\uFF08\u4EBA\u5DF2\u6362 runtime / \u8865\u4E86\u51ED\u8BC1 / \u6539\u4E86\u4EFB\u52A1\u4E66\uFF09\uFF0C\u5426\u5219\u4E00\u653E\u53C8\u683D\u540C\u4E00\u4E2A\u5751\u3002
46565
+ \u5224\u65AD\u8FB9\u754C\uFF1A\u8FD9\u4FE9\u662F"\u6709\u4EE3\u4EF7\u3001\u9700\u5224\u65AD"\u7684\u52A8\u4F5C\u2014\u2014**\u4EBA\u6279\u51C6\u4E86\u518D\u505A**\uFF0C\u522B\u81EA\u4F5C\u4E3B\u5F20\u628A\u4EBA\u6B63\u5728\u67E5\u7684\u8282\u70B9\u653E\u51FA\u53BB\u3002`;
46229
46566
  CONVERSATIONAL_MANAGER_BODY = `${CONVERSATIONAL_ETHOS}
46230
46567
 
46231
- ${SHARED_GRAPH_BODY}`;
46568
+ ${SHARED_GRAPH_BODY}
46569
+
46570
+ ${CONVERSATIONAL_RECOVERY_TOOLS}`;
46232
46571
  CoordinatorWorker = class {
46233
46572
  constructor(deps) {
46234
46573
  this.deps = deps;
@@ -46559,6 +46898,69 @@ ${SHARED_GRAPH_BODY}`;
46559
46898
  ].join("\n");
46560
46899
  await this.runCoordinator(p2.id, task, `\u6B7B\u9501\u8BC4\u4F30 ${p2.id}\uFF08\u963B\u585E ${mins}min\uFF09`);
46561
46900
  }
46901
+ /**
46902
+ * ADR-0048 自动分诊:结构性运行时故障(连不上 / 挂死超时 / 缺凭证 / 配额打满)熔断升级前,**先跑一次本工单管理者
46903
+ * 产出诊断**——人点开 inbox 卡时看到的是"管理者已诊断 + 给了处置建议",而非冷启动的系统通用占位。
46904
+ *
46905
+ * 由 SLA 扫描 **fire-and-forget** 调用(内部 await 管理者会话跑完,但不阻塞扫描线程)。调用前 SLA 扫描已把节点
46906
+ * **冻结**(hold source:sla),所以这里管理者用自主 prompt(COORDINATOR_SYSTEM_PROMPT,**不含 hold/release**)——
46907
+ * 它能做的只有"诊断 + escalate"(运行时故障它多半解不了),**不会**误把刚冻的节点放出去。
46908
+ *
46909
+ * 兜底(保证 inbox 一定有卡):无可用管理者(run=null)/ 管理者跑完仍没 escalate(空手)→ 系统落一条通用 escalate。
46910
+ */
46911
+ async triageFailure(artifactId, ctx) {
46912
+ if (unresolvedEscalationsOf(this.deps.kernel.model, artifactId).length > 0) return;
46913
+ const task = this.buildTriageTask(artifactId, ctx);
46914
+ const run = await this.runCoordinator(
46915
+ artifactId,
46916
+ task,
46917
+ `\u5931\u8D25\u5206\u8BCA ${artifactId}\uFF08\u8FDE\u8D25 ${ctx.consecutiveFailures}${ctx.lastReason ? `\uFF0C\u672B\u6B21 ${ctx.lastReason}` : ""}\uFF09`
46918
+ );
46919
+ if (unresolvedEscalationsOf(this.deps.kernel.model, artifactId).length > 0) {
46920
+ this.deps.log?.(`[coordinator] ${artifactId} \u81EA\u52A8\u5206\u8BCA\u5B8C\u6210\uFF1A\u7BA1\u7406\u8005\u5DF2\u4EA7\u51FA\u8BCA\u65AD\u5E76 escalate`);
46921
+ return;
46922
+ }
46923
+ const failLine = `agent \u8FDE\u8D25\u7194\u65AD\uFF08\u8FDE\u8D25 ${ctx.consecutiveFailures} \u6B21${ctx.lastReason ? `\uFF0C\u672B\u6B21\u5931\u8D25\uFF1A${ctx.lastReason}` : ""}\uFF09`;
46924
+ await this.deps.kernel.escalate({
46925
+ artifactId,
46926
+ actor: SYSTEM_ACTOR,
46927
+ reason: run ? `\u81EA\u52A8\u5206\u8BCA\u672A\u6536\u53E3\uFF08\u7BA1\u7406\u8005\u88AB\u5524\u8D77\u5374\u6CA1\u4E0A\u62A5\u8BCA\u65AD\uFF09\u2014\u2014\u7CFB\u7EDF\u515C\u5E95\u5347\u7EA7\uFF1A${failLine}\uFF0C\u8BF7\u4EBA\u5DE5\u6392\u67E5\u6839\u56E0\uFF08\u8FDE\u4E0D\u4E0A/\u6302\u6B7B/\u7F3A\u51ED\u8BC1/\u914D\u989D\uFF09\u3002` : `\u672C\u5DE5\u5355\u65E0\u53EF\u7528\u7BA1\u7406\u8005\u3001\u65E0\u6CD5\u81EA\u52A8\u5206\u8BCA\u2014\u2014\u7CFB\u7EDF\u5347\u7EA7\uFF1A${failLine}\uFF0C\u8BF7\u4EBA\u5DE5\u6392\u67E5\u6839\u56E0\uFF08\u8FDE\u4E0D\u4E0A/\u6302\u6B7B/\u7F3A\u51ED\u8BC1/\u914D\u989D\uFF09\u3002`
46928
+ }).catch((e) => this.deps.log?.(`[coordinator] ${artifactId} \u5206\u8BCA\u515C\u5E95 escalate \u5931\u8D25\uFF1A${String(e)}`));
46929
+ this.deps.log?.(`[coordinator] ${artifactId} \u81EA\u52A8\u5206\u8BCA\u515C\u5E95\uFF1A\u7CFB\u7EDF\u843D\u901A\u7528 escalate\uFF08\u7BA1\u7406\u8005${run ? "\u7A7A\u624B" : "\u4E0D\u53EF\u7528"}\uFF09`);
46930
+ }
46931
+ /** 失败分诊的 TASK.md:把已知失败事实喂给管理者,让它归因 + 给处置建议 + escalate(唯一收尾)。 */
46932
+ buildTriageTask(artifactId, ctx) {
46933
+ const m2 = this.deps.kernel.model;
46934
+ const node = m2.artifacts.get(artifactId);
46935
+ const brief = node?.title ?? node?.description ?? "";
46936
+ const downstreams = consumersOf(m2, artifactId).map((a) => a.id);
46937
+ return [
46938
+ `## \u672C\u6B21\u4E3A\u4EC0\u4E48\u5524\u8D77\u4F60`,
46939
+ `\u8282\u70B9 **${artifactId}**${brief ? `\uFF08\u5B83\u662F\uFF1A${brief}\uFF09` : ""} \u7684 agent **\u53CD\u590D\u5931\u8D25\u3001\u5DF2\u88AB\u7194\u65AD**\u2014\u2014\u8FDE\u8D25 **${ctx.consecutiveFailures}** \u6B21\u3002`,
46940
+ ctx.lastReason ? `> \u672B\u6B21\u5931\u8D25\u539F\u56E0\uFF08\u8FD0\u884C\u65F6\u7ED9\u7684\uFF09\uFF1A\`${ctx.lastReason}\`` : `> \u672B\u6B21\u5931\u8D25\u539F\u56E0\uFF1A\u672A\u77E5\uFF08\u8FD0\u884C\u65F6\u672A\u7ED9\u7ED3\u6784\u5316\u539F\u56E0\uFF09\u3002`,
46941
+ `\u7CFB\u7EDF\u5DF2\u628A\u5B83**\u51BB\u7ED3**\uFF08\u9632\u6B62\u5B83\u7A7A\u8F6C\u53CD\u590D\u91CD\u8DD1\uFF09\u3002**\u4F60\u7684\u4EFB\u52A1\u662F\u8BCA\u65AD + \u4E0A\u62A5\uFF0C\u4E0D\u662F\u8BA9\u5B83\u590D\u5DE5**\u2014\u2014\u6839\u56E0\u6CA1\u9664\u5C31\u653E\u51FA\u53BB\u53EA\u4F1A\u518D\u683D\u4E00\u6B21\u3002`,
46942
+ downstreams.length ? `\u8FD9\u6761\u7EBF\u5361\u7740\u3001\u4E0B\u6E38\u8DDF\u7740\u505C\uFF1A${downstreams.map((d) => `\`${d}\``).join("\u3001")}\u3002` : ``,
46943
+ ``,
46944
+ `## \u8FD9\u591A\u534A\u662F\u8FD0\u884C\u65F6 / \u8D44\u6E90\u7C7B\u6545\u969C\uFF08\u4E0D\u662F\u56FE\u75C5\uFF09`,
46945
+ `\u7194\u65AD = agent \u8FDE\u7740\u8DD1\u4E0D\u8D77\u6765\u6216\u8DD1\u4E0D\u5B8C\uFF0C\u5E38\u89C1\u51E0\u7C7B\uFF0C\u4F60\u636E\u672B\u6B21\u539F\u56E0\u5224\u65AD\u843D\u5728\u54EA\u7C7B\uFF1A`,
46946
+ `- **\u7ED1\u5B9A\u8D26\u53F7\u914D\u989D\u6253\u6EE1**\uFF08\u5982 429 / \u4F7F\u7528\u4E0A\u9650\uFF09\u2014\u2014\u8981\u4EBA\u52A0\u989D\u5EA6 / \u6362\u7ED1\u5B9A\u5230\u6709\u989D\u5EA6\u7684\u8D26\u53F7 / \u51CF\u5E76\u53D1\u3002`,
46947
+ `- **\u7F3A\u51ED\u8BC1 / \u5BC6\u94A5**\uFF08\u5982\u67D0\u4ED3\u5E93\u3001\u67D0 API \u6CA1\u6388\u6743\uFF09\u2014\u2014\u8981\u4EBA\u8865\u51ED\u8BC1\u3002`,
46948
+ `- **runtime \u8FDE\u4E0D\u4E0A / \u4F1A\u8BDD\u6302\u6B7B\u8D85\u65F6**\uFF08\u8282\u70B9\u6389\u7EBF\u3001\u8FDB\u7A0B\u5361\u6B7B\uFF09\u2014\u2014\u8981\u4EBA\u6362 runtime / \u91CD\u542F\u8282\u70B9\u3002`,
46949
+ `- **\u4EFB\u52A1\u672C\u8EAB\u8BA9 agent \u53CD\u590D\u4EA7\u4E0D\u51FA**\uFF08\u4EFB\u52A1\u4E66\u6709\u786C\u4F24 / \u7F3A\u5173\u952E\u8F93\u5165\uFF09\u2014\u2014\u8981\u4EBA\u6539\u4EFB\u52A1\u4E66\u6216\u8865\u8F93\u5165\u3002`,
46950
+ `\u8FD9\u4E9B\u4F60**\u591A\u534A\u72EC\u7ACB\u89E3\u4E0D\u4E86**\uFF08\u6362\u989D\u5EA6\u3001\u6362\u673A\u5668\u3001\u8865\u51ED\u8BC1\u90FD\u8981\u4EBA\uFF09\uFF0C\u6240\u4EE5\u6838\u5FC3\u4EA7\u51FA\u662F**\u4E00\u4EFD\u8BA9\u4EBA\u4E00\u773C\u770B\u61C2\u8BE5\u600E\u4E48\u4FEE\u7684\u8BCA\u65AD**\u3002`,
46951
+ ``,
46952
+ `## \u73B0\u6709\u4EA7\u7269\uFF08\u90BB\u57DF\u4E0A\u4E0B\u6587\uFF0C\u5E2E\u4F60\u5224\u65AD\u5F71\u54CD\u9762\uFF09`,
46953
+ this.structDigest(artifactId),
46954
+ ``,
46955
+ `## \u4F60\u7684\u52A8\u4F5C\u2014\u2014**\u53EA\u6709\u4E00\u4E2A\u6536\u5C3E\uFF1Aescalate**`,
46956
+ `\`oasis escalate ${artifactId} --reason "<\u4F60\u5224\u65AD\u7684\u6839\u56E0\u7C7B\u522B + \u5EFA\u8BAE\u4EBA\u5177\u4F53\u505A\u4EC0\u4E48>"\``,
46957
+ `- reason \u5199\u4EBA\u8BDD\uFF1A\u5148\u8BF4\u6839\u56E0\uFF08\u5982"\u7ED1\u5B9A\u8D26\u53F7\u914D\u989D\u6253\u6EE1\uFF0C\u672B\u6B21\u62A5 429 \u4F7F\u7528\u4E0A\u9650"\uFF09\uFF0C\u518D\u8BF4\u5EFA\u8BAE\uFF08\u5982"\u6362\u7ED1\u5B9A\u5230\u6709\u989D\u5EA6\u8D26\u53F7 / \u52A0\u989D\u5EA6 / \u51CF\u5E76\u53D1"\uFF09\u3002\u4EBA\u5728 inbox \u91CC\u76F4\u63A5\u770B\u8FD9\u6BB5\u3002`,
46958
+ `- **\u522B\u6539\u56FE**\uFF08link/spawn/cancel\uFF09\u2014\u2014\u8FD9\u4E0D\u662F\u7F3A\u4E0A\u6E38 / \u56FE\u75C5\uFF0C\u4E71\u6539\u56FE\u4F1A\u63A9\u76D6\u771F\u95EE\u9898\u3002`,
46959
+ `- **\u522B resolve-gap**\u2014\u2014\u8FD9\u91CC\u6CA1\u6709 gap\u3002`,
46960
+ `- **\u522B\u8BD5\u56FE\u8BA9\u5B83\u590D\u5DE5 / \u522B\u50AC\u91CD\u8DD1**\u2014\u2014\u5B83\u88AB\u51BB\u7740\u662F\u5BF9\u7684\uFF0C\u6839\u56E0\u6CA1\u9664\u653E\u51FA\u53BB\u5FC5\u518D\u683D\u3002`,
46961
+ `- **\u7EDD\u4E0D\u7A7A\u624B\u9000\u51FA**\uFF1A\u4E0D escalate = \u4EBA\u62FF\u5230\u7684\u8FD8\u662F\u7CFB\u7EDF\u7684\u901A\u7528\u5360\u4F4D\u3001\u8FD9\u6B21\u5206\u8BCA\u767D\u8DD1\u3002\u5224\u65AD\u4E0D\u4E86\u6839\u56E0\uFF0C\u4E5F\u628A"\u6211\u770B\u5230\u7684\u73B0\u8C61 + \u9700\u8981\u4EBA\u67E5\u4EC0\u4E48"escalate \u4E0A\u53BB\u3002`
46962
+ ].filter(Boolean).join("\n");
46963
+ }
46562
46964
  /**
46563
46965
  * 决策 0026:解析某节点所属**工单**的管理者——读该 workspace 根 brief 的 `fields.manager`(陪发起人聊出此单的
46564
46966
  * AI 实例),再经 `resolveManager` 拿它的 active record + binding。无 manager 字段 / 解析不到(非 active / 无绑定)
@@ -47580,11 +47982,11 @@ var require_binaryParsers = __commonJS({
47580
47982
  var array2 = [];
47581
47983
  var i2;
47582
47984
  if (dimension.length > 1) {
47583
- var count = dimension.shift();
47584
- for (i2 = 0; i2 < count; i2++) {
47985
+ var count2 = dimension.shift();
47986
+ for (i2 = 0; i2 < count2; i2++) {
47585
47987
  array2[i2] = parse2(dimension, elementType2);
47586
47988
  }
47587
- dimension.unshift(count);
47989
+ dimension.unshift(count2);
47588
47990
  } else {
47589
47991
  for (i2 = 0; i2 < dimension[0]; i2++) {
47590
47992
  array2[i2] = parseElement(elementType2);
@@ -52925,8 +53327,8 @@ function renderIndexYaml2(index) {
52925
53327
  function renderProgressJsonl(progress) {
52926
53328
  return "```json\n" + progress.map((p2) => JSON.stringify(p2)).join("\n") + "\n```";
52927
53329
  }
52928
- function parseDocRef(ref) {
52929
- return ref.startsWith(DOC_REF_PREFIX) ? ref.slice(DOC_REF_PREFIX.length) : null;
53330
+ function parseDocRef(ref2) {
53331
+ return ref2.startsWith(DOC_REF_PREFIX) ? ref2.slice(DOC_REF_PREFIX.length) : null;
52930
53332
  }
52931
53333
  function runStateKey2(workOrderId, nodeId) {
52932
53334
  return `${workOrderId ?? ""}::${nodeId ?? ""}`;
@@ -55919,6 +56321,7 @@ var rowToRun2 = (row) => ({
55919
56321
  });
55920
56322
 
55921
56323
  // ../storage/src/postgres-chat-sessions.ts
56324
+ init_chat_session();
55922
56325
  var ident7 = (s2) => {
55923
56326
  if (!/^[a-z_][a-z0-9_]*$/.test(s2)) throw new Error(`invalid schema name: ${s2}`);
55924
56327
  return s2;
@@ -55986,10 +56389,24 @@ var PostgresChatSessionStore = class _PostgresChatSessionStore {
55986
56389
  }
55987
56390
  async listSessions(humanActorId) {
55988
56391
  const r = await this.pool.query(
55989
- `SELECT * FROM ${this.s}.chat_sessions WHERE human_actor_id = $1 ORDER BY touched_at DESC`,
56392
+ `SELECT s.*, lm.status AS last_assistant_status, lm.content AS last_assistant_content
56393
+ FROM ${this.s}.chat_sessions s
56394
+ LEFT JOIN LATERAL (
56395
+ SELECT status, content FROM ${this.s}.chat_messages
56396
+ WHERE session_id = s.id AND role = 'assistant'
56397
+ ORDER BY seq DESC LIMIT 1
56398
+ ) lm ON TRUE
56399
+ WHERE s.human_actor_id = $1
56400
+ ORDER BY s.touched_at DESC`,
55990
56401
  [humanActorId]
55991
56402
  );
55992
- return r.rows.map(rowToSession);
56403
+ return r.rows.map((row) => {
56404
+ const quality = deriveLastTurnQuality({
56405
+ status: row.last_assistant_status ?? void 0,
56406
+ content: row.last_assistant_content ?? ""
56407
+ });
56408
+ return { ...rowToSession(row), ...quality ? { lastTurnQuality: quality } : {} };
56409
+ });
55993
56410
  }
55994
56411
  async getSession(id) {
55995
56412
  const r = await this.pool.query(`SELECT * FROM ${this.s}.chat_sessions WHERE id = $1`, [id]);
@@ -56630,10 +57047,10 @@ async function startServe(opts) {
56630
57047
  let nodeStore = await FileNodeStore.open(path16.join(opts.dir, "nodes.json"));
56631
57048
  const registryAuditFile = path16.join(opts.dir, "registry-audit.ndjson");
56632
57049
  const registryListeners = /* @__PURE__ */ new Set();
56633
- const registryAudit = (record5) => {
56634
- fs18.appendFile(registryAuditFile, JSON.stringify(record5) + "\n", () => {
57050
+ const registryAudit = (record6) => {
57051
+ fs18.appendFile(registryAuditFile, JSON.stringify(record6) + "\n", () => {
56635
57052
  });
56636
- for (const l of registryListeners) l({ kind: record5.kind, actor: record5.actor, target: record5.target, timestamp: record5.timestamp });
57053
+ for (const l of registryListeners) l({ kind: record6.kind, actor: record6.actor, target: record6.target, timestamp: record6.timestamp });
56637
57054
  };
56638
57055
  await syncRegistryRolesToKernel(registryStore, kernel);
56639
57056
  let builtinSkills = [];
@@ -56856,6 +57273,20 @@ async function startServe(opts) {
56856
57273
  fs18.appendFile(journalFile, JSON.stringify(entry) + "\n", () => {
56857
57274
  });
56858
57275
  };
57276
+ const readMetricJournal = () => {
57277
+ if (!fs18.existsSync(journalFile)) return [...journalRing];
57278
+ try {
57279
+ return fs18.readFileSync(journalFile, "utf8").split(/\r?\n/).filter(Boolean).flatMap((line) => {
57280
+ try {
57281
+ return [JSON.parse(line)];
57282
+ } catch {
57283
+ return [];
57284
+ }
57285
+ });
57286
+ } catch {
57287
+ return [...journalRing];
57288
+ }
57289
+ };
56859
57290
  const closeOrphanedDispatches = () => {
56860
57291
  const open2 = /* @__PURE__ */ new Map();
56861
57292
  for (const entry of journalRing) {
@@ -57051,6 +57482,7 @@ async function startServe(opts) {
57051
57482
  registry: registryStore,
57052
57483
  artifacts: artifactStateStore,
57053
57484
  dispatchJournal: () => journalRing.slice(-200),
57485
+ metricsDispatchJournal: readMetricJournal,
57054
57486
  workorderDrafts,
57055
57487
  // 活工单查不到时回退查建单草案(status="draft")
57056
57488
  ...opts.sla ? { sla: opts.sla } : {},
@@ -57647,6 +58079,7 @@ ${detail}` : genericLine));
57647
58079
  const humanMs = opts.sla?.humanMs ?? 24 * 36e5;
57648
58080
  const agentMs = opts.sla?.agentMs ?? 10 * 6e4;
57649
58081
  const quotaStarvationMs = opts.sla?.quotaStarvationMs ?? 6 * 36e5;
58082
+ let triageFailure;
57650
58083
  const initiatorCache = /* @__PURE__ */ new Map();
57651
58084
  const initiatorOf = async (workspace) => {
57652
58085
  if (initiatorCache.has(workspace)) return initiatorCache.get(workspace);
@@ -57736,7 +58169,21 @@ ${detail}` : genericLine));
57736
58169
  if (f2.action !== "produce") continue;
57737
58170
  if (!kernel.model.artifacts.get(f2.artifactId)) continue;
57738
58171
  if (now - Date.parse(f2.fusedAt) <= agentMs) continue;
57739
- await escalateHold(f2.artifactId, `agent \u8FDE\u8D25\u7194\u65AD\u540E ${Math.round(agentMs / 6e4)} \u5206\u949F\u65E0\u4EBA\u5904\u7406\uFF08\u8FDE\u8D25 ${f2.consecutiveFailures} \u6B21\uFF09`, "\u7194\u65AD\u5347\u7EA7");
58172
+ if (unresolvedEscalationsOf(kernel.model, f2.artifactId).length > 0) continue;
58173
+ if (isHeld(kernel.model, f2.artifactId)) continue;
58174
+ const failReason = `agent \u8FDE\u8D25\u7194\u65AD\u540E ${Math.round(agentMs / 6e4)} \u5206\u949F\u65E0\u4EBA\u5904\u7406\uFF08\u8FDE\u8D25 ${f2.consecutiveFailures} \u6B21\uFF09`;
58175
+ if (triageFailure) {
58176
+ const owner = kernel.model.artifacts.get(f2.artifactId)?.owner ?? "";
58177
+ try {
58178
+ await kernel.hold({ artifactId: f2.artifactId, actor: SYSTEM_ACTOR, source: "sla", reason: failReason });
58179
+ console.log(`[sla] ${f2.artifactId} \u7194\u65AD\u5347\u7EA7\uFF1A\u51BB\u7ED3 + \u89E6\u53D1\u81EA\u52A8\u5206\u8BCA\uFF08owner \u4FDD\u6301 ${owner}\uFF0C\u4E0D\u593A\uFF09`);
58180
+ void triageFailure(f2.artifactId, { consecutiveFailures: f2.consecutiveFailures, ...f2.lastReason ? { lastReason: f2.lastReason } : {} });
58181
+ } catch (err) {
58182
+ console.error(`[sla] \u7194\u65AD\u5347\u7EA7\u51BB\u7ED3\u5931\u8D25 ${f2.artifactId}: ${String(err)}`);
58183
+ }
58184
+ } else {
58185
+ await escalateHold(f2.artifactId, failReason, "\u7194\u65AD\u5347\u7EA7");
58186
+ }
57740
58187
  }
57741
58188
  for (const s2 of allDispatchers().flatMap((d) => d.starvingJobs(quotaStarvationMs, now))) {
57742
58189
  if (s2.action !== "produce") continue;
@@ -57835,6 +58282,7 @@ ${detail}` : genericLine));
57835
58282
  // 0030 D7 落盘
57836
58283
  });
57837
58284
  coordinatorRef = coordinator;
58285
+ triageFailure = (artifactId, ctx) => coordinator.triageFailure(artifactId, ctx);
57838
58286
  coordTimer = setInterval(() => {
57839
58287
  void coordinator.tick().catch((err) => console.error(`[coordinator] tick \u5931\u8D25: ${String(err)}`));
57840
58288
  }, 15e3);
@@ -59997,7 +60445,7 @@ ${res.warning}`);
59997
60445
  }
59998
60446
 
59999
60447
  // src/index.ts
60000
- var PKG_VERSION = true ? "0.1.56" : "dev";
60448
+ var PKG_VERSION = true ? "0.1.57" : "dev";
60001
60449
  var OASIS_DIR = path18.join(os9.homedir(), ".oasis");
60002
60450
  var CONFIG_FILE = path18.join(OASIS_DIR, "node-config.json");
60003
60451
  var PID_FILE = path18.join(OASIS_DIR, "node.pid");