@adhdev/mesh-shared 1.0.82-rc.4 → 1.0.82-rc.40

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 (65) hide show
  1. package/dist/assistant-protocol.d.ts +161 -6
  2. package/dist/decision-push-relay.d.ts +20 -0
  3. package/dist/index.d.ts +11 -0
  4. package/dist/index.js +1197 -118
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +1107 -118
  7. package/dist/index.mjs.map +1 -1
  8. package/dist/launch-defaults.d.ts +196 -0
  9. package/dist/mesh-tool-names.d.ts +2 -2
  10. package/dist/mesh-vocabulary.d.ts +13 -4
  11. package/dist/mission-git-state.d.ts +83 -0
  12. package/dist/mission-items.d.ts +202 -0
  13. package/dist/node-facts.d.ts +75 -1
  14. package/dist/outbound-message.d.ts +9 -2
  15. package/dist/path-ownership.d.ts +1 -1
  16. package/dist/protocol/daemon-server.d.ts +42 -2
  17. package/dist/protocol/dashboard-daemon-p2p.d.ts +1 -1
  18. package/dist/protocol/dashboard-server.d.ts +20 -2
  19. package/dist/provider-approval.d.ts +36 -0
  20. package/dist/provider-question.d.ts +19 -0
  21. package/dist/quota-freshness.d.ts +65 -0
  22. package/dist/relay-reprobe.d.ts +52 -0
  23. package/dist/release.d.ts +90 -0
  24. package/dist/role-launch.d.ts +11 -0
  25. package/dist/session-launch.d.ts +10 -22
  26. package/dist/slot-proposal.d.ts +14 -0
  27. package/dist/task-source-phase.d.ts +75 -0
  28. package/dist/turn-evidence.d.ts +29 -13
  29. package/dist/turn-ipc-mission.d.ts +68 -1
  30. package/dist/turn-ipc-queue.d.ts +19 -0
  31. package/dist/turn-ipc.d.ts +2 -2
  32. package/dist/types.d.ts +1 -0
  33. package/dist/worker-protocol.d.ts +1 -1
  34. package/package.json +1 -1
  35. package/src/assistant-protocol.ts +302 -6
  36. package/src/daemon-normalize.ts +7 -5
  37. package/src/decision-push-relay.ts +23 -0
  38. package/src/index.ts +12 -0
  39. package/src/keyed-doc-delta.ts +9 -1
  40. package/src/launch-defaults.ts +170 -0
  41. package/src/mesh-tool-names.ts +16 -0
  42. package/src/mesh-vocabulary.ts +12 -2
  43. package/src/mission-git-state.ts +112 -0
  44. package/src/mission-items.ts +421 -0
  45. package/src/node-facts.ts +70 -1
  46. package/src/outbound-message.ts +19 -0
  47. package/src/path-ownership.ts +4 -6
  48. package/src/protocol/daemon-server.ts +37 -2
  49. package/src/protocol/dashboard-server.ts +13 -2
  50. package/src/provider-approval.ts +59 -0
  51. package/src/provider-question.ts +31 -0
  52. package/src/quota-freshness.ts +139 -0
  53. package/src/relay-reprobe.ts +117 -0
  54. package/src/release.ts +121 -0
  55. package/src/role-launch.ts +51 -0
  56. package/src/session-launch.ts +17 -1
  57. package/src/slot-proposal.ts +61 -2
  58. package/src/task-source-phase.ts +61 -0
  59. package/src/turn-evidence.ts +27 -20
  60. package/src/turn-ipc-mission.ts +121 -11
  61. package/src/turn-ipc-queue.ts +29 -1
  62. package/src/turn-ipc-turn.ts +1 -1
  63. package/src/turn-ipc.ts +1 -0
  64. package/src/types.ts +1 -0
  65. package/src/worker-protocol.ts +15 -0
package/dist/index.mjs CHANGED
@@ -194,15 +194,15 @@ function pickBestTransitGitStatus(node, options) {
194
194
  }
195
195
 
196
196
  // src/session-normalize.ts
197
- function deriveSyntheticSessionId(record) {
197
+ function deriveSyntheticSessionId(record2) {
198
198
  const parts = [
199
- readString(record.workspace),
200
- readString(record.providerType, record.provider),
201
- readString(record.role),
202
- readString(record.state, record.status),
203
- readString(record.title),
204
- readString(record.createdAt, record.created_at),
205
- readString(record.startedAt, record.started_at)
199
+ readString(record2.workspace),
200
+ readString(record2.providerType, record2.provider),
201
+ readString(record2.role),
202
+ readString(record2.state, record2.status),
203
+ readString(record2.title),
204
+ readString(record2.createdAt, record2.created_at),
205
+ readString(record2.startedAt, record2.started_at)
206
206
  ].filter((part) => Boolean(part));
207
207
  if (parts.length === 0) return void 0;
208
208
  return `synthetic:${parts.join("|")}`;
@@ -214,33 +214,33 @@ function sessionIdsEquivalent(a, b) {
214
214
  return idA === idB;
215
215
  }
216
216
  function normalizeMeshSessionRecord(entry) {
217
- const record = readRecord(entry);
218
- const sessionId = readString(record.sessionId, record.session_id, record.id) ?? deriveSyntheticSessionId(record);
217
+ const record2 = readRecord(entry);
218
+ const sessionId = readString(record2.sessionId, record2.session_id, record2.id) ?? deriveSyntheticSessionId(record2);
219
219
  if (!sessionId) return null;
220
220
  return {
221
221
  sessionId,
222
- ...readString(record.providerType, record.provider) ? { providerType: readString(record.providerType, record.provider) } : {},
223
- ...readString(record.state, record.status) ? { state: readString(record.state, record.status) } : {},
224
- ...readString(record.chatStatus, record.chat_status) ? { chatStatus: readString(record.chatStatus, record.chat_status) } : {},
225
- ...readString(record.lifecycle) ? { lifecycle: readString(record.lifecycle) } : {},
226
- ...readString(record.surfaceKind, record.surface_kind) ? { surfaceKind: readString(record.surfaceKind, record.surface_kind) } : {},
227
- ...readString(record.recoveryState, record.recovery_state) ? { recoveryState: readString(record.recoveryState, record.recovery_state) } : {},
228
- ...readString(record.workspace) ? { workspace: readString(record.workspace) } : {},
229
- ...readString(record.title) ? { title: readString(record.title) } : {},
230
- ...readString(record.role) ? { role: readString(record.role) } : {},
231
- ...readBoolean(record.isSelfCoordinator, record.is_self_coordinator) !== void 0 ? { isSelfCoordinator: readBoolean(record.isSelfCoordinator, record.is_self_coordinator) } : {},
232
- ...readString(record.statusNote, record.status_note) ? { statusNote: readString(record.statusNote, record.status_note) } : {},
233
- ...readString(record.createdAt, record.created_at) ? { createdAt: readString(record.createdAt, record.created_at) } : {},
234
- ...readString(record.startedAt, record.started_at) ? { startedAt: readString(record.startedAt, record.started_at) } : {},
235
- ...readString(record.lastActivityAt, record.last_activity_at) ? { lastActivityAt: readString(record.lastActivityAt, record.last_activity_at) } : {},
236
- ...readBoolean(record.isCached, record.is_cached) !== void 0 ? { isCached: readBoolean(record.isCached, record.is_cached) } : {}
222
+ ...readString(record2.providerType, record2.provider) ? { providerType: readString(record2.providerType, record2.provider) } : {},
223
+ ...readString(record2.state, record2.status) ? { state: readString(record2.state, record2.status) } : {},
224
+ ...readString(record2.chatStatus, record2.chat_status) ? { chatStatus: readString(record2.chatStatus, record2.chat_status) } : {},
225
+ ...readString(record2.lifecycle) ? { lifecycle: readString(record2.lifecycle) } : {},
226
+ ...readString(record2.surfaceKind, record2.surface_kind) ? { surfaceKind: readString(record2.surfaceKind, record2.surface_kind) } : {},
227
+ ...readString(record2.recoveryState, record2.recovery_state) ? { recoveryState: readString(record2.recoveryState, record2.recovery_state) } : {},
228
+ ...readString(record2.workspace) ? { workspace: readString(record2.workspace) } : {},
229
+ ...readString(record2.title) ? { title: readString(record2.title) } : {},
230
+ ...readString(record2.role) ? { role: readString(record2.role) } : {},
231
+ ...readBoolean(record2.isSelfCoordinator, record2.is_self_coordinator) !== void 0 ? { isSelfCoordinator: readBoolean(record2.isSelfCoordinator, record2.is_self_coordinator) } : {},
232
+ ...readString(record2.statusNote, record2.status_note) ? { statusNote: readString(record2.statusNote, record2.status_note) } : {},
233
+ ...readString(record2.createdAt, record2.created_at) ? { createdAt: readString(record2.createdAt, record2.created_at) } : {},
234
+ ...readString(record2.startedAt, record2.started_at) ? { startedAt: readString(record2.startedAt, record2.started_at) } : {},
235
+ ...readString(record2.lastActivityAt, record2.last_activity_at) ? { lastActivityAt: readString(record2.lastActivityAt, record2.last_activity_at) } : {},
236
+ ...readBoolean(record2.isCached, record2.is_cached) !== void 0 ? { isCached: readBoolean(record2.isCached, record2.is_cached) } : {}
237
237
  };
238
238
  }
239
239
 
240
240
  // src/node-normalize.ts
241
241
  function normalizeMeshNodeId(node) {
242
- const record = node && typeof node === "object" ? node : {};
243
- return readString(record.id, record.nodeId, record.node_id);
242
+ const record2 = node && typeof node === "object" ? node : {};
243
+ return readString(record2.id, record2.nodeId, record2.node_id);
244
244
  }
245
245
  function meshNodeIdMatches(node, candidateId) {
246
246
  if (!candidateId) return false;
@@ -252,12 +252,12 @@ function meshNodeIdMatches(node, candidateId) {
252
252
  // src/node-facts.ts
253
253
  function normalizeMeshNodeFacts(raw) {
254
254
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
255
- const record = raw;
256
- const schemaVersion = Number(record.schemaVersion);
257
- const reportedAt = Number(record.reportedAt);
255
+ const record2 = raw;
256
+ const schemaVersion = Number(record2.schemaVersion);
257
+ const reportedAt = Number(record2.reportedAt);
258
258
  if (!Number.isFinite(schemaVersion) || schemaVersion < 1) return void 0;
259
259
  if (!Number.isFinite(reportedAt) || reportedAt <= 0) return void 0;
260
- return { ...record, schemaVersion, reportedAt };
260
+ return { ...record2, schemaVersion, reportedAt };
261
261
  }
262
262
  var QUOTA_SUPPORTED_PROVIDERS = [
263
263
  "antigravity-cli",
@@ -300,6 +300,52 @@ function defaultProviderPriorityFromNodeFacts(facts) {
300
300
  return orderProvidersByBuiltinPreference(detected.length ? detected : enabled);
301
301
  }
302
302
 
303
+ // src/quota-freshness.ts
304
+ var QUOTA_RETRY_INFLIGHT_GRACE_MS = 6e4;
305
+ var QUOTA_BACKFILL_HORIZON_MS = 60 * 60 * 1e3;
306
+ function hasUsableWindow(window) {
307
+ return !!window && typeof window.usedPercent === "number" && Number.isFinite(window.usedPercent);
308
+ }
309
+ function hasReading(quota) {
310
+ if (hasUsableWindow(quota.session) || hasUsableWindow(quota.weekly) || hasUsableWindow(quota.monthly)) return true;
311
+ return Array.isArray(quota.buckets) && quota.buckets.some((b) => !!b && typeof b.usedPercent === "number" && Number.isFinite(b.usedPercent));
312
+ }
313
+ function finiteMs(value) {
314
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : void 0;
315
+ }
316
+ function backfillCheckAt(quota, now) {
317
+ const dataDue = finiteMs(quota.updatedAt);
318
+ const attempted = finiteMs(quota.metadata?.fetchedAt);
319
+ const dueAt = Math.max(
320
+ dataDue === void 0 ? Number.NEGATIVE_INFINITY : dataDue + QUOTA_BACKFILL_HORIZON_MS,
321
+ attempted === void 0 ? Number.NEGATIVE_INFINITY : attempted + QUOTA_BACKFILL_HORIZON_MS
322
+ );
323
+ return Number.isFinite(dueAt) && dueAt > now ? dueAt : void 0;
324
+ }
325
+ function assessQuotaFreshness(quota, now = Date.now()) {
326
+ const meta = quota.metadata;
327
+ const kind = meta?.failureKind;
328
+ const userMustAct = kind === "no-data" && quota.provider !== "codex-cli";
329
+ const awaitsCliUse = kind === "expired-token" && ["grok-cli", "kimi", "antigravity-cli"].includes(quota.provider);
330
+ if (userMustAct) return hasReading(quota) ? { cue: "stale", userMustAct: true } : { userMustAct: true };
331
+ if (awaitsCliUse) return hasReading(quota) ? { cue: "stale", userMustAct: false } : { userMustAct: false };
332
+ if (meta?.lastGoodWindows !== true) {
333
+ const measuredAt = finiteMs(quota.updatedAt);
334
+ if (hasReading(quota) && (measuredAt === void 0 || now - measuredAt >= QUOTA_BACKFILL_HORIZON_MS)) {
335
+ return { cue: "stale", userMustAct };
336
+ }
337
+ return { userMustAct };
338
+ }
339
+ const retryAtMs = finiteMs(meta?.retryAtMs);
340
+ const retryStopped = meta?.retryExhausted === true || retryAtMs !== void 0 && retryAtMs + QUOTA_RETRY_INFLIGHT_GRACE_MS < now;
341
+ if (kind !== "no-data" && !retryStopped) return { cue: "refreshing", userMustAct: false };
342
+ const nextCheckAt = backfillCheckAt(quota, now);
343
+ return nextCheckAt === void 0 ? { cue: "stale", userMustAct: false } : { cue: "stale", userMustAct: false, nextCheckAt };
344
+ }
345
+ function minutesUntilQuotaCheck(nextCheckAt, now = Date.now()) {
346
+ return Math.max(1, Math.round((nextCheckAt - now) / 6e4));
347
+ }
348
+
303
349
  // src/workspace-normalize.ts
304
350
  function normalizeMeshWorkspaceForCompare(dir) {
305
351
  if (typeof dir !== "string") return "";
@@ -329,19 +375,21 @@ function isPhantomDaemonEntry(entry) {
329
375
  function machineCoreFromDaemonId(id2) {
330
376
  const trimmed = readString(id2);
331
377
  if (!trimmed) return void 0;
378
+ const lower = trimmed.toLowerCase();
332
379
  for (const prefix of DAEMON_ID_PREFIXES) {
333
- if (trimmed.startsWith(prefix)) {
380
+ if (lower.startsWith(prefix)) {
334
381
  const core = trimmed.slice(prefix.length).trim();
335
- return core || void 0;
382
+ if (!core) return void 0;
383
+ return /^mach_/i.test(core) ? `mach_${core.slice(5)}` : core;
336
384
  }
337
385
  }
338
- return trimmed;
386
+ return /^mach_/i.test(trimmed) ? `mach_${trimmed.slice(5)}` : trimmed;
339
387
  }
340
388
  function canonicalDaemonId(id2) {
341
389
  const core = machineCoreFromDaemonId(id2);
342
390
  if (!core) return void 0;
343
- if (!core.startsWith("mach_")) return core;
344
- return `daemon_${core}`;
391
+ if (!/^mach_/i.test(core)) return core;
392
+ return `daemon_mach_${core.slice(5)}`;
345
393
  }
346
394
  function daemonIdsEquivalent(a, b) {
347
395
  const coreA = machineCoreFromDaemonId(a);
@@ -370,9 +418,9 @@ function expandDaemonIdForms(ids) {
370
418
 
371
419
  // src/git-summarize.ts
372
420
  function summarizeGitShape(status) {
373
- const record = readRecord(status);
374
- if (!Object.keys(record).length) return null;
375
- const submodules = Array.isArray(record.submodules) ? record.submodules.map((entry) => {
421
+ const record2 = readRecord(status);
422
+ if (!Object.keys(record2).length) return null;
423
+ const submodules = Array.isArray(record2.submodules) ? record2.submodules.map((entry) => {
376
424
  const sub = readRecord(entry);
377
425
  return {
378
426
  path: readString(sub.path) ?? null,
@@ -382,23 +430,23 @@ function summarizeGitShape(status) {
382
430
  };
383
431
  }) : [];
384
432
  return {
385
- isGitRepo: readBoolean(record.isGitRepo),
386
- workspace: readString(record.workspace) ?? null,
387
- repoRoot: readString(record.repoRoot, record.repo_root) ?? null,
388
- branch: readString(record.branch) ?? null,
389
- upstream: readString(record.upstream) ?? null,
390
- upstreamStatus: readString(record.upstreamStatus, record.upstream_status) ?? null,
391
- headCommit: readString(record.headCommit, record.head_commit)?.slice(0, 12) ?? null,
392
- ahead: readNumber(record.ahead) ?? null,
393
- behind: readNumber(record.behind) ?? null,
433
+ isGitRepo: readBoolean(record2.isGitRepo),
434
+ workspace: readString(record2.workspace) ?? null,
435
+ repoRoot: readString(record2.repoRoot, record2.repo_root) ?? null,
436
+ branch: readString(record2.branch) ?? null,
437
+ upstream: readString(record2.upstream) ?? null,
438
+ upstreamStatus: readString(record2.upstreamStatus, record2.upstream_status) ?? null,
439
+ headCommit: readString(record2.headCommit, record2.head_commit)?.slice(0, 12) ?? null,
440
+ ahead: readNumber(record2.ahead) ?? null,
441
+ behind: readNumber(record2.behind) ?? null,
394
442
  dirtyCounts: {
395
- staged: readNumber(record.staged) ?? 0,
396
- modified: readNumber(record.modified) ?? 0,
397
- untracked: readNumber(record.untracked) ?? 0,
398
- deleted: readNumber(record.deleted) ?? 0,
399
- renamed: readNumber(record.renamed) ?? 0
443
+ staged: readNumber(record2.staged) ?? 0,
444
+ modified: readNumber(record2.modified) ?? 0,
445
+ untracked: readNumber(record2.untracked) ?? 0,
446
+ deleted: readNumber(record2.deleted) ?? 0,
447
+ renamed: readNumber(record2.renamed) ?? 0
400
448
  },
401
- lastCheckedAt: readNumber(record.lastCheckedAt, record.last_checked_at) ?? null,
449
+ lastCheckedAt: readNumber(record2.lastCheckedAt, record2.last_checked_at) ?? null,
402
450
  submoduleCount: submodules.length,
403
451
  submodules
404
452
  };
@@ -564,10 +612,25 @@ var CLI_SLOT_RECIPES = Object.freeze({
564
612
  ],
565
613
  "antigravity-cli": [
566
614
  {
567
- model: "Gemini 3.1 Pro (High)",
615
+ model: "Gemini 3.8 Flash (High)",
616
+ modelCandidates: ["Gemini 3.8 Flash (High)", "Gemini 4 Argon (Low)", "Gemini 3.7 Flash (High)", "Gemini 3.1 Pro (High)"],
568
617
  difficulty: ["easy"],
569
618
  maxParallel: 2,
570
619
  rationale: "Cheap capacity for easy tasks."
620
+ },
621
+ {
622
+ model: "Gemini 4 Argon (Medium)",
623
+ modelCandidates: ["Gemini 4 Argon (Medium)", "Gemini 3.8 Flash (High)", "Gemini 3.7 Flash (High)", "Gemini 3.1 Pro (High)"],
624
+ difficulty: ["medium"],
625
+ maxParallel: 2,
626
+ rationale: "Balanced Argon tier for medium tasks."
627
+ },
628
+ {
629
+ model: "Gemini 4 Argon (High)",
630
+ modelCandidates: ["Gemini 4 Argon (High)", "Gemini 3.8 Flash (High)", "Gemini 3.1 Pro (High)"],
631
+ difficulty: ["difficult"],
632
+ maxParallel: 1,
633
+ rationale: "Reserved for hard tasks; capped at 1 to bound cost."
571
634
  }
572
635
  ],
573
636
  "cursor-cli": [
@@ -606,6 +669,24 @@ function dedupeDetected(detected) {
606
669
  }
607
670
  return out;
608
671
  }
672
+ function resolveRecipeModel(recipe, modelOptions) {
673
+ if (!Array.isArray(modelOptions) || modelOptions.length === 0) {
674
+ return recipe.model;
675
+ }
676
+ const available = new Set(
677
+ modelOptions.filter((m) => typeof m === "string" && m.trim().length > 0).map((m) => m.trim())
678
+ );
679
+ if (available.size === 0) return recipe.model;
680
+ const candidates = [
681
+ ...recipe.model ? [recipe.model] : [],
682
+ ...recipe.modelCandidates ?? []
683
+ ];
684
+ for (const candidate of candidates) {
685
+ const trimmed = typeof candidate === "string" ? candidate.trim() : "";
686
+ if (trimmed && available.has(trimmed)) return trimmed;
687
+ }
688
+ return recipe.model;
689
+ }
609
690
  function buildSlotProposal(detected, currentSlots = []) {
610
691
  const providers = dedupeDetected(detected ?? []);
611
692
  const proposedSlots = [];
@@ -621,7 +702,7 @@ function buildSlotProposal(detected, currentSlots = []) {
621
702
  for (const recipe of recipes) {
622
703
  const slot = normalizeNodeCapabilitySlot({
623
704
  provider: provider.type,
624
- model: recipe.model,
705
+ model: resolveRecipeModel(recipe, provider.modelOptions),
625
706
  thinkingLevel: recipe.thinkingLevel,
626
707
  difficulty: recipe.difficulty,
627
708
  maxParallel: recipe.maxParallel
@@ -674,7 +755,9 @@ var CANONICAL_MESH_TOOL_NAMES = [
674
755
  "mesh_enqueue_task",
675
756
  "mesh_view_queue",
676
757
  "mesh_queue_cancel",
758
+ "mesh_direct_cancel",
677
759
  "mesh_queue_requeue",
760
+ "mesh_queue_revise",
678
761
  "mesh_send_task",
679
762
  "mesh_read_chat",
680
763
  "mesh_read_debug",
@@ -691,8 +774,11 @@ var CANONICAL_MESH_TOOL_NAMES = [
691
774
  "mesh_list_pending_approvals",
692
775
  "mesh_create",
693
776
  "mesh_add_node",
777
+ "mesh_reattach_source_parent",
778
+ "mesh_attach_remote",
694
779
  "mesh_clone_node",
695
780
  "mesh_remove_node",
781
+ "mesh_retry_node_bootstrap",
696
782
  "mesh_cleanup_worktree_nodes",
697
783
  "mesh_refine_node",
698
784
  "mesh_refine_batch",
@@ -709,8 +795,19 @@ var CANONICAL_MESH_TOOL_NAMES = [
709
795
  "mesh_reconcile_ledger",
710
796
  "mesh_mission_upsert",
711
797
  "mesh_mission_list",
798
+ "mesh_mission_git_eval",
799
+ "mesh_release_upsert",
800
+ "mesh_release_scope",
801
+ "mesh_release_list",
802
+ "mesh_release_record_deploy",
803
+ "mesh_release_changelog_draft",
712
804
  "mesh_review_inbox",
713
- "mesh_node_slots"
805
+ "mesh_node_slots",
806
+ "driver_list",
807
+ "driver_describe",
808
+ "artifact_list",
809
+ "artifact_read",
810
+ "artifact_register"
714
811
  ];
715
812
  var CANONICAL_MESH_TOOL_COUNT = CANONICAL_MESH_TOOL_NAMES.length;
716
813
  var RETIRED_MESH_TOOLS = {
@@ -1020,9 +1117,15 @@ var DAEMON_STATUS_EVENT_NAMES = [
1020
1117
  "agent:waiting_choice",
1021
1118
  "agent:generating_completed",
1022
1119
  "agent:stopped",
1023
- "monitor:no_progress"
1120
+ "monitor:no_progress",
1121
+ // An owner decision (structured missions) needs the owner. Server-bound for the push only;
1122
+ // the dashboard learns about decisions over P2P (`mission_decisions_list`).
1123
+ "agent:decision_needed"
1024
1124
  ];
1025
1125
  var isDaemonStatusEventName = makeTypeGuard(DAEMON_STATUS_EVENT_NAMES);
1126
+ var DECISION_PUSH_QUESTION_MAX = 80;
1127
+ var DECISION_PUSH_OPTION_LABEL_MAX = 24;
1128
+ var DECISION_PUSH_OPTIONS_MAX = 3;
1026
1129
  var RELEASE_CHANNELS = ["stable", "preview"];
1027
1130
  var NPM_UPDATE_TAGS = ["latest", "next"];
1028
1131
  var VERSION_UPDATE_REASONS = ["force_update_below", "major_minor_mismatch", "patch_mismatch", "daemon_ahead"];
@@ -1385,21 +1488,22 @@ function isTerminalSessionRecordStatus(raw) {
1385
1488
  return typeof raw === "string" && TERMINAL_SESSION_RECORD_STATUSES.includes(raw.trim().toLowerCase());
1386
1489
  }
1387
1490
  function isIdleSessionState(state) {
1388
- const record = state && typeof state === "object" ? state : {};
1389
- const status = typeof record.status === "string" ? record.status.trim().toLowerCase() : "";
1491
+ const record2 = state && typeof state === "object" ? state : {};
1492
+ const status = typeof record2.status === "string" ? record2.status.trim().toLowerCase() : "";
1390
1493
  if (isTerminalSessionRecordStatus(status) || isDeadStatus(status)) return false;
1391
- return isReadyStatus(status) || record.activeChat?.status === "waiting_input";
1494
+ return isReadyStatus(status) || record2.activeChat?.status === "waiting_input";
1392
1495
  }
1393
1496
 
1394
1497
  // src/mesh-vocabulary.ts
1395
- var MESH_TASK_STATUSES = ["pending", "assigned", "completed", "failed", "cancelled"];
1396
- var MESH_TERMINAL_TASK_STATUSES = ["completed", "failed", "cancelled"];
1498
+ var MESH_TASK_STATUSES = ["pending", "assigned", "completed", "blocked", "failed", "cancelled"];
1499
+ var MESH_TERMINAL_TASK_STATUSES = ["completed", "blocked", "failed", "cancelled"];
1397
1500
  var MESH_TASK_MODES = ["code_change", "validation", "live_debug_readonly", "launch_app", "convergence"];
1398
1501
  var MESH_TASK_PRIORITIES = ["low", "normal", "high"];
1399
1502
  var MESH_THINKING_LEVELS = ["low", "medium", "high"];
1400
1503
  var MESH_DELIVERY_MODES = ["when_idle", "interrupt"];
1401
1504
  var MESH_SESSION_CLEANUP_MODES = ["preserve", "stop", "delete_stopped", "stop_and_delete"];
1402
1505
  var WORKER_REPORT_OUTCOMES = ["completed", "blocked", "failed"];
1506
+ var WORKER_REPORT_SUMMARY_MAX_CHARS = 8e3;
1403
1507
  var WORKER_BRANCH_STATES = [
1404
1508
  "merged_to_main",
1405
1509
  "pushed_feature_branch_needs_merge",
@@ -1466,6 +1570,7 @@ var SEND_REFUSAL_REASONS = [
1466
1570
  "no_target",
1467
1571
  "bootstrap_pending",
1468
1572
  "duplicate_dispatch",
1573
+ "new_work_held",
1469
1574
  "internal_error"
1470
1575
  ];
1471
1576
  function isSendRefusal(value) {
@@ -1497,6 +1602,14 @@ function isOutboundMessage(value) {
1497
1602
  const candidate = value;
1498
1603
  return isMessageId(candidate.messageId) && typeof candidate.sessionId === "string" && candidate.sessionId.length > 0 && isInputEnvelopeWire(candidate.input) && isOutboundMessageOrigin(candidate.origin) && isSendPolicy(candidate.policy) && typeof candidate.createdAt === "number";
1499
1604
  }
1605
+ var PASTED_OPEN_RE = /^\s*<pasted_content(?:\s+id="[^"]*")?\s*>\s*$/;
1606
+ var PASTED_CLOSE_RE = /^\s*<\/pasted_content(?:\s+id="[^"]*")?\s*>\s*$/;
1607
+ function unwrapPastedContent(text) {
1608
+ const lines = text.replace(/\r\n?/g, "\n").split("\n");
1609
+ const first = lines.findIndex((line) => line.trim());
1610
+ if (first < 0 || !PASTED_OPEN_RE.test(lines[first])) return text;
1611
+ return lines.filter((line) => !PASTED_OPEN_RE.test(line) && !PASTED_CLOSE_RE.test(line)).join("\n");
1612
+ }
1500
1613
 
1501
1614
  // src/mission-brief.ts
1502
1615
  var GOAL_MAX = 500;
@@ -1582,7 +1695,22 @@ var WORKER_TOOLS = [
1582
1695
  "peer_context_pull",
1583
1696
  "git_status",
1584
1697
  "git_log",
1585
- "git_diff"
1698
+ "git_diff",
1699
+ "driver_list",
1700
+ "driver_describe",
1701
+ "driver_invoke",
1702
+ "driver_scaffold",
1703
+ "driver_validate",
1704
+ "driver_export",
1705
+ "driver_install",
1706
+ "artifact_register",
1707
+ "artifact_list",
1708
+ "artifact_read",
1709
+ // Contract versioning (Cut A): exact pinned-unit reads (E2), the explicit
1710
+ // read claim (C1) and the authoritative head/notice pull.
1711
+ "contract_read",
1712
+ "contract_observe",
1713
+ "contract_current"
1586
1714
  ];
1587
1715
  var WORKER_TOOL_SET = new Set(WORKER_TOOLS);
1588
1716
  function isWorkerTool(value) {
@@ -1667,15 +1795,29 @@ function renderCoordinatorWorkerSection() {
1667
1795
  // src/assistant-protocol.ts
1668
1796
  var ASSISTANT_TOOLS = [
1669
1797
  "projects",
1798
+ "environment",
1799
+ "assistant_action",
1800
+ "project_watch",
1670
1801
  "project_status",
1671
1802
  "project_send",
1672
1803
  "project_read",
1673
1804
  "project_add",
1805
+ "project_attach_remote",
1674
1806
  "discover_repos",
1675
1807
  "memory",
1808
+ "memory_search",
1676
1809
  "skill_view",
1677
1810
  "skill_manage",
1678
- "project_note"
1811
+ "project_note",
1812
+ "launch_defaults",
1813
+ "launch_defaults_set",
1814
+ "driver_list",
1815
+ "driver_describe",
1816
+ "artifact_list",
1817
+ "artifact_read",
1818
+ "decision_answer",
1819
+ "decision_request",
1820
+ "session_control"
1679
1821
  ];
1680
1822
  var ASSISTANT_TOOL_SET = new Set(ASSISTANT_TOOLS);
1681
1823
  function isAssistantTool(value) {
@@ -1683,50 +1825,167 @@ function isAssistantTool(value) {
1683
1825
  }
1684
1826
  var ASSISTANT_VERB = {
1685
1827
  // tool verbs
1828
+ driverList: "driver_list",
1829
+ driverDescribe: "driver_describe",
1686
1830
  projects: "assistant_projects",
1831
+ environment: "assistant_environment",
1832
+ action: "assistant_action",
1833
+ watch: "assistant_project_watch",
1834
+ executionState: "assistant_execution_state",
1835
+ executionSettings: "assistant_execution_settings",
1687
1836
  projectStatus: "assistant_project_status",
1688
1837
  projectSend: "assistant_project_send",
1689
1838
  projectRead: "assistant_project_read",
1690
1839
  projectAdd: "assistant_project_add",
1840
+ projectAttachRemote: "assistant_project_attach_remote",
1691
1841
  discoverRepos: "assistant_discover_repos",
1692
1842
  memory: "assistant_memory",
1843
+ /** Pull-only FTS search over the archive tier (memory design 2026-11-01 §3.4). */
1844
+ memorySearch: "assistant_memory_search",
1693
1845
  skillView: "assistant_skill_view",
1694
1846
  skillManage: "assistant_skill_manage",
1695
1847
  projectNote: "assistant_project_note",
1848
+ launchDefaults: "assistant_launch_defaults",
1849
+ launchDefaultsSet: "assistant_launch_defaults_set",
1850
+ artifactList: "assistant_artifact_list",
1851
+ artifactRead: "assistant_artifact_read",
1852
+ /** Owner-decision inbox (structured-missions design 2026-10-28 §6.3): the owner's words recorded as answers. */
1853
+ decisionAnswer: "assistant_decision_answer",
1854
+ /** Register a plain-text question a coordinator put to the owner as a decision item (§5.2). */
1855
+ decisionRequest: "assistant_decision_request",
1856
+ /** Stop / restart / switch the provider of a coordinator, worker or the assistant session (handoff design 2026-11-01 §4). */
1857
+ sessionControl: "assistant_session_control",
1696
1858
  // assistant-side daemon verbs without a tool of the same name
1697
1859
  launch: "launch_assistant",
1698
1860
  pendingRelays: "assistant_pending_relays",
1699
1861
  // owner verbs (dashboard only)
1700
1862
  stagedResolve: "assistant_staged_resolve",
1701
1863
  storeAdmin: "assistant_store_admin",
1702
- importSkills: "assistant_import_skills"
1864
+ importSkills: "assistant_import_skills",
1865
+ /** Owner skill list (attach/view counts, save proposals, recent skill metrics); reads move no counter. */
1866
+ skillsList: "assistant_skills_list",
1867
+ /** Owner: what the assistant remembered recently, with undo handles (memory design §3.2). */
1868
+ memoryDigest: "assistant_memory_digest",
1869
+ /** Owner: reverse one remembered write or one batch (memory design §3.2). Never an assistant tool. */
1870
+ memoryUndo: "assistant_memory_undo",
1871
+ /** Projects the assistant is following (open relay threads) — list / stop following. */
1872
+ threads: "assistant_threads",
1873
+ threadClose: "assistant_thread_close"
1703
1874
  };
1704
1875
  var ASSISTANT_TOOL_VERBS = {
1876
+ driver_list: ASSISTANT_VERB.driverList,
1877
+ driver_describe: ASSISTANT_VERB.driverDescribe,
1705
1878
  projects: ASSISTANT_VERB.projects,
1879
+ environment: ASSISTANT_VERB.environment,
1880
+ assistant_action: ASSISTANT_VERB.action,
1881
+ project_watch: ASSISTANT_VERB.watch,
1706
1882
  project_status: ASSISTANT_VERB.projectStatus,
1707
1883
  project_send: ASSISTANT_VERB.projectSend,
1708
1884
  project_read: ASSISTANT_VERB.projectRead,
1709
1885
  project_add: ASSISTANT_VERB.projectAdd,
1886
+ project_attach_remote: ASSISTANT_VERB.projectAttachRemote,
1710
1887
  discover_repos: ASSISTANT_VERB.discoverRepos,
1711
1888
  memory: ASSISTANT_VERB.memory,
1889
+ memory_search: ASSISTANT_VERB.memorySearch,
1712
1890
  skill_view: ASSISTANT_VERB.skillView,
1713
1891
  skill_manage: ASSISTANT_VERB.skillManage,
1714
- project_note: ASSISTANT_VERB.projectNote
1892
+ project_note: ASSISTANT_VERB.projectNote,
1893
+ launch_defaults: ASSISTANT_VERB.launchDefaults,
1894
+ launch_defaults_set: ASSISTANT_VERB.launchDefaultsSet,
1895
+ artifact_list: ASSISTANT_VERB.artifactList,
1896
+ artifact_read: ASSISTANT_VERB.artifactRead,
1897
+ decision_answer: ASSISTANT_VERB.decisionAnswer,
1898
+ decision_request: ASSISTANT_VERB.decisionRequest,
1899
+ session_control: ASSISTANT_VERB.sessionControl
1715
1900
  };
1716
- var ASSISTANT_WRITE_TOOLS = ["memory", "skill_manage", "project_note", "project_send", "project_add"];
1901
+ var ASSISTANT_WRITE_TOOLS = ["project_watch", "assistant_action", "memory", "skill_manage", "project_note", "project_send", "project_add", "project_attach_remote", "launch_defaults_set", "decision_answer", "decision_request", "session_control"];
1717
1902
  var ASSISTANT_OWNER_VERBS = [
1903
+ ASSISTANT_VERB.executionSettings,
1718
1904
  ASSISTANT_VERB.stagedResolve,
1719
1905
  ASSISTANT_VERB.storeAdmin,
1720
- ASSISTANT_VERB.importSkills
1906
+ ASSISTANT_VERB.importSkills,
1907
+ ASSISTANT_VERB.skillsList,
1908
+ ASSISTANT_VERB.memoryDigest,
1909
+ ASSISTANT_VERB.memoryUndo,
1910
+ ASSISTANT_VERB.threadClose
1721
1911
  ];
1722
1912
  var ASSISTANT_REVIEW_TURN_VERBS = [
1723
1913
  ASSISTANT_VERB.memory,
1914
+ ASSISTANT_VERB.memorySearch,
1724
1915
  ASSISTANT_VERB.skillView,
1725
1916
  ASSISTANT_VERB.skillManage,
1726
1917
  ASSISTANT_VERB.projectNote
1727
1918
  ];
1728
1919
  var ASSISTANT_SESSION_ID_ENV = "ADHDEV_ASSISTANT_SESSION_ID";
1729
1920
  var ASSISTANT_SESSION_ID_ARG = "assistantSessionId";
1921
+ var ASSISTANT_ACCOUNT_SLOT = "personal";
1922
+ var ASSISTANT_REMOTE_PROJECT_COMMAND = "assistant_remote_project";
1923
+ var ASSISTANT_REMOTE_PROJECT_CATALOG_COMMAND = "assistant_remote_project_catalog";
1924
+ var ASSISTANT_REMOTE_PROJECT_ACCESS_COMMAND = "assistant_remote_project_access";
1925
+ var ASSISTANT_REMOTE_FOLLOW_COMMAND = "assistant_remote_follow";
1926
+ var ASSISTANT_FOLLOWER_ALLOWED_OPS = ["status", "read", "poll", "report", "send", "artifact_list", "artifact_read", "decision_list", "decision_answer", "decision_request"];
1927
+ var ASSISTANT_FOLLOWER_ALLOWED_OP_SET = new Set(ASSISTANT_FOLLOWER_ALLOWED_OPS);
1928
+ function isAssistantFollowerAllowedOp(value) {
1929
+ return typeof value === "string" && ASSISTANT_FOLLOWER_ALLOWED_OP_SET.has(value);
1930
+ }
1931
+ var DECISION_OP_IMPLIED_BY = {
1932
+ decision_list: "status",
1933
+ decision_answer: "send",
1934
+ decision_request: "send"
1935
+ };
1936
+ function followerOpPermitted(op, allowedOps) {
1937
+ if (!isAssistantFollowerAllowedOp(op)) return false;
1938
+ if (allowedOps.includes(op)) return true;
1939
+ const implied = DECISION_OP_IMPLIED_BY[op];
1940
+ return implied !== void 0 && allowedOps.includes(implied);
1941
+ }
1942
+ function followedRemoteProjectKey(hostDaemonId, meshId) {
1943
+ const canonHost = canonicalDaemonId(hostDaemonId) ?? hostDaemonId.trim();
1944
+ return `${canonHost}::${meshId.trim()}`;
1945
+ }
1946
+ function sanitizeRemoteRepoIdentity(raw) {
1947
+ if (typeof raw !== "string") return null;
1948
+ const trimmed = raw.trim();
1949
+ if (!trimmed) return null;
1950
+ if (trimmed.startsWith("/") || trimmed.startsWith("./") || trimmed.startsWith("../") || trimmed.startsWith("~/") || trimmed.startsWith("\\") || /^[a-zA-Z]:[\\/]/.test(trimmed) || /^file:/i.test(trimmed)) {
1951
+ return null;
1952
+ }
1953
+ const withoutQuery = trimmed.replace(/[?#].*$/, "").replace(/\/+$/, "");
1954
+ if (!withoutQuery) return null;
1955
+ let host = "";
1956
+ let repoPath = "";
1957
+ if (/^[a-z][a-z0-9+.-]*:\/\//i.test(withoutQuery)) {
1958
+ try {
1959
+ const url = new URL(withoutQuery);
1960
+ if (url.protocol === "file:") return null;
1961
+ host = url.hostname.toLowerCase();
1962
+ repoPath = decodeURIComponent(url.pathname).replace(/^\/+|\/+$/g, "").replace(/\.git$/i, "");
1963
+ } catch {
1964
+ return null;
1965
+ }
1966
+ } else {
1967
+ const scpMatch = withoutQuery.match(/^(?:[^@/:]+@)?(\[[^\]]+\]|[^/:]+):(.+)$/);
1968
+ if (scpMatch) {
1969
+ host = scpMatch[1].replace(/^\[|\]$/g, "").toLowerCase();
1970
+ repoPath = scpMatch[2].replace(/^\/+|\/+$/g, "").replace(/\.git$/i, "");
1971
+ } else {
1972
+ const slash = withoutQuery.indexOf("/");
1973
+ if (slash > 0) {
1974
+ const rawHost = withoutQuery.slice(0, slash);
1975
+ const atIdx = rawHost.lastIndexOf("@");
1976
+ host = (atIdx >= 0 ? rawHost.slice(atIdx + 1) : rawHost).toLowerCase();
1977
+ repoPath = withoutQuery.slice(slash + 1).replace(/^\/+|\/+$/g, "").replace(/\.git$/i, "");
1978
+ }
1979
+ }
1980
+ }
1981
+ if (!host || !repoPath) return null;
1982
+ if (!host.includes(".") && host !== "localhost") return null;
1983
+ if (/[\s@:\\]/.test(host)) return null;
1984
+ const segments = repoPath.split("/").filter(Boolean);
1985
+ if (segments.length === 0) return null;
1986
+ if (segments.some((seg) => seg === "." || seg === ".." || /[\s@:\\]/.test(seg))) return null;
1987
+ return `${host}/${segments.join("/")}`.slice(0, 200);
1988
+ }
1730
1989
 
1731
1990
  // src/turn-evidence.ts
1732
1991
  var MESH_TOPIC_PROTOCOL_VERSION = 2;
@@ -1762,7 +2021,7 @@ var TURN_SCOPES = ["mesh_queue", "mesh_direct", "plain"];
1762
2021
  var RECLAIMING_SEND_REFUSALS = ["session_exited", "no_target", "unsupported_input"];
1763
2022
  var DELIVERY_OUTCOMES = ["delivered", "queued"];
1764
2023
  var DELIVERY_VIAS = ["local", "p2p"];
1765
- var DISPATCH_FAILURE_REASONS = ["worker_absent", "transport_error", "spawn_failed", "rejected_by_worker", "timeout"];
2024
+ var DISPATCH_FAILURE_REASONS = ["worker_absent", "transport_error", "spawn_failed", "rejected_by_worker", "timeout", "submit_unconfirmed"];
1766
2025
  function sanitizeRefusalCode(value) {
1767
2026
  if (typeof value !== "string") return void 0;
1768
2027
  const normalized = value.trim().toLowerCase().replace(/[^a-z_]/g, "_").replace(/_+/g, "_").replace(/^_+|_+$/g, "");
@@ -1772,8 +2031,8 @@ function sanitizeRefusalCode(value) {
1772
2031
  var CONSUME_PROFILES = ["default", "native_source"];
1773
2032
  var SESSION_REBOUND_REASONS = ["restart", "live_holder"];
1774
2033
  var SUSPENSION_MODALS = ["approval", "choice"];
1775
- var SUSPENSION_RESOLUTIONS = ["approved", "rejected", "answered"];
1776
- var SUSPENSION_RESOLUTION_VIAS = ["modal_button", "auto_approve", "prompt_answer"];
2034
+ var SUSPENSION_RESOLUTIONS = ["approved", "rejected", "answered", "dismissed"];
2035
+ var SUSPENSION_RESOLUTION_VIAS = ["modal_button", "auto_approve", "prompt_answer", "modal_disappeared"];
1777
2036
  var TURN_END_STRENGTHS = ["genuine", "weak"];
1778
2037
  var TURN_END_BLOCK_REASONS = [
1779
2038
  "missing_final_assistant",
@@ -1781,9 +2040,9 @@ var TURN_END_BLOCK_REASONS = [
1781
2040
  "terminal_block_hard_cap",
1782
2041
  "decoupled_completion"
1783
2042
  ];
1784
- var NATIVE_TURN_OUTCOMES = ["completed", "aborted"];
2043
+ var NATIVE_TURN_OUTCOMES = ["completed", "aborted", "failed"];
1785
2044
  var LIVENESS_RESULTS = ["alive", "unknown", "read_failed", "dead"];
1786
- var PROVIDER_FAILURES = ["auth_failed", "billing_failed"];
2045
+ var PROVIDER_FAILURES = ["auth_failed", "billing_failed", "usage_limit_exceeded", "server_overloaded", "provider_error"];
1787
2046
  var SESSION_ERROR_REASONS = ["provider_error", "adapter_error", "spawn_failed", "auth_failed", "billing_failed", "unknown", "daemon_restart"];
1788
2047
  var CANCEL_REASONS = ["operator_cancel", "intentional_cleanup", "task_removed", "mission_abandoned", "superseded"];
1789
2048
  var OPERATOR_STATUSES = ["completed", "failed"];
@@ -1810,9 +2069,10 @@ var HOLD_REASONS = [
1810
2069
  // — a turn_end commits the report (R9t), expiry commits it anyway (R13t) so
1811
2070
  // a session whose FSM never shows the idle edge again does not wait for
1812
2071
  // liveness / hard_ceiling.
1813
- "await_end"
2072
+ "await_end",
2073
+ "report_correction"
1814
2074
  ];
1815
- var TURN_OUTCOMES = ["completed", "failed", "cancelled"];
2075
+ var TURN_OUTCOMES = ["completed", "blocked", "failed", "cancelled"];
1816
2076
  var COMMIT_STRENGTHS = ["genuine", "weak", "tool_report", "operator"];
1817
2077
  var TURN_REASONS = [
1818
2078
  // commits
@@ -1821,9 +2081,15 @@ var TURN_REASONS = [
1821
2081
  "transcript_final",
1822
2082
  "worker_reported",
1823
2083
  "finalization_timeout_no_response",
2084
+ "weak_end_liveness_unconfirmed",
2085
+ "weak_end_probe_unobserved",
2086
+ "report_correction_expired",
1824
2087
  "session_error",
1825
2088
  "provider_auth_failed",
1826
2089
  "provider_billing_failed",
2090
+ "provider_usage_limit_exceeded",
2091
+ "provider_server_overloaded",
2092
+ "provider_error",
1827
2093
  "operator_cancel",
1828
2094
  "intentional_cleanup",
1829
2095
  "task_removed",
@@ -1851,6 +2117,7 @@ var TURN_REASONS = [
1851
2117
  ];
1852
2118
  var NOTIFY_KINDS = [
1853
2119
  "completed",
2120
+ "blocked",
1854
2121
  "failed",
1855
2122
  "cancelled",
1856
2123
  "stopped",
@@ -1900,8 +2167,8 @@ var TURN_EVIDENCE_FIELD_SPECS = {
1900
2167
  duplicate_dispatch_refusal: { holderSessionId: id, holderAttemptId: idOpt },
1901
2168
  session_rebound: { toSessionId: id, reason: en(SESSION_REBOUND_REASONS) },
1902
2169
  turn_started: { retro: bool },
1903
- suspension: { modal: en(SUSPENSION_MODALS), modalKey: idOpt },
1904
- suspension_resolved: { resolution: en(SUSPENSION_RESOLUTIONS), via: en(SUSPENSION_RESOLUTION_VIAS) },
2170
+ suspension: { modal: en(SUSPENSION_MODALS), modalKey: idOpt, providerSetup: boolOpt, clockUnknown: boolOpt },
2171
+ suspension_resolved: { resolution: en(SUSPENSION_RESOLUTIONS), via: en(SUSPENSION_RESOLUTION_VIAS), modalKey: idOpt },
1905
2172
  turn_end: {
1906
2173
  strength: en(TURN_END_STRENGTHS),
1907
2174
  afterFinalizationTimeout: boolOpt,
@@ -1911,6 +2178,7 @@ var TURN_EVIDENCE_FIELD_SPECS = {
1911
2178
  releasedByHardCap: boolOpt,
1912
2179
  nativeOutcome: enOpt(NATIVE_TURN_OUTCOMES),
1913
2180
  live: { t: "live", optional: true },
2181
+ nativeMarker: { t: "native_marker", optional: true },
1914
2182
  reportExpected: boolOpt,
1915
2183
  providerFailure: enOpt(PROVIDER_FAILURES)
1916
2184
  },
@@ -1924,7 +2192,7 @@ var TURN_EVIDENCE_FIELD_SPECS = {
1924
2192
  },
1925
2193
  transcript_activity: { newestActivityAt: ms },
1926
2194
  no_progress: { stalledMs: ms, observedStatus: en(NO_PROGRESS_OBSERVED_STATUSES), finalAssistantPresent: bool },
1927
- liveness: { result: en(LIVENESS_RESULTS) },
2195
+ liveness: { result: en(LIVENESS_RESULTS), probeStartedAtMs: msOpt },
1928
2196
  process_exit: { exitCode: { t: "int", nullable: true }, providerFailure: enOpt(PROVIDER_FAILURES) },
1929
2197
  session_error: { reason: en(SESSION_ERROR_REASONS) },
1930
2198
  worker_report: {
@@ -1934,6 +2202,7 @@ var TURN_EVIDENCE_FIELD_SPECS = {
1934
2202
  branchState: enOpt(WORKER_BRANCH_STATES),
1935
2203
  touchedFileCount: intOpt
1936
2204
  },
2205
+ worker_report_correction_requested: { deliveryId: { t: "id", optional: true } },
1937
2206
  worker_progress: { note: { t: "summary_ref", optional: true } },
1938
2207
  git_side_effect: { dirty: bool, commitsSinceDispatch: { t: "int" }, attributable: bool },
1939
2208
  cancel: { reason: en(CANCEL_REASONS) },
@@ -1981,7 +2250,7 @@ function isLiveTurnPending(value) {
1981
2250
  return isRecord2(value) && hasOnlyKeys(value, ["modal", "adapterPending", "trailingTool", "newestActivityAt"]) && typeof value.modal === "boolean" && typeof value.adapterPending === "boolean" && typeof value.trailingTool === "boolean" && (value.newestActivityAt === void 0 || isFiniteNumber2(value.newestActivityAt));
1982
2251
  }
1983
2252
  function isNativeMarkerRef(value) {
1984
- return isRecord2(value) && hasOnlyKeys(value, ["outcome", "turnId"]) && NATIVE_TURN_OUTCOMES.includes(value.outcome) && (value.turnId === void 0 || isEvidenceIdentifier(value.turnId));
2253
+ return isRecord2(value) && hasOnlyKeys(value, ["outcome", "turnId", "receivedAt", "startedAt", "errorAt"]) && NATIVE_TURN_OUTCOMES.includes(value.outcome) && (value.turnId === void 0 || isEvidenceIdentifier(value.turnId)) && ["receivedAt", "startedAt", "errorAt"].every((key) => value[key] === void 0 || isFiniteNumber2(value[key]));
1985
2254
  }
1986
2255
  function isCoordinatorIdentity(value) {
1987
2256
  return isRecord2(value) && hasOnlyKeys(value, ["daemonId", "coordinatorRunId", "sessionId"]) && isEvidenceIdentifier(value.daemonId) && isEvidenceIdentifier(value.coordinatorRunId) && (value.sessionId === void 0 || isEvidenceIdentifier(value.sessionId));
@@ -2104,17 +2373,89 @@ function projectTurnEvidenceEntry(evidence, attempt) {
2104
2373
  };
2105
2374
  }
2106
2375
 
2376
+ // src/launch-defaults.ts
2377
+ var LAUNCH_DEFAULT_ROLES = ["assistant", "coordinator"];
2378
+ var LAUNCH_DEFAULT_SOURCES = ["user", "stored_default", "project_default", "provider_default"];
2379
+ var LAUNCH_DEFAULTS_NEXT_LAUNCH_NOTE = "Applies to the next launch; running sessions are unchanged.";
2380
+ function isLaunchDefaultRole(value) {
2381
+ return typeof value === "string" && LAUNCH_DEFAULT_ROLES.includes(value);
2382
+ }
2383
+ function isLaunchDefaultSource(value) {
2384
+ return typeof value === "string" && LAUNCH_DEFAULT_SOURCES.includes(value);
2385
+ }
2386
+ var LAUNCH_DEFAULT_ERROR_CODES = [
2387
+ "invalid_args",
2388
+ "launch_default_required",
2389
+ "launch_default_unavailable",
2390
+ "launch_selection_invalid",
2391
+ "launch_default_invalid",
2392
+ "revision_conflict",
2393
+ "store_unavailable",
2394
+ "store_busy",
2395
+ "persistence_failed",
2396
+ "project_not_found",
2397
+ "project_ambiguous",
2398
+ "project_not_hosted",
2399
+ "project_storage_unavailable",
2400
+ "staging_unavailable",
2401
+ "staging_failed",
2402
+ "review_turn_tool_denied"
2403
+ ];
2404
+
2405
+ // src/role-launch.ts
2406
+ function record(value) {
2407
+ return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
2408
+ }
2409
+ function ref(value) {
2410
+ const r = record(value);
2411
+ if (!r || !isLaunchDefaultRole(r.role) || r.scope !== "global" && r.scope !== "project" || !Number.isSafeInteger(r.revision) || r.revision < 1 || r.scope === "project" && (typeof r.projectId !== "string" || !r.projectId)) return void 0;
2412
+ return {
2413
+ role: r.role,
2414
+ scope: r.scope,
2415
+ revision: r.revision,
2416
+ ...r.scope === "project" ? { projectId: r.projectId } : {}
2417
+ };
2418
+ }
2419
+ function axis(value) {
2420
+ const a = record(value);
2421
+ if (!a || !isLaunchDefaultSource(a.source) || a.value !== null && typeof a.value !== "string") return void 0;
2422
+ const defaultRef = ref(a.defaultRef);
2423
+ if (a.source === "stored_default" && defaultRef?.scope !== "global" || a.source === "project_default" && defaultRef?.scope !== "project" || (a.source === "user" || a.source === "provider_default") && a.defaultRef !== void 0) return void 0;
2424
+ return { value: a.value, source: a.source, ...defaultRef ? { defaultRef } : {} };
2425
+ }
2426
+ function parseRoleLaunchSelection(value) {
2427
+ const r = record(value), s = record(r?.selection), a = record(r?.applied);
2428
+ if (!r || !isLaunchDefaultRole(r.role) || !s || typeof s.provider !== "string" || !s.provider || !Number.isSafeInteger(r.documentRevision) || r.documentRevision < 1 || s.model !== void 0 && typeof s.model !== "string" || s.thinkingLevel !== void 0 && typeof s.thinkingLevel !== "string") return void 0;
2429
+ const provider = axis(a?.provider), model = axis(a?.model), thinkingLevel = axis(a?.thinkingLevel);
2430
+ if (!provider || !model || !thinkingLevel || [provider, model, thinkingLevel].some((axis2) => axis2.defaultRef && (axis2.defaultRef.role !== r.role || axis2.defaultRef.scope === "global" && axis2.defaultRef.revision > r.documentRevision)) || provider.value !== s.provider || model.value !== (s.model ?? null) || thinkingLevel.value !== (s.thinkingLevel ?? null)) return void 0;
2431
+ const defaultRef = ref(r.defaultRef);
2432
+ return {
2433
+ role: r.role,
2434
+ selection: {
2435
+ provider: s.provider,
2436
+ ...typeof s.model === "string" ? { model: s.model } : {},
2437
+ ...typeof s.thinkingLevel === "string" ? { thinkingLevel: s.thinkingLevel } : {}
2438
+ },
2439
+ applied: { provider, model, thinkingLevel },
2440
+ ...defaultRef ? { defaultRef } : {},
2441
+ documentRevision: r.documentRevision
2442
+ };
2443
+ }
2444
+
2107
2445
  // src/session-launch.ts
2108
2446
  var MODEL_AXIS_SOURCES = [
2109
2447
  /** Picked explicitly for this launch (dashboard dropdown, coordinator dialog). */
2110
2448
  "user",
2111
2449
  /** The dashboard dialog restored it from the last launch (browser-local memory). */
2112
2450
  "remembered",
2451
+ /** The authoritative daemon role default or host project override. */
2452
+ "stored_default",
2453
+ "project_default",
2113
2454
  /** A mesh capability slot supplied it (or a difficulty preset the slot outranked). */
2114
2455
  "mesh_slot",
2115
2456
  /** An explicit per-task model / thinking level on a mesh queue task. */
2116
2457
  "task_override",
2117
- /** Nothing was requested; the provider's default is known (discovery / manifest). */
2458
+ /** Nothing requested: the provider chooses; resolvedDefault records it when known. */
2118
2459
  "provider_default",
2119
2460
  /** A value was requested without saying where it came from, or nothing is known. */
2120
2461
  "unspecified"
@@ -2158,10 +2499,10 @@ function readFiniteNumber(value) {
2158
2499
  }
2159
2500
  function parseModelSelection(raw) {
2160
2501
  if (!raw || typeof raw !== "object") return void 0;
2161
- const record = raw;
2502
+ const record2 = raw;
2162
2503
  const history = [];
2163
- if (Array.isArray(record.history)) {
2164
- for (const entry of record.history) {
2504
+ if (Array.isArray(record2.history)) {
2505
+ for (const entry of record2.history) {
2165
2506
  if (!entry || typeof entry !== "object") continue;
2166
2507
  const e = entry;
2167
2508
  const value = readString(e.value);
@@ -2170,41 +2511,45 @@ function parseModelSelection(raw) {
2170
2511
  if (value && at !== void 0 && via) history.push({ at, value, via });
2171
2512
  }
2172
2513
  }
2173
- const requested = readString(record.requested);
2174
- const launchValue = readString(record.launchValue);
2175
- const resolvedDefault = readString(record.resolvedDefault);
2176
- const current = readString(record.current);
2177
- const observed = readString(record.observed);
2178
- const observedAt = readFiniteNumber(record.observedAt);
2514
+ const requested = readString(record2.requested);
2515
+ const launchValue = readString(record2.launchValue);
2516
+ const resolvedDefault = readString(record2.resolvedDefault);
2517
+ const current = readString(record2.current);
2518
+ const observed = readString(record2.observed);
2519
+ const observedAt = readFiniteNumber(record2.observedAt);
2520
+ const fallback = record2.fallback === true;
2179
2521
  return {
2180
- source: isModelAxisSource(record.source) ? record.source : "unspecified",
2522
+ source: isModelAxisSource(record2.source) ? record2.source : "unspecified",
2181
2523
  ...requested ? { requested } : {},
2182
2524
  ...launchValue ? { launchValue } : {},
2183
2525
  ...resolvedDefault ? { resolvedDefault } : {},
2184
2526
  ...current ? { current } : {},
2185
2527
  ...observed ? { observed } : {},
2186
2528
  ...observedAt !== void 0 ? { observedAt } : {},
2529
+ ...fallback ? { fallback } : {},
2187
2530
  history: history.slice(-MODEL_SELECTION_HISTORY_LIMIT)
2188
2531
  };
2189
2532
  }
2190
2533
  function parseSessionLaunchRecord(raw) {
2191
2534
  if (!raw || typeof raw !== "object") return void 0;
2192
- const record = raw;
2193
- const sessionId = readString(record.sessionId);
2194
- const providerType = readString(record.providerType);
2195
- const launchedAt = readFiniteNumber(record.launchedAt);
2196
- const model = parseModelSelection(record.model);
2197
- const thinkingLevel = parseModelSelection(record.thinkingLevel);
2535
+ const record2 = raw;
2536
+ const sessionId = readString(record2.sessionId);
2537
+ const providerType = readString(record2.providerType);
2538
+ const launchedAt = readFiniteNumber(record2.launchedAt);
2539
+ const model = parseModelSelection(record2.model);
2540
+ const thinkingLevel = parseModelSelection(record2.thinkingLevel);
2198
2541
  if (!sessionId || !providerType || launchedAt === void 0 || !model || !thinkingLevel) return void 0;
2199
- const providerVersion = readString(record.providerVersion);
2200
- const workspace = readString(record.workspace);
2201
- const autoApproveModeId = readString(record.autoApproveModeId);
2542
+ const providerVersion = readString(record2.providerVersion);
2543
+ const workspace = readString(record2.workspace);
2544
+ const autoApproveModeId = readString(record2.autoApproveModeId);
2545
+ const roleLaunch = parseRoleLaunchSelection(record2.roleLaunch);
2202
2546
  return {
2547
+ ...roleLaunch ? { roleLaunch } : {},
2203
2548
  sessionId,
2204
2549
  providerType,
2205
2550
  ...providerVersion ? { providerVersion } : {},
2206
- ...record.providerChannel === "stable" || record.providerChannel === "preview" ? { providerChannel: record.providerChannel } : {},
2207
- launchedBy: isSessionLaunchedBy(record.launchedBy) ? record.launchedBy : "api",
2551
+ ...record2.providerChannel === "stable" || record2.providerChannel === "preview" ? { providerChannel: record2.providerChannel } : {},
2552
+ launchedBy: isSessionLaunchedBy(record2.launchedBy) ? record2.launchedBy : "api",
2208
2553
  launchedAt,
2209
2554
  ...workspace ? { workspace } : {},
2210
2555
  model,
@@ -2268,7 +2613,7 @@ function isTurnAttemptRefValue(value) {
2268
2613
  function isTurnObserveResponse(value) {
2269
2614
  return isRecord(value) && hasOnlyKeys2(value, ["verdict", "attemptRef", "outcome"]) && isTurnObserveVerdict(value.verdict) && isTurnAttemptRefValue(value.attemptRef) && (value.outcome === void 0 || isTurnOutcomeValue(value.outcome));
2270
2615
  }
2271
- var TURN_OUTCOMES_LOCAL = ["completed", "failed", "cancelled"];
2616
+ var TURN_OUTCOMES_LOCAL = ["completed", "blocked", "failed", "cancelled"];
2272
2617
  function isTurnOutcomeValue(value) {
2273
2618
  return typeof value === "string" && TURN_OUTCOMES_LOCAL.includes(value);
2274
2619
  }
@@ -2494,8 +2839,23 @@ function isMissionBriefWire(value) {
2494
2839
  }
2495
2840
  return true;
2496
2841
  }
2842
+ var STRUCTURED_MISSION_KEYS = ["summary", "releaseNote", "outcome", "outcomeReason", "version", "carryOver", "openItems"];
2843
+ function isOpenItemCountsWire(value) {
2844
+ if (!isRecord(value) || !hasOnlyKeys2(value, ["remaining", "live_check", "decision", "evidence"])) return false;
2845
+ return ["remaining", "live_check", "decision", "evidence"].every((k) => isNonNegativeInt(value[k]));
2846
+ }
2847
+ function isStructuredMissionFields(value) {
2848
+ for (const k of ["summary", "releaseNote", "outcome", "outcomeReason"]) {
2849
+ if (value[k] !== void 0 && typeof value[k] !== "string") return false;
2850
+ }
2851
+ if (value.version !== void 0 && !isNonNegativeInt(value.version)) return false;
2852
+ if (value.carryOver !== void 0 && typeof value.carryOver !== "boolean") return false;
2853
+ if (value.openItems !== void 0 && !isOpenItemCountsWire(value.openItems)) return false;
2854
+ return true;
2855
+ }
2497
2856
  function isMeshMissionRecordWire(value) {
2498
- if (!isRecord(value) || !hasOnlyKeys2(value, ["id", "meshId", "title", "goal", "status", "brief"])) return false;
2857
+ if (!isRecord(value) || !hasOnlyKeys2(value, ["id", "meshId", "title", "goal", "status", "brief", ...STRUCTURED_MISSION_KEYS])) return false;
2858
+ if (!isStructuredMissionFields(value)) return false;
2499
2859
  if (!isEvidenceIdentifier(value.id) || !isEvidenceIdentifier(value.meshId)) return false;
2500
2860
  if (typeof value.title !== "string" || typeof value.goal !== "string") return false;
2501
2861
  if (!isMeshMissionStatusValue(value.status)) return false;
@@ -2503,11 +2863,22 @@ function isMeshMissionRecordWire(value) {
2503
2863
  return true;
2504
2864
  }
2505
2865
  function isMissionUpsertRequest(value) {
2506
- if (!isRecord(value) || !hasOnlyKeys2(value, ["v", "meshId", "id", "title", "goal", "status", "brief"])) return false;
2866
+ if (!isRecord(value) || !hasOnlyKeys2(value, ["v", "meshId", "id", "title", "goal", "status", "brief", "structured", "summary", "releaseNote", "outcome", "outcomeReason", "carryOverTo", "toCarryOver", "itemsAdd", "itemsUpdate"])) return false;
2507
2867
  if (value.v !== TURN_IPC_PROTOCOL_VERSION) return false;
2508
2868
  if (!isEvidenceIdentifier(value.meshId)) return false;
2509
2869
  if (value.id !== void 0 && !isEvidenceIdentifier(value.id)) return false;
2510
- if (typeof value.title !== "string" || value.title.trim().length === 0) return false;
2870
+ if (typeof value.title !== "string") return false;
2871
+ if (value.title.trim().length === 0 && value.toCarryOver !== true && value.id === void 0) return false;
2872
+ if (value.structured !== void 0 && typeof value.structured !== "boolean") return false;
2873
+ if (value.toCarryOver !== void 0 && typeof value.toCarryOver !== "boolean") return false;
2874
+ for (const k of ["summary", "releaseNote", "outcome", "outcomeReason"]) {
2875
+ if (value[k] !== void 0 && typeof value[k] !== "string") return false;
2876
+ }
2877
+ if (value.carryOverTo !== void 0 && !isEvidenceIdentifier(value.carryOverTo)) return false;
2878
+ for (const k of ["itemsAdd", "itemsUpdate"]) {
2879
+ const list = value[k];
2880
+ if (list !== void 0 && (!Array.isArray(list) || list.length > 500 || !list.every(isRecord))) return false;
2881
+ }
2511
2882
  if (value.goal !== void 0 && typeof value.goal !== "string") return false;
2512
2883
  if (value.status !== void 0 && !isMeshMissionStatusValue(value.status)) return false;
2513
2884
  if (value.brief !== void 0 && value.brief !== null && !isMissionBriefWire(value.brief)) return false;
@@ -2517,7 +2888,7 @@ function decodeMissionUpsertRequest(value) {
2517
2888
  return isMissionUpsertRequest(value) ? value : null;
2518
2889
  }
2519
2890
  function isMissionUpsertResponse(value) {
2520
- return isRecord(value) && hasOnlyKeys2(value, ["mission"]) && isMeshMissionRecordWire(value.mission);
2891
+ return isRecord(value) && hasOnlyKeys2(value, ["mission", "result"]) && isMeshMissionRecordWire(value.mission) && (value.result === void 0 || isRecord(value.result));
2521
2892
  }
2522
2893
  function decodeMissionUpsertResponse(value) {
2523
2894
  return isMissionUpsertResponse(value) ? value : null;
@@ -2543,7 +2914,10 @@ function decodeMissionQueryResponse(value) {
2543
2914
  return isMissionQueryResponse(value) ? value : null;
2544
2915
  }
2545
2916
  function isMissionListQueryRequest(value) {
2546
- if (!isRecord(value) || !hasOnlyKeys2(value, ["v", "meshId", "statuses", "verbose", "withStats", "limit", "historyIdLimit", "meshStatusView"])) return false;
2917
+ if (!isRecord(value) || !hasOnlyKeys2(value, ["v", "meshId", "statuses", "verbose", "withStats", "limit", "historyIdLimit", "meshStatusView", "structured", "items", "history"])) return false;
2918
+ for (const k of ["structured", "items", "history"]) {
2919
+ if (value[k] !== void 0 && typeof value[k] !== "boolean") return false;
2920
+ }
2547
2921
  if (value.meshStatusView !== void 0 && value.meshStatusView !== "compact" && value.meshStatusView !== "verbose") return false;
2548
2922
  if (value.v !== TURN_IPC_PROTOCOL_VERSION) return false;
2549
2923
  if (!isEvidenceIdentifier(value.meshId)) return false;
@@ -2569,12 +2943,13 @@ function isMeshMissionTaskAggregateWire(value) {
2569
2943
  return value.lastActivityAt === null || typeof value.lastActivityAt === "string";
2570
2944
  }
2571
2945
  function isMeshMissionStatsWire(value) {
2572
- const keys = ["missionId", "taskCount", "completed", "failed", "totalDurationMs", "wallClockMs", "retries", "incompleteTaskIds"];
2946
+ const keys = ["missionId", "taskCount", "completed", "failed", "blocked", "totalDurationMs", "wallClockMs", "retries", "incompleteTaskIds"];
2573
2947
  if (!isRecord(value) || !hasOnlyKeys2(value, keys)) return false;
2574
2948
  if (!isEvidenceIdentifier(value.missionId)) return false;
2575
2949
  for (const k of ["taskCount", "completed", "failed", "totalDurationMs", "retries"]) {
2576
2950
  if (!isNonNegativeInt(value[k])) return false;
2577
2951
  }
2952
+ if (value.blocked !== void 0 && !isNonNegativeInt(value.blocked)) return false;
2578
2953
  if (value.wallClockMs !== null && !isNonNegativeInt(value.wallClockMs)) return false;
2579
2954
  if (!Array.isArray(value.incompleteTaskIds) || !value.incompleteTaskIds.every(isEvidenceIdentifier)) return false;
2580
2955
  return true;
@@ -2584,7 +2959,7 @@ function isMissionListSummaryWire(value) {
2584
2959
  const hasGoal = "goal" in value;
2585
2960
  const hasPreview = "goalPreview" in value && "goalTruncated" in value;
2586
2961
  if (hasGoal === hasPreview) return false;
2587
- const baseKeys = ["id", "meshId", "title", "status", "tasks", "stats", "brief", "createdAt", "updatedAt", "closeCandidateEmittedAt"];
2962
+ const baseKeys = ["id", "meshId", "title", "status", "tasks", "stats", "brief", "createdAt", "updatedAt", "closeCandidateEmittedAt", ...STRUCTURED_MISSION_KEYS, "items", "history"];
2588
2963
  const allowed = hasGoal ? [...baseKeys, "goal"] : [...baseKeys, "goalPreview", "goalTruncated"];
2589
2964
  if (!hasOnlyKeys2(value, allowed)) return false;
2590
2965
  if (!isEvidenceIdentifier(value.id) || !isEvidenceIdentifier(value.meshId)) return false;
@@ -2598,6 +2973,10 @@ function isMissionListSummaryWire(value) {
2598
2973
  if (value.createdAt !== void 0 && typeof value.createdAt !== "string") return false;
2599
2974
  if (value.updatedAt !== void 0 && typeof value.updatedAt !== "string") return false;
2600
2975
  if (value.closeCandidateEmittedAt !== void 0 && value.closeCandidateEmittedAt !== null && typeof value.closeCandidateEmittedAt !== "string") return false;
2976
+ if (!isStructuredMissionFields(value)) return false;
2977
+ for (const k of ["items", "history"]) {
2978
+ if (value[k] !== void 0 && (!Array.isArray(value[k]) || !value[k].every(isRecord))) return false;
2979
+ }
2601
2980
  return true;
2602
2981
  }
2603
2982
  function isMeshMissionHistoryFoldWire(value) {
@@ -2696,12 +3075,13 @@ function isLedgerQueryEntryWire(value) {
2696
3075
  return true;
2697
3076
  }
2698
3077
  function isLedgerQuerySummaryWire(value) {
2699
- const keys = ["meshId", "totalEntries", "taskDispatched", "taskCompleted", "taskFailed", "taskStalled", "sessionLaunched", "checkpointCreated", "lastActivityAt", "recentFailures"];
3078
+ const keys = ["meshId", "totalEntries", "taskDispatched", "taskCompleted", "taskFailed", "taskBlocked", "taskStalled", "sessionLaunched", "checkpointCreated", "lastActivityAt", "recentFailures"];
2700
3079
  if (!isRecord(value) || !hasOnlyKeys2(value, keys)) return false;
2701
3080
  if (!isEvidenceIdentifier(value.meshId)) return false;
2702
3081
  for (const k of ["totalEntries", "taskDispatched", "taskCompleted", "taskFailed", "taskStalled", "sessionLaunched", "checkpointCreated", "recentFailures"]) {
2703
3082
  if (!isNonNegativeInt(value[k])) return false;
2704
3083
  }
3084
+ if (value.taskBlocked !== void 0 && !isNonNegativeInt(value.taskBlocked)) return false;
2705
3085
  if (value.lastActivityAt !== null && typeof value.lastActivityAt !== "string") return false;
2706
3086
  return true;
2707
3087
  }
@@ -2745,9 +3125,10 @@ function isQueueDependencyHeadWire(value) {
2745
3125
  return isRecord(value) && hasOnlyKeys2(value, ["id", "status", "cancelReason"]) && typeof value.id === "string" && typeof value.status === "string" && (value.cancelReason === void 0 || typeof value.cancelReason === "string");
2746
3126
  }
2747
3127
  function isQueueQueryResponse(value) {
2748
- if (!isRecord(value) || !hasOnlyKeys2(value, ["entries", "counts", "oldHistoricalCount", "dependencyHeads"])) return false;
3128
+ if (!isRecord(value) || !hasOnlyKeys2(value, ["entries", "counts", "oldHistoricalCount", "legacyReportedBlockedCount", "dependencyHeads"])) return false;
2749
3129
  if (!Array.isArray(value.entries) || !value.entries.every(isQueueEntryWire)) return false;
2750
3130
  if (value.counts !== void 0 && (!isRecord(value.counts) || !Object.values(value.counts).every(isNonNegativeInt))) return false;
3131
+ if (value.legacyReportedBlockedCount !== void 0 && !isNonNegativeInt(value.legacyReportedBlockedCount)) return false;
2751
3132
  if (value.oldHistoricalCount !== void 0 && !isNonNegativeInt(value.oldHistoricalCount)) return false;
2752
3133
  if (value.dependencyHeads !== void 0 && (!Array.isArray(value.dependencyHeads) || !value.dependencyHeads.every(isQueueDependencyHeadWire))) return false;
2753
3134
  return true;
@@ -2869,6 +3250,17 @@ function isRecoveryContextQueryResponse(value) {
2869
3250
  function decodeRecoveryContextQueryResponse(value) {
2870
3251
  return isRecoveryContextQueryResponse(value) ? value : null;
2871
3252
  }
3253
+ function decodeQueueReviseRequest(value) {
3254
+ if (!isRecord(value) || !hasOnlyKeys2(value, ["v", "meshId", "taskId", "expectedRevision", "patch"]) || value.v !== TURN_IPC_PROTOCOL_VERSION || !isEvidenceIdentifier(value.meshId) || !isEvidenceIdentifier(value.taskId) || !Number.isSafeInteger(value.expectedRevision) || value.expectedRevision < 0 || !isRecord(value.patch) || !Object.keys(value.patch).length || !hasOnlyKeys2(value.patch, ["message", "ownedPaths", "phase", "dependsOn", "routingPreferences", "review"])) return null;
3255
+ const p = value.patch;
3256
+ if (p.message !== void 0 && (typeof p.message !== "string" || !p.message.trim())) return null;
3257
+ if (p.phase !== void 0 && p.phase !== "source" && p.phase !== "integration") return null;
3258
+ for (const key of ["ownedPaths", "dependsOn"]) {
3259
+ if (p[key] !== void 0 && (!Array.isArray(p[key]) || !p[key].every((x) => typeof x === "string" && !!x.trim()))) return null;
3260
+ }
3261
+ return value;
3262
+ }
3263
+ var decodeQueueReviseResponse = decodeQueueRequeueResponse;
2872
3264
 
2873
3265
  // src/turn-ipc-stats.ts
2874
3266
  function isTaskStatsQueryRequest(value) {
@@ -2967,6 +3359,7 @@ var TURN_IPC_COMMANDS = [
2967
3359
  "queue_enqueue_batch",
2968
3360
  "queue_cancel",
2969
3361
  "queue_requeue",
3362
+ "queue_revise",
2970
3363
  "direct_dispatch_record",
2971
3364
  "active_work_query",
2972
3365
  "recovery_context_query",
@@ -3050,14 +3443,11 @@ function normalizeOwnedPaths(input) {
3050
3443
  }
3051
3444
  function entryContains(base, path) {
3052
3445
  if (path === base.path) return true;
3053
- if (base.subtree && (path === base.path || path.startsWith(`${base.path}/`))) return true;
3446
+ if (base.subtree && (base.path === "" || path.startsWith(`${base.path}/`))) return true;
3054
3447
  return false;
3055
3448
  }
3056
3449
  function entriesOverlap(a, b) {
3057
- if (a.path === b.path) return true;
3058
- if (a.subtree && (b.path === a.path || b.path.startsWith(`${a.path}/`))) return true;
3059
- if (b.subtree && (a.path === b.path || a.path.startsWith(`${b.path}/`))) return true;
3060
- return false;
3450
+ return entryContains(a, b.path) || entryContains(b, a.path);
3061
3451
  }
3062
3452
  function pathsOverlap(a, b) {
3063
3453
  if (a.paths.length === 0 || b.paths.length === 0) return false;
@@ -3109,6 +3499,357 @@ function touchedFilesOutsideOwnership(touched, owned) {
3109
3499
  return { undeclaredTouched, unusedDeclarations };
3110
3500
  }
3111
3501
 
3502
+ // src/mission-items.ts
3503
+ var MISSION_ITEM_KINDS = ["remaining", "live_check", "decision", "evidence"];
3504
+ var MISSION_ITEM_STATES = ["open", "done", "failed", "dropped", "moved", "answered", "expired", "withdrawn", "superseded"];
3505
+ var COORDINATOR_SETTABLE_ITEM_STATES = {
3506
+ remaining: ["open", "done", "dropped"],
3507
+ live_check: ["open", "done", "dropped"],
3508
+ evidence: ["open", "done", "dropped"],
3509
+ decision: ["open", "withdrawn", "superseded"]
3510
+ };
3511
+ var MISSION_OUTCOMES = ["merged", "verified_live", "superseded", "not_needed", "owner_abandoned", "unspecified"];
3512
+ function isMissionOutcome(value) {
3513
+ return typeof value === "string" && MISSION_OUTCOMES.includes(value);
3514
+ }
3515
+ var MISSION_REF_KINDS = ["commit", "branch", "pr", "task", "artifact", "mission", "url"];
3516
+ var MISSION_LIMITS = {
3517
+ summary: 300,
3518
+ outcomeReason: 500,
3519
+ itemText: 300,
3520
+ machine: 80,
3521
+ refs: 8,
3522
+ refValue: 300,
3523
+ refRepo: 120,
3524
+ refNote: 200,
3525
+ dedupeKey: 400,
3526
+ question: 300,
3527
+ context: 600,
3528
+ options: 5,
3529
+ optionLabel: 60,
3530
+ optionDetail: 200,
3531
+ /** Open items per mission before the oldest `remaining` fold into a "N more" summary item. */
3532
+ openItemsPerMission: 200,
3533
+ /** One event payload (serialized). */
3534
+ eventPayloadBytes: 16 * 1024,
3535
+ /** items_add / items_update entries honoured per call (extra entries are reported, not applied). */
3536
+ itemsPerCall: 50
3537
+ };
3538
+ var MISSION_DECISION_OPTION_IDS = ["a", "b", "c", "d", "e"];
3539
+ var MISSION_DECISION_URGENCIES = ["normal", "blocking"];
3540
+ var MISSION_DECISION_ON_DUE = ["remind", "apply_recommended"];
3541
+ function truncateMissionText(value, max) {
3542
+ if (value.length <= max) return value;
3543
+ return `${value.slice(0, max - 1).trimEnd()}\u2026`;
3544
+ }
3545
+ function str(value) {
3546
+ return typeof value === "string" ? value.trim() : "";
3547
+ }
3548
+ function collapse(value) {
3549
+ return value.replace(/\s+/g, " ").trim();
3550
+ }
3551
+ function normalizeMissionSummary(value) {
3552
+ if (typeof value !== "string") return null;
3553
+ const text = collapse(value);
3554
+ return { value: truncateMissionText(text, MISSION_LIMITS.summary), truncated: text.length > MISSION_LIMITS.summary };
3555
+ }
3556
+ function normalizeOutcomeReason(value) {
3557
+ if (typeof value !== "string") return null;
3558
+ const text = value.trim();
3559
+ return { value: truncateMissionText(text, MISSION_LIMITS.outcomeReason), truncated: text.length > MISSION_LIMITS.outcomeReason };
3560
+ }
3561
+ function normalizeMissionRefs(value) {
3562
+ if (!Array.isArray(value)) return { refs: [], truncated: false };
3563
+ const refs = [];
3564
+ let truncated = false;
3565
+ for (const raw of value) {
3566
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) continue;
3567
+ const r = raw;
3568
+ const kind = str(r.kind);
3569
+ const refValue = str(r.value);
3570
+ if (!MISSION_REF_KINDS.includes(kind) || !refValue) continue;
3571
+ if (refs.length >= MISSION_LIMITS.refs) {
3572
+ truncated = true;
3573
+ break;
3574
+ }
3575
+ const repo = str(r.repo);
3576
+ const note = str(r.note);
3577
+ refs.push({
3578
+ kind,
3579
+ ...repo ? { repo: truncateMissionText(repo, MISSION_LIMITS.refRepo) } : {},
3580
+ value: truncateMissionText(refValue, MISSION_LIMITS.refValue),
3581
+ ...note ? { note: truncateMissionText(note, MISSION_LIMITS.refNote) } : {}
3582
+ });
3583
+ }
3584
+ return { refs, truncated };
3585
+ }
3586
+ function normalizeOptions(value, truncated) {
3587
+ if (!Array.isArray(value)) return [];
3588
+ const out = [];
3589
+ for (const raw of value) {
3590
+ if (typeof raw === "string" && raw.trim()) {
3591
+ if (out.length >= MISSION_LIMITS.options) {
3592
+ truncated.push("options");
3593
+ break;
3594
+ }
3595
+ out.push({ id: MISSION_DECISION_OPTION_IDS[out.length], label: truncateMissionText(raw.trim(), MISSION_LIMITS.optionLabel) });
3596
+ continue;
3597
+ }
3598
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) continue;
3599
+ const o = raw;
3600
+ const label = collapse(str(o.label));
3601
+ if (!label) continue;
3602
+ if (out.length >= MISSION_LIMITS.options) {
3603
+ truncated.push("options");
3604
+ break;
3605
+ }
3606
+ const detail = str(o.detail);
3607
+ out.push({
3608
+ id: MISSION_DECISION_OPTION_IDS[out.length],
3609
+ label: truncateMissionText(label, MISSION_LIMITS.optionLabel),
3610
+ ...detail ? { detail: truncateMissionText(detail, MISSION_LIMITS.optionDetail) } : {}
3611
+ });
3612
+ }
3613
+ return out;
3614
+ }
3615
+ function normalizeDueAt(value) {
3616
+ if (typeof value !== "string" || !value.trim()) return void 0;
3617
+ const ms2 = Date.parse(value);
3618
+ return Number.isNaN(ms2) ? void 0 : new Date(ms2).toISOString();
3619
+ }
3620
+ function normalizeDecisionInput(raw, truncated) {
3621
+ const questionSource = collapse(str(raw.question) || str(raw.text));
3622
+ if (!questionSource) return null;
3623
+ if (questionSource.length > MISSION_LIMITS.question) truncated.push("question");
3624
+ const question = truncateMissionText(questionSource, MISSION_LIMITS.question);
3625
+ const contextSource = str(raw.context);
3626
+ if (contextSource.length > MISSION_LIMITS.context) truncated.push("context");
3627
+ const options = normalizeOptions(raw.options, truncated);
3628
+ const recommendedRaw = str(raw.recommended);
3629
+ const recommended = recommendedRaw && options.some((o) => o.id === recommendedRaw) ? recommendedRaw : options.find((o) => recommendedRaw && o.label.toLowerCase() === recommendedRaw.toLowerCase())?.id;
3630
+ const dueAt = normalizeDueAt(raw.dueAt ?? raw.due_at);
3631
+ const onDueRaw = str(raw.onDue ?? raw.on_due);
3632
+ const urgencyRaw = str(raw.urgency);
3633
+ const allowFreeTextRaw = raw.allowFreeText ?? raw.allow_free_text;
3634
+ return {
3635
+ question,
3636
+ ...contextSource ? { context: truncateMissionText(contextSource, MISSION_LIMITS.context) } : {},
3637
+ options,
3638
+ ...recommended ? { recommended } : {},
3639
+ allowFreeText: typeof allowFreeTextRaw === "boolean" ? allowFreeTextRaw : true,
3640
+ ...dueAt ? { dueAt } : {},
3641
+ // apply_recommended without a recommended option has nothing to apply — fall back to remind.
3642
+ onDue: onDueRaw === "apply_recommended" && recommended ? "apply_recommended" : "remind",
3643
+ urgency: urgencyRaw === "blocking" ? "blocking" : "normal"
3644
+ };
3645
+ }
3646
+ function normalizeForDedupe(text) {
3647
+ return collapse(text).toLowerCase().replace(/[\s.!?。]+$/u, "");
3648
+ }
3649
+ function deriveItemDedupeKey(kind, parts) {
3650
+ const explicit = str(parts.explicit);
3651
+ if (explicit) return truncateMissionText(`k:${explicit}`, MISSION_LIMITS.dedupeKey);
3652
+ if (kind === "decision") return truncateMissionText(`decision:${normalizeForDedupe(parts.question ?? parts.text ?? "")}`, MISSION_LIMITS.dedupeKey);
3653
+ if (kind === "evidence") {
3654
+ const ref2 = parts.refs?.[0];
3655
+ if (ref2) return truncateMissionText(`evidence:${ref2.kind}:${ref2.repo ?? ""}:${ref2.value}`, MISSION_LIMITS.dedupeKey);
3656
+ }
3657
+ const machine = parts.machine ? `@${normalizeForDedupe(parts.machine)}` : "";
3658
+ return truncateMissionText(`${kind}${machine}:${normalizeForDedupe(parts.text ?? "")}`, MISSION_LIMITS.dedupeKey);
3659
+ }
3660
+ function normalizeMissionItemInput(raw) {
3661
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return { error: "item must be an object" };
3662
+ const r = raw;
3663
+ const kind = str(r.kind) || "remaining";
3664
+ if (!MISSION_ITEM_KINDS.includes(kind)) {
3665
+ return { error: `invalid kind '${kind}' (valid: ${MISSION_ITEM_KINDS.join(", ")})` };
3666
+ }
3667
+ const truncated = [];
3668
+ const { refs, truncated: refsTruncated } = normalizeMissionRefs(r.refs);
3669
+ if (refsTruncated) truncated.push("refs");
3670
+ const machineRaw = collapse(str(r.machine));
3671
+ const machine = machineRaw ? truncateMissionText(machineRaw, MISSION_LIMITS.machine) : void 0;
3672
+ const explicitKey = str(r.dedupe_key ?? r.dedupeKey);
3673
+ if (kind === "decision") {
3674
+ const decisionRaw = r.decision && typeof r.decision === "object" && !Array.isArray(r.decision) ? r.decision : r;
3675
+ const decision = normalizeDecisionInput({ ...decisionRaw, question: decisionRaw.question ?? r.question ?? r.text }, truncated);
3676
+ if (!decision) return { error: "decision item needs a question" };
3677
+ return {
3678
+ item: {
3679
+ kind,
3680
+ text: decision.question,
3681
+ ...machine ? { machine } : {},
3682
+ refs,
3683
+ decision,
3684
+ dedupeKey: deriveItemDedupeKey("decision", { question: decision.question, explicit: explicitKey }),
3685
+ truncated
3686
+ }
3687
+ };
3688
+ }
3689
+ const textSource = collapse(str(r.text));
3690
+ if (!textSource && !(kind === "evidence" && refs.length > 0)) return { error: `${kind} item needs text` };
3691
+ if (textSource.length > MISSION_LIMITS.itemText) truncated.push("text");
3692
+ const text = truncateMissionText(textSource || `${refs[0].kind}: ${refs[0].value}`, MISSION_LIMITS.itemText);
3693
+ return {
3694
+ item: {
3695
+ kind,
3696
+ text,
3697
+ ...machine ? { machine } : {},
3698
+ refs,
3699
+ dedupeKey: deriveItemDedupeKey(kind, { text, machine, refs, explicit: explicitKey }),
3700
+ truncated
3701
+ }
3702
+ };
3703
+ }
3704
+ function normalizeMissionItemUpdate(raw) {
3705
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) return { error: "update must be an object" };
3706
+ const r = raw;
3707
+ const id2 = str(r.id ?? r.item_id ?? r.itemId);
3708
+ if (!id2) return { error: "update needs an item id" };
3709
+ const truncated = [];
3710
+ const update = { id: id2 };
3711
+ if (r.state !== void 0) {
3712
+ const state = str(r.state);
3713
+ if (!MISSION_ITEM_STATES.includes(state)) return { error: `invalid state '${state}'` };
3714
+ update.state = state;
3715
+ }
3716
+ if (typeof r.text === "string") {
3717
+ const text = collapse(r.text);
3718
+ if (text.length > MISSION_LIMITS.itemText) truncated.push("text");
3719
+ if (text) update.text = truncateMissionText(text, MISSION_LIMITS.itemText);
3720
+ }
3721
+ if (r.machine === null) update.machine = null;
3722
+ else if (typeof r.machine === "string") {
3723
+ const machine = collapse(r.machine);
3724
+ update.machine = machine ? truncateMissionText(machine, MISSION_LIMITS.machine) : null;
3725
+ }
3726
+ if (r.refs !== void 0) {
3727
+ const { refs, truncated: t } = normalizeMissionRefs(r.refs);
3728
+ if (t) truncated.push("refs");
3729
+ update.refs = refs;
3730
+ }
3731
+ return { update, truncated };
3732
+ }
3733
+ function boundEventPayload(payload) {
3734
+ let json = JSON.stringify(payload);
3735
+ if (json.length <= MISSION_LIMITS.eventPayloadBytes) return json;
3736
+ const shrunk = {};
3737
+ for (const [k, v] of Object.entries(payload)) {
3738
+ shrunk[k] = typeof v === "string" && v.length > 4e3 ? `${v.slice(0, 4e3)}\u2026` : v;
3739
+ }
3740
+ shrunk.payloadTruncated = true;
3741
+ json = JSON.stringify(shrunk);
3742
+ if (json.length <= MISSION_LIMITS.eventPayloadBytes) return json;
3743
+ return JSON.stringify({ payloadTruncated: true, keys: Object.keys(payload).slice(0, 20) });
3744
+ }
3745
+ var CARRY_OVER_MISSION_TITLE = "Carry-over \u2014 open items from closed missions";
3746
+ var LEGACY_CARRY_OVER_MISSION_TITLE = "\uC774\uC6D4 \u2014 \uB2EB\uD78C \uBBF8\uC158\uC5D0\uC11C \uB118\uC5B4\uC628 \uD56D\uBAA9";
3747
+ var CARRY_OVER_MISSION_GOAL = "Open items carried over from closed missions, and decisions requested without a mission. Managed automatically \u2014 do not close.";
3748
+ function isCarryOverMissionRecord(m) {
3749
+ return !!m && (m.isCarryOver === true || isCarryOverMissionTitle(m.title));
3750
+ }
3751
+ function isCarryOverMissionTitle(title) {
3752
+ if (typeof title !== "string") return false;
3753
+ const t = title.trim();
3754
+ return t === CARRY_OVER_MISSION_TITLE || t === LEGACY_CARRY_OVER_MISSION_TITLE;
3755
+ }
3756
+ var OWNER_ABANDON_CONFIRM_KEY_PREFIX = "owner-abandon-confirm:";
3757
+ var OWNER_ABANDON_CONFIRM_QUESTION = "The coordinator closed this as 'owner abandoned' \u2014 correct?";
3758
+ var OWNER_ABANDON_CONFIRM_OPTIONS = ["Correct", "Reopen"];
3759
+ var WORKER_DECISIONS_NEEDED_MAX = 3;
3760
+ var WORKER_COMMITS_MAX = 20;
3761
+ var SHA_RE = /^[0-9a-f]{7,64}$/i;
3762
+ function normalizeReportCommits(value) {
3763
+ if (!Array.isArray(value)) return null;
3764
+ const out = [];
3765
+ for (const v of value) {
3766
+ if (typeof v !== "string") return null;
3767
+ const sha = v.trim();
3768
+ if (!SHA_RE.test(sha)) return null;
3769
+ if (!out.includes(sha.toLowerCase())) out.push(sha.toLowerCase());
3770
+ }
3771
+ return out;
3772
+ }
3773
+
3774
+ // src/mission-git-state.ts
3775
+ var MISSION_REF_GIT_STATUSES = ["contained_ancestor", "contained_patch_equivalent", "not_contained", "unknown"];
3776
+ var MISSION_REF_GIT_METHODS = ["ancestry", "cherry", "residual_patch"];
3777
+ var MISSION_GIT_STATES = ["no_refs", "landed", "partial", "not_landed", "unknown"];
3778
+ function isMissionRefContained(status) {
3779
+ return status === "contained_ancestor" || status === "contained_patch_equivalent";
3780
+ }
3781
+ function aggregateMissionGitState(statuses) {
3782
+ const total = statuses.length;
3783
+ const contained = statuses.filter(isMissionRefContained).length;
3784
+ const notContained = statuses.filter((s) => s === "not_contained").length;
3785
+ const unknown = statuses.filter((s) => s === "unknown").length;
3786
+ const counts = { total, contained, notContained, unknown };
3787
+ if (total === 0) return { state: "no_refs", partialUnknown: false, counts };
3788
+ if (contained === total) return { state: "landed", partialUnknown: false, counts };
3789
+ if (contained > 0) return { state: "partial", partialUnknown: unknown > 0, counts };
3790
+ if (notContained === total) return { state: "not_landed", partialUnknown: false, counts };
3791
+ return { state: "unknown", partialUnknown: false, counts };
3792
+ }
3793
+
3794
+ // src/release.ts
3795
+ var MESH_RELEASE_CHANNELS = ["preview", "stable"];
3796
+ function isMeshReleaseChannel(value) {
3797
+ return typeof value === "string" && MESH_RELEASE_CHANNELS.includes(value);
3798
+ }
3799
+ var MESH_RELEASE_STATUSES = ["planned", "frozen", "deployed", "verified", "superseded", "cancelled"];
3800
+ function isReleaseStatus(value) {
3801
+ return typeof value === "string" && MESH_RELEASE_STATUSES.includes(value);
3802
+ }
3803
+ var RELEASE_MEMBER_STATES = ["member", "moved_out", "removed"];
3804
+ var RELEASE_ACTORS = ["coordinator", "owner", "assistant", "script"];
3805
+ var RELEASE_EVENT_TYPES = [
3806
+ "created",
3807
+ "status_changed",
3808
+ "scope_added",
3809
+ "scope_moved",
3810
+ "scope_removed",
3811
+ "deploy_recorded",
3812
+ "changelog_drafted",
3813
+ "changelog_applied"
3814
+ ];
3815
+ var MISSION_RELEASE_EVENT_TYPES = ["release_attached", "release_moved", "release_detached"];
3816
+ var RELEASE_LIMITS = {
3817
+ name: 80,
3818
+ note: 500,
3819
+ /** `mesh_missions.release_note`: one user/operator-visible sentence. */
3820
+ releaseNote: 400,
3821
+ missionsPerCall: 100,
3822
+ changelogEntries: 300
3823
+ };
3824
+ var CHANGELOG_SECTIONS = ["Added", "Fixed", "Changed"];
3825
+ var NEEDS_WORDING_MARKER = "[needs user-facing wording]";
3826
+ function changelogMissionMarker(missionId) {
3827
+ return `<!-- m:${missionId.slice(0, 8)} -->`;
3828
+ }
3829
+ function classifyChangelogSection(text, hint) {
3830
+ const m = /^\s*\[(added|fixed|changed)\]\s*/i.exec(text);
3831
+ if (m) {
3832
+ const key = m[1].toLowerCase();
3833
+ return { section: key === "added" ? "Added" : key === "fixed" ? "Fixed" : "Changed", text: text.slice(m[0].length).trim() };
3834
+ }
3835
+ const probe = `${hint ?? ""} ${text}`.toLowerCase();
3836
+ if (/\b(fix|fixes|fixed|bug|regression|crash|error)\b|오류|결함|버그|수정/.test(probe)) return { section: "Fixed", text };
3837
+ if (/\b(add|adds|added|new|introduc\w*|support\w*)\b|신규|추가/.test(probe)) return { section: "Added", text };
3838
+ return { section: "Changed", text };
3839
+ }
3840
+ function lintChangelogText(text) {
3841
+ const out = [];
3842
+ if (/\bwave[\s-]*\d+/i.test(text) || /웨이브\s*\d+/.test(text)) out.push("mentions an internal wave number");
3843
+ if (/\brc[.\s-]?\d+\b/i.test(text)) out.push("mentions an internal rc number");
3844
+ if (/\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/i.test(text) || /\bmi_[0-9a-f]{12}\b/.test(text) || /\brel_[0-9a-f]{12}\b/.test(text)) out.push("contains an internal id");
3845
+ if (/\bmission\b/i.test(text)) out.push('mentions "mission" (internal vocabulary)');
3846
+ return out;
3847
+ }
3848
+
3849
+ // src/decision-push-relay.ts
3850
+ var DECISION_PUSH_RELAY_COMMAND = "mission_decision_push_relay_answer";
3851
+ var DECISION_PUSH_RELAY_SOURCE = "push_relay";
3852
+
3112
3853
  // src/keyed-doc-delta.ts
3113
3854
  function sig(value) {
3114
3855
  if (value === void 0) return void 0;
@@ -3329,7 +4070,15 @@ function foldKeyedDoc(held, delta, spec) {
3329
4070
  const heldList = heldCollections.get(path);
3330
4071
  if (change?.absent) {
3331
4072
  const [head2, tail2] = splitPath(path);
3332
- if (!tail2) delete next[head2];
4073
+ if (!tail2) {
4074
+ delete next[head2];
4075
+ continue;
4076
+ }
4077
+ const parent2 = next[head2];
4078
+ if (!isRecord3(parent2) || !(tail2 in parent2)) continue;
4079
+ const copy = { ...parent2 };
4080
+ delete copy[tail2];
4081
+ next[head2] = copy;
3333
4082
  continue;
3334
4083
  }
3335
4084
  if (!change && heldList === void 0) continue;
@@ -3393,8 +4142,164 @@ function stableMeshNodeRow(row) {
3393
4142
  }
3394
4143
  return out;
3395
4144
  }
4145
+
4146
+ // src/provider-approval.ts
4147
+ function isActionableProviderApproval(approval) {
4148
+ return !!approval && approval.source === "provider_modal" && approval.type === "tool_permission" && approval.lifecycle === "pending" && approval.evidence === "live" && approval.actionable && !!approval.modalKey && Array.isArray(approval.buttons) && approval.buttons.some((button) => typeof button === "string" && !!button.trim());
4149
+ }
4150
+ function readProviderDecision(approval, waiting, hasModal = false) {
4151
+ if (approval !== void 0) return approval && ["provider_modal", "legacy_provider", "status_only", "ledger_approval"].includes(approval.source) ? approval : null;
4152
+ if (!waiting) return null;
4153
+ return {
4154
+ source: hasModal ? "legacy_provider" : "status_only",
4155
+ type: "unknown",
4156
+ compatibility: hasModal ? "session_only" : "unknown",
4157
+ evidence: "unavailable",
4158
+ lifecycle: "pending",
4159
+ modalKey: null,
4160
+ createdAt: null,
4161
+ resolvedAt: null,
4162
+ description: "",
4163
+ buttons: [],
4164
+ actionable: false
4165
+ };
4166
+ }
4167
+ function providerApprovalSnapshot(approval) {
4168
+ if (!approval) return null;
4169
+ const {
4170
+ source,
4171
+ type,
4172
+ lifecycle,
4173
+ modalKey,
4174
+ createdAt,
4175
+ resolvedAt,
4176
+ providerType,
4177
+ sessionId,
4178
+ nodeId,
4179
+ meshId,
4180
+ taskId,
4181
+ attemptId,
4182
+ generation
4183
+ } = approval;
4184
+ return {
4185
+ source,
4186
+ type,
4187
+ lifecycle,
4188
+ modalKey,
4189
+ createdAt,
4190
+ resolvedAt,
4191
+ providerType,
4192
+ sessionId,
4193
+ nodeId,
4194
+ meshId,
4195
+ taskId,
4196
+ attemptId,
4197
+ generation,
4198
+ evidence: "cached",
4199
+ actionable: false,
4200
+ description: "",
4201
+ buttons: []
4202
+ };
4203
+ }
4204
+
4205
+ // src/provider-question.ts
4206
+ function isProviderQuestionBinding(value) {
4207
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
4208
+ const b = value;
4209
+ if (b.transport !== "codex_rpc" && b.transport !== "codex_async") return false;
4210
+ const keys = ["transport", "sessionId", "generation", "threadId", "turnId", "itemId", ...b.transport === "codex_rpc" ? ["requestId"] : []];
4211
+ if (Reflect.ownKeys(b).some((key) => typeof key !== "string" || !keys.includes(key))) return false;
4212
+ if (["sessionId", "generation", "threadId", "turnId", "itemId"].some((key) => typeof b[key] !== "string" || !b[key].trim())) return false;
4213
+ return b.transport === "codex_async" ? b.requestId === void 0 : typeof b.requestId === "string" && !!b.requestId.trim() || typeof b.requestId === "number" && Number.isFinite(b.requestId);
4214
+ }
4215
+
4216
+ // src/relay-reprobe.ts
4217
+ var RELAY_REPROBE_BASE_DELAY_MS = 6e4;
4218
+ var RELAY_REPROBE_MAX_DELAY_MS = 5 * 6e4;
4219
+ var RELAY_REPROBE_JITTER_RATIO = 0.2;
4220
+ function computeRelayReprobeDelay(failures, random, timing = {}) {
4221
+ const base = timing.baseDelayMs ?? RELAY_REPROBE_BASE_DELAY_MS;
4222
+ const max = timing.maxDelayMs ?? RELAY_REPROBE_MAX_DELAY_MS;
4223
+ const jitter = timing.jitterRatio ?? RELAY_REPROBE_JITTER_RATIO;
4224
+ const grown = Math.min(max, base * 2 ** Math.max(0, failures));
4225
+ const factor = 1 + jitter * (Math.min(1, Math.max(0, random())) * 2 - 1);
4226
+ return Math.round(grown * factor);
4227
+ }
4228
+ var RelayReprobeScheduler = class {
4229
+ constructor(options) {
4230
+ this.options = options;
4231
+ }
4232
+ handle = null;
4233
+ running = false;
4234
+ inFlight = false;
4235
+ failureCount = 0;
4236
+ generation = 0;
4237
+ get isRunning() {
4238
+ return this.running;
4239
+ }
4240
+ get failures() {
4241
+ return this.failureCount;
4242
+ }
4243
+ get probing() {
4244
+ return this.inFlight;
4245
+ }
4246
+ /** Begin probing (idempotent). Call when a connection is selected as relay. */
4247
+ start() {
4248
+ if (this.running) return;
4249
+ this.running = true;
4250
+ this.failureCount = 0;
4251
+ this.generation++;
4252
+ this.schedule();
4253
+ }
4254
+ /** Stop for good (direct path found, connection closed, auth epoch changed). */
4255
+ stop() {
4256
+ this.running = false;
4257
+ this.generation++;
4258
+ if (this.handle !== null) {
4259
+ this.options.clearTimer(this.handle);
4260
+ this.handle = null;
4261
+ }
4262
+ }
4263
+ schedule() {
4264
+ if (!this.running) return;
4265
+ const generation = this.generation;
4266
+ const delay = computeRelayReprobeDelay(this.failureCount, this.options.random, this.options);
4267
+ this.handle = this.options.setTimer(() => {
4268
+ this.handle = null;
4269
+ void this.tick(generation);
4270
+ }, delay);
4271
+ }
4272
+ async tick(generation) {
4273
+ if (!this.running || generation !== this.generation) return;
4274
+ if (this.inFlight || !this.options.shouldProbe()) {
4275
+ this.schedule();
4276
+ return;
4277
+ }
4278
+ this.inFlight = true;
4279
+ let outcome;
4280
+ try {
4281
+ outcome = await this.options.probe();
4282
+ } catch {
4283
+ outcome = "failed";
4284
+ }
4285
+ this.inFlight = false;
4286
+ if (!this.running || generation !== this.generation) return;
4287
+ if (outcome === "direct") {
4288
+ this.stop();
4289
+ return;
4290
+ }
4291
+ if (outcome !== "skipped") this.failureCount++;
4292
+ this.schedule();
4293
+ }
4294
+ };
3396
4295
  export {
4296
+ ASSISTANT_ACCOUNT_SLOT,
4297
+ ASSISTANT_FOLLOWER_ALLOWED_OPS,
3397
4298
  ASSISTANT_OWNER_VERBS,
4299
+ ASSISTANT_REMOTE_FOLLOW_COMMAND,
4300
+ ASSISTANT_REMOTE_PROJECT_ACCESS_COMMAND,
4301
+ ASSISTANT_REMOTE_PROJECT_CATALOG_COMMAND,
4302
+ ASSISTANT_REMOTE_PROJECT_COMMAND,
3398
4303
  ASSISTANT_REVIEW_TURN_VERBS,
3399
4304
  ASSISTANT_SESSION_ID_ARG,
3400
4305
  ASSISTANT_SESSION_ID_ENV,
@@ -3406,12 +4311,16 @@ export {
3406
4311
  CANCEL_REASONS,
3407
4312
  CANONICAL_MESH_TOOL_COUNT,
3408
4313
  CANONICAL_MESH_TOOL_NAMES,
4314
+ CARRY_OVER_MISSION_GOAL,
4315
+ CARRY_OVER_MISSION_TITLE,
4316
+ CHANGELOG_SECTIONS,
3409
4317
  CLAUDE_TUI_REVIEW_PAGE_NOT_FOCUSED_PREFIX,
3410
4318
  CLAUDE_TUI_REVIEW_UNCONFIRMED_PREFIX,
3411
4319
  CLI_SLOT_RECIPES,
3412
4320
  COMMIT_STRENGTHS,
3413
4321
  CONSUME_PROFILES,
3414
4322
  COORDINATOR_ACK_OUTCOMES,
4323
+ COORDINATOR_SETTABLE_ITEM_STATES,
3415
4324
  DAEMON_METADATA_DOC_SPEC,
3416
4325
  DAEMON_P2P_SIGNAL_TYPES,
3417
4326
  DAEMON_STATUS_EVENT_NAMES,
@@ -3424,6 +4333,11 @@ export {
3424
4333
  DASHBOARD_TO_DAEMON_P2P_TYPES,
3425
4334
  DASHBOARD_TO_USER_SESSION_TYPES,
3426
4335
  DASHBOARD_WIRE_VERSION,
4336
+ DECISION_PUSH_OPTIONS_MAX,
4337
+ DECISION_PUSH_OPTION_LABEL_MAX,
4338
+ DECISION_PUSH_QUESTION_MAX,
4339
+ DECISION_PUSH_RELAY_COMMAND,
4340
+ DECISION_PUSH_RELAY_SOURCE,
3427
4341
  DEFAULT_DIFFICULTY_BRAINS,
3428
4342
  DELIVERY_OUTCOMES,
3429
4343
  DELIVERY_VIAS,
@@ -3431,6 +4345,11 @@ export {
3431
4345
  EVIDENCE_ENVELOPE_FIELD_SPECS,
3432
4346
  EVIDENCE_SOURCE_IDS,
3433
4347
  HOLD_REASONS,
4348
+ LAUNCH_DEFAULTS_NEXT_LAUNCH_NOTE,
4349
+ LAUNCH_DEFAULT_ERROR_CODES,
4350
+ LAUNCH_DEFAULT_ROLES,
4351
+ LAUNCH_DEFAULT_SOURCES,
4352
+ LEGACY_CARRY_OVER_MISSION_TITLE,
3434
4353
  LIVENESS_RESULTS,
3435
4354
  MAX_MESH_RECORD_STRING,
3436
4355
  MAX_OWNED_PATHS,
@@ -3445,6 +4364,8 @@ export {
3445
4364
  MESH_MISSION_STATUSES,
3446
4365
  MESH_P2P_SIGNAL_TYPES,
3447
4366
  MESH_RECORD_PAYLOAD_KEYS,
4367
+ MESH_RELEASE_CHANNELS,
4368
+ MESH_RELEASE_STATUSES,
3448
4369
  MESH_SESSION_CLEANUP_MODES,
3449
4370
  MESH_STATUS_DOC_SPEC,
3450
4371
  MESH_TASK_DIFFICULTIES,
@@ -3456,10 +4377,23 @@ export {
3456
4377
  MESH_TOPIC_ENTRY_KINDS,
3457
4378
  MESH_TOPIC_PROTOCOL_VERSION,
3458
4379
  MISSION_BRIEF_RENDER_MAX_CHARS,
4380
+ MISSION_DECISION_ON_DUE,
4381
+ MISSION_DECISION_OPTION_IDS,
4382
+ MISSION_DECISION_URGENCIES,
4383
+ MISSION_GIT_STATES,
4384
+ MISSION_ITEM_KINDS,
4385
+ MISSION_ITEM_STATES,
4386
+ MISSION_LIMITS,
4387
+ MISSION_OUTCOMES,
4388
+ MISSION_REF_GIT_METHODS,
4389
+ MISSION_REF_GIT_STATUSES,
4390
+ MISSION_REF_KINDS,
4391
+ MISSION_RELEASE_EVENT_TYPES,
3459
4392
  MODEL_AXIS_SOURCES,
3460
4393
  MODEL_SELECTION_HISTORY_LIMIT,
3461
4394
  MeshChunkAssembler,
3462
4395
  NATIVE_TURN_OUTCOMES,
4396
+ NEEDS_WORDING_MARKER,
3463
4397
  NOTIFY_KINDS,
3464
4398
  NO_PROGRESS_OBSERVED_STATUSES,
3465
4399
  NPM_UPDATE_TAGS,
@@ -3469,14 +4403,27 @@ export {
3469
4403
  OPERATOR_STATUS_REASON_VALUES,
3470
4404
  OPERATOR_STATUS_VALUES,
3471
4405
  OUTBOUND_MESSAGE_ORIGINS,
4406
+ OWNER_ABANDON_CONFIRM_KEY_PREFIX,
4407
+ OWNER_ABANDON_CONFIRM_OPTIONS,
4408
+ OWNER_ABANDON_CONFIRM_QUESTION,
3472
4409
  P2P_SIGNAL_TYPES,
3473
4410
  PROVIDER_FAILURES,
4411
+ QUOTA_BACKFILL_HORIZON_MS,
4412
+ QUOTA_RETRY_INFLIGHT_GRACE_MS,
3474
4413
  QUOTA_SUPPORTED_PROVIDERS,
3475
4414
  RECENT_SESSION_BUCKETS,
3476
4415
  RECLAIMING_SEND_REFUSALS,
4416
+ RELAY_REPROBE_BASE_DELAY_MS,
4417
+ RELAY_REPROBE_JITTER_RATIO,
4418
+ RELAY_REPROBE_MAX_DELAY_MS,
4419
+ RELEASE_ACTORS,
3477
4420
  RELEASE_CHANNELS,
4421
+ RELEASE_EVENT_TYPES,
4422
+ RELEASE_LIMITS,
4423
+ RELEASE_MEMBER_STATES,
3478
4424
  REMOVED_MESH_TOOLS,
3479
4425
  RETIRED_MESH_TOOLS,
4426
+ RelayReprobeScheduler,
3480
4427
  SEND_POLICY_MODES,
3481
4428
  SEND_REFUSAL_REASONS,
3482
4429
  SERVER_STATUS_EVENT_NAMES,
@@ -3514,16 +4461,25 @@ export {
3514
4461
  VERSION_UPDATE_REASONS,
3515
4462
  VIEWER_TO_SHARED_SESSION_TYPES,
3516
4463
  WORKER_BRANCH_STATES,
4464
+ WORKER_COMMITS_MAX,
4465
+ WORKER_DECISIONS_NEEDED_MAX,
3517
4466
  WORKER_PROTOCOL_FOOTER_MARKER,
3518
4467
  WORKER_REPORT_OUTCOMES,
4468
+ WORKER_REPORT_SUMMARY_MAX_CHARS,
3519
4469
  WORKER_TOOLS,
4470
+ aggregateMissionGitState,
3520
4471
  appendWorkerProtocolFooter,
3521
4472
  argsCarryStatusProbeMarker,
4473
+ assessQuotaFreshness,
4474
+ boundEventPayload,
3522
4475
  buildSlotProposal,
3523
4476
  canonicalDaemonId,
4477
+ changelogMissionMarker,
4478
+ classifyChangelogSection,
3524
4479
  classifySessionStatus,
3525
4480
  compareDashboardWireVersion,
3526
4481
  compareSemver,
4482
+ computeRelayReprobeDelay,
3527
4483
  daemonIdsEquivalent,
3528
4484
  decodeActiveWorkQueryRequest,
3529
4485
  decodeActiveWorkQueryResponse,
@@ -3566,6 +4522,8 @@ export {
3566
4522
  decodeQueueQueryResponse,
3567
4523
  decodeQueueRequeueRequest,
3568
4524
  decodeQueueRequeueResponse,
4525
+ decodeQueueReviseRequest,
4526
+ decodeQueueReviseResponse,
3569
4527
  decodeRecordLocalRequest,
3570
4528
  decodeRecordLocalResponse,
3571
4529
  decodeRecoveryContextQueryRequest,
@@ -3585,6 +4543,7 @@ export {
3585
4543
  decodeUserSessionToDashboard,
3586
4544
  decodeViewerToSharedSession,
3587
4545
  defaultProviderPriorityFromNodeFacts,
4546
+ deriveItemDedupeKey,
3588
4547
  deriveProviderPriorityFromSlots,
3589
4548
  deriveSlotsFromLegacy,
3590
4549
  describeModelSelection,
@@ -3595,13 +4554,19 @@ export {
3595
4554
  expandDaemonIdForms,
3596
4555
  findOwnershipConflicts,
3597
4556
  foldKeyedDoc,
4557
+ followedRemoteProjectKey,
4558
+ followerOpPermitted,
3598
4559
  formatQuotaAccount,
3599
4560
  hasGitStatusEvidence,
3600
4561
  hasWorkerProtocolFooter,
3601
4562
  interpolateString,
4563
+ isActionableProviderApproval,
4564
+ isAssistantFollowerAllowedOp,
3602
4565
  isAssistantTool,
3603
4566
  isBlockedStatus,
3604
4567
  isBusyStatus,
4568
+ isCarryOverMissionRecord,
4569
+ isCarryOverMissionTitle,
3605
4570
  isChunkType,
3606
4571
  isCommitStrength,
3607
4572
  isDaemonDirectCommandType,
@@ -3620,11 +4585,14 @@ export {
3620
4585
  isFiniteNumber,
3621
4586
  isIdleSessionState,
3622
4587
  isInputEnvelopeWire,
4588
+ isLaunchDefaultRole,
4589
+ isLaunchDefaultSource,
3623
4590
  isMeshDeliveryMode,
3624
4591
  isMeshIndexQueryResponse,
3625
4592
  isMeshMissionStatusValue,
3626
4593
  isMeshP2PSignalType,
3627
4594
  isMeshRecordPayload,
4595
+ isMeshReleaseChannel,
3628
4596
  isMeshTaskDifficulty,
3629
4597
  isMeshTaskMode,
3630
4598
  isMeshTaskPriority,
@@ -3632,17 +4600,22 @@ export {
3632
4600
  isMeshTerminalTaskStatus,
3633
4601
  isMeshTopicEntry,
3634
4602
  isMessageId,
4603
+ isMissionOutcome,
4604
+ isMissionRefContained,
3635
4605
  isMissionUpsertResponse,
3636
4606
  isModelAxisSource,
4607
+ isNativeMarkerRef,
3637
4608
  isNonEmptyString,
3638
4609
  isNotifyKind,
3639
4610
  isOutboundMessage,
3640
4611
  isOutboundMessageOrigin,
3641
4612
  isP2PSignalType,
3642
4613
  isPhantomDaemonEntry,
4614
+ isProviderQuestionBinding,
3643
4615
  isRawDaemonDoId,
3644
4616
  isReadyStatus,
3645
4617
  isRecord,
4618
+ isReleaseStatus,
3646
4619
  isSendPolicy,
3647
4620
  isSendPolicyMode,
3648
4621
  isSendRefusal,
@@ -3669,6 +4642,7 @@ export {
3669
4642
  isWorkingStatus,
3670
4643
  joinRepoPath,
3671
4644
  launchModelSelectionValue,
4645
+ lintChangelogText,
3672
4646
  machineCoreFromDaemonId,
3673
4647
  makeTypeGuard,
3674
4648
  measureWorstCaseChunkEnvelopeBytes,
@@ -3677,33 +4651,45 @@ export {
3677
4651
  meshUtf8ByteLength,
3678
4652
  meshWorkspacesEquivalent,
3679
4653
  mintMessageId,
4654
+ minutesUntilQuotaCheck,
3680
4655
  normalizeAuthOkLimits,
3681
4656
  normalizeBrainSlot,
4657
+ normalizeDecisionInput,
3682
4658
  normalizeDifficultyBrainMap,
4659
+ normalizeForDedupe,
3683
4660
  normalizeGitStatus,
3684
4661
  normalizeMeshNodeFacts,
3685
4662
  normalizeMeshNodeId,
3686
4663
  normalizeMeshSessionRecord,
3687
4664
  normalizeMeshWorkspaceForCompare,
3688
4665
  normalizeMissionBrief,
4666
+ normalizeMissionItemInput,
4667
+ normalizeMissionItemUpdate,
4668
+ normalizeMissionRefs,
4669
+ normalizeMissionSummary,
3689
4670
  normalizeNodeCapabilitySlot,
3690
4671
  normalizeNodeCapabilitySlots,
4672
+ normalizeOutcomeReason,
3691
4673
  normalizeOwnedPaths,
4674
+ normalizeReportCommits,
3692
4675
  normalizeSessionStatus,
3693
4676
  normalizeThinkingLevel,
3694
4677
  orderProvidersByBuiltinPreference,
3695
4678
  parseJsonRecord,
4679
+ parseRoleLaunchSelection,
3696
4680
  parseSemver,
3697
4681
  parseSessionLaunchRecord,
3698
4682
  pathsOverlap,
3699
4683
  pickBestTransitGitStatus,
3700
4684
  projectFileDiffRow,
3701
4685
  projectTurnEvidenceEntry,
4686
+ providerApprovalSnapshot,
3702
4687
  readBoolean,
3703
4688
  readEnvelopeFields,
3704
4689
  readGitSubmodules,
3705
4690
  readNumber,
3706
4691
  readOptionalRecord,
4692
+ readProviderDecision,
3707
4693
  readRecord,
3708
4694
  readString,
3709
4695
  readStringArray,
@@ -3714,6 +4700,7 @@ export {
3714
4700
  retiredMeshToolError,
3715
4701
  sanitizeModelIdentifier,
3716
4702
  sanitizeRefusalCode,
4703
+ sanitizeRemoteRepoIdentity,
3717
4704
  scoreGitStatusCandidate,
3718
4705
  scoreGitUpstreamFreshness,
3719
4706
  sessionIdsEquivalent,
@@ -3724,6 +4711,8 @@ export {
3724
4711
  summarizeGitShape,
3725
4712
  supportsQuota,
3726
4713
  touchedFilesOutsideOwnership,
4714
+ truncateMissionText,
4715
+ unwrapPastedContent,
3727
4716
  withStatusProbeMarker
3728
4717
  };
3729
4718
  //# sourceMappingURL=index.mjs.map