@cleocode/cleo 2026.4.152 → 2026.4.154

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.
package/dist/cli/index.js CHANGED
@@ -385,7 +385,18 @@ var init_branch_lock = __esm({
385
385
  /** L4c: override requires TTY but stdin/stderr is not a TTY. */
386
386
  E_OVERRIDE_NEEDS_TTY: "E_OVERRIDE_NEEDS_TTY",
387
387
  /** L4d: session override limit exceeded. */
388
- E_OVERRIDE_RATE_LIMIT: "E_OVERRIDE_RATE_LIMIT"
388
+ E_OVERRIDE_RATE_LIMIT: "E_OVERRIDE_RATE_LIMIT",
389
+ /**
390
+ * T1501 / P0-5: per-session cap (default 3) exceeded without a valid waiver doc.
391
+ * Set CLEO_OWNER_OVERRIDE_WAIVER=<absolute path> to a file containing
392
+ * `cap-waiver: true` in its frontmatter to bypass the cap.
393
+ */
394
+ E_OVERRIDE_CAP_EXCEEDED: "E_OVERRIDE_CAP_EXCEEDED",
395
+ /**
396
+ * T1502 / P0-6: the same evidence atom was used across >3 distinct tasks and
397
+ * `--shared-evidence` was not passed (or CLEO_STRICT_EVIDENCE=1 is set in CI).
398
+ */
399
+ E_SHARED_EVIDENCE_FLAG_REQUIRED: "E_SHARED_EVIDENCE_FLAG_REQUIRED"
389
400
  };
390
401
  }
391
402
  });
@@ -3772,6 +3783,17 @@ var init_registry = __esm({
3772
3783
  requiredParams: [],
3773
3784
  params: []
3774
3785
  },
3786
+ {
3787
+ gateway: "query",
3788
+ domain: "check",
3789
+ operation: "test.coverage",
3790
+ description: "check.test.coverage (query) \u2014 dedicated test coverage sub-op (T1434)",
3791
+ tier: 1,
3792
+ idempotent: true,
3793
+ sessionRequired: false,
3794
+ requiredParams: [],
3795
+ params: []
3796
+ },
3775
3797
  {
3776
3798
  gateway: "query",
3777
3799
  domain: "check",
@@ -5290,6 +5312,32 @@ var init_registry = __esm({
5290
5312
  }
5291
5313
  ]
5292
5314
  },
5315
+ // T1147 W7 — sweep mutate variant (approve, rollback) — routes to same handler as query
5316
+ // Registered separately so mutate:memory.sweep resolves correctly (T1496/P0-1)
5317
+ {
5318
+ gateway: "mutate",
5319
+ domain: "memory",
5320
+ operation: "sweep",
5321
+ description: "memory.sweep (mutate) \u2014 T1147 W7 BRAIN noise sweep approve/rollback. approve <runId>: apply sweep to live brain tables. rollback <runId>: discard a staged run without applying changes.",
5322
+ tier: 0,
5323
+ idempotent: false,
5324
+ sessionRequired: false,
5325
+ requiredParams: [],
5326
+ params: [
5327
+ {
5328
+ name: "approve",
5329
+ type: "string",
5330
+ required: false,
5331
+ description: "Run ID to approve and apply to live tables."
5332
+ },
5333
+ {
5334
+ name: "rollback",
5335
+ type: "string",
5336
+ required: false,
5337
+ description: "Run ID to roll back without applying changes."
5338
+ }
5339
+ ]
5340
+ },
5293
5341
  // T791 — LLM extraction backend status
5294
5342
  {
5295
5343
  gateway: "query",
@@ -8563,6 +8611,25 @@ var init_registry = __esm({
8563
8611
  description: "Remove worktrees idle for longer than this many hours (default: 24)"
8564
8612
  }
8565
8613
  ]
8614
+ },
8615
+ // T1462 — Single-task worktree prune (auto-triggered by cleo complete)
8616
+ {
8617
+ gateway: "mutate",
8618
+ domain: "orchestrate",
8619
+ operation: "worktree.prune",
8620
+ description: "orchestrate.worktree.prune (mutate) \u2014 prune the worktree for a single completed task, or all orphaned worktrees when no taskId is supplied",
8621
+ tier: 2,
8622
+ idempotent: true,
8623
+ sessionRequired: false,
8624
+ requiredParams: [],
8625
+ params: [
8626
+ {
8627
+ name: "taskId",
8628
+ type: "string",
8629
+ required: false,
8630
+ description: "Task ID whose worktree should be pruned (omit for bulk prune)"
8631
+ }
8632
+ ]
8566
8633
  }
8567
8634
  ];
8568
8635
  counts = getCounts();
@@ -9584,6 +9651,7 @@ import {
9584
9651
  paginate,
9585
9652
  parseScope,
9586
9653
  persistHandoff,
9654
+ readSessionOverrideCount,
9587
9655
  recordAssumption,
9588
9656
  recordDecision,
9589
9657
  showSession,
@@ -9598,12 +9666,14 @@ async function sessionStatus(projectRoot) {
9598
9666
  const focusState = await accessor.getMetaValue("focus_state");
9599
9667
  const sessions2 = await accessor.loadSessions();
9600
9668
  const active = sessions2.find((s) => s.status === "active");
9669
+ const overrideCount = active ? readSessionOverrideCount(projectRoot, active.id) : 0;
9601
9670
  return {
9602
9671
  success: true,
9603
9672
  data: {
9604
9673
  hasActiveSession: !!active,
9605
9674
  session: active || null,
9606
- taskWork: focusState || null
9675
+ taskWork: focusState || null,
9676
+ overrideCount
9607
9677
  }
9608
9678
  };
9609
9679
  } catch {
@@ -14605,8 +14675,10 @@ import {
14605
14675
  import {
14606
14676
  appendForceBypassLine,
14607
14677
  appendGateAuditLine,
14678
+ checkAndIncrementOverrideCap,
14608
14679
  checkGateEvidenceMinimum,
14609
14680
  composeGateEvidence,
14681
+ enforceSharedEvidence,
14610
14682
  getAccessor as getAccessor7,
14611
14683
  parseEvidence,
14612
14684
  validateAtom
@@ -15111,6 +15183,44 @@ async function validateGateVerify(params, projectRoot) {
15111
15183
  }
15112
15184
  const isWriteRequiringEvidence = (all || gate && value !== false) && !reset;
15113
15185
  const override = readOverrideState();
15186
+ let sessionOverrideOrdinal;
15187
+ let isWorktreeCtx = false;
15188
+ if (override.override && isWriteRequiringEvidence) {
15189
+ const command = (process.argv.slice(1).join(" ") || "cleo").slice(0, 512);
15190
+ const capResult = checkAndIncrementOverrideCap(
15191
+ root,
15192
+ sessionId ?? "global",
15193
+ void 0,
15194
+ command
15195
+ );
15196
+ if (!capResult.allowed) {
15197
+ return engineError(
15198
+ capResult.errorCode ?? "E_OVERRIDE_CAP_EXCEEDED",
15199
+ capResult.errorMessage ?? "Per-session override cap exceeded."
15200
+ );
15201
+ }
15202
+ sessionOverrideOrdinal = capResult.sessionOverrideOrdinal;
15203
+ isWorktreeCtx = capResult.workTreeContext === true;
15204
+ }
15205
+ let sharedEvidenceAcknowledged = false;
15206
+ let sharedAtomWarned = false;
15207
+ if (isWriteRequiringEvidence && !override.override && params.evidence && sessionId) {
15208
+ const seResult = enforceSharedEvidence(
15209
+ root,
15210
+ sessionId,
15211
+ taskId,
15212
+ params.evidence,
15213
+ params.sharedEvidence === true
15214
+ );
15215
+ if (!seResult.allowed) {
15216
+ return engineError(
15217
+ seResult.errorCode ?? "E_SHARED_EVIDENCE_FLAG_REQUIRED",
15218
+ seResult.errorMessage ?? "Shared evidence flag required."
15219
+ );
15220
+ }
15221
+ sharedEvidenceAcknowledged = seResult.acknowledged === true;
15222
+ sharedAtomWarned = seResult.warned === true;
15223
+ }
15114
15224
  let verification = task.verification ?? initVerification();
15115
15225
  if (!verification.evidence) {
15116
15226
  verification.evidence = {};
@@ -15225,7 +15335,18 @@ Or set CLEO_OWNER_OVERRIDE=1 with CLEO_OWNER_OVERRIDE_REASON=<reason> for emerge
15225
15335
  ...auditRecord,
15226
15336
  overrideReason: override.reason,
15227
15337
  pid: process.pid,
15228
- command: (process.argv.slice(1).join(" ") || "cleo").slice(0, 512)
15338
+ command: (process.argv.slice(1).join(" ") || "cleo").slice(0, 512),
15339
+ ...sessionOverrideOrdinal !== void 0 ? { sessionOverrideOrdinal } : {},
15340
+ ...isWorktreeCtx ? { workTreeContext: true } : {}
15341
+ });
15342
+ } else if ((sharedEvidenceAcknowledged || sharedAtomWarned) && action !== "reset") {
15343
+ await appendForceBypassLine(root, {
15344
+ ...auditRecord,
15345
+ overrideReason: "shared-evidence",
15346
+ pid: process.pid,
15347
+ command: (process.argv.slice(1).join(" ") || "cleo").slice(0, 512),
15348
+ ...sharedEvidenceAcknowledged ? { sharedEvidence: true } : {},
15349
+ ...sharedAtomWarned ? { sharedAtomWarning: true } : {}
15229
15350
  });
15230
15351
  }
15231
15352
  } catch {
@@ -17729,7 +17850,8 @@ var init_check = __esm({
17729
17850
  all: params.all,
17730
17851
  reset: params.reset,
17731
17852
  evidence: params.evidence,
17732
- sessionId: params.sessionId
17853
+ sessionId: params.sessionId,
17854
+ sharedEvidence: params.sharedEvidence
17733
17855
  };
17734
17856
  const result = await validateGateVerify(gateParams, projectRoot);
17735
17857
  setImmediate(async () => {
@@ -17818,6 +17940,7 @@ var init_check = __esm({
17818
17940
  "compliance.summary",
17819
17941
  "workflow.compliance",
17820
17942
  "test",
17943
+ "test.coverage",
17821
17944
  "coherence",
17822
17945
  "gate.status",
17823
17946
  "archive.stats",
@@ -18590,197 +18713,375 @@ function mimeFromPath(filePath) {
18590
18713
  if (lower.endsWith(".css")) return "text/css";
18591
18714
  return "application/octet-stream";
18592
18715
  }
18593
- var DocsHandler;
18716
+ function docsEnvelopeToResponse(envelope, gateway, operation, startTime) {
18717
+ if (!envelope.success) {
18718
+ return {
18719
+ meta: dispatchMeta(gateway, "docs", operation, startTime),
18720
+ success: false,
18721
+ error: {
18722
+ code: String(envelope.error?.code ?? "E_INTERNAL"),
18723
+ message: envelope.error?.message ?? "Unknown error"
18724
+ }
18725
+ };
18726
+ }
18727
+ let attachmentBackend;
18728
+ let responseData = envelope.data;
18729
+ if (responseData !== null && responseData !== void 0 && typeof responseData === "object") {
18730
+ const dataObj = responseData;
18731
+ if ("attachmentBackend" in dataObj && dataObj["attachmentBackend"] !== void 0) {
18732
+ attachmentBackend = dataObj["attachmentBackend"];
18733
+ const { attachmentBackend: _lifted, ...cleanData } = dataObj;
18734
+ responseData = cleanData;
18735
+ }
18736
+ }
18737
+ return {
18738
+ meta: {
18739
+ ...dispatchMeta(gateway, "docs", operation, startTime),
18740
+ ...attachmentBackend !== void 0 ? { attachmentBackend } : {}
18741
+ },
18742
+ success: true,
18743
+ data: responseData
18744
+ };
18745
+ }
18746
+ var _docsTypedHandler, QUERY_OPS3, MUTATE_OPS3, DocsHandler;
18594
18747
  var init_docs = __esm({
18595
18748
  "packages/cleo/src/dispatch/domains/docs.ts"() {
18596
18749
  "use strict";
18750
+ init_typed();
18597
18751
  init_base();
18598
18752
  init_meta2();
18753
+ _docsTypedHandler = defineTypedHandler("docs", {
18754
+ // ── docs.list ──────────────────────────────────────────────────────────────
18755
+ list: async (params) => {
18756
+ const ownerId = params.task ?? params.session ?? params.observation;
18757
+ if (!ownerId) {
18758
+ return lafsError(
18759
+ "E_INVALID_INPUT",
18760
+ "Provide one of --task, --session, or --observation to scope the list.",
18761
+ "list"
18762
+ );
18763
+ }
18764
+ const ownerType = inferOwnerType(ownerId);
18765
+ const store = createAttachmentStore();
18766
+ const attachments = await store.listByOwner(ownerType, ownerId);
18767
+ const backend = await resolveAttachmentBackend();
18768
+ return lafsSuccess(
18769
+ {
18770
+ ownerId,
18771
+ ownerType,
18772
+ count: attachments.length,
18773
+ attachments: attachments.map((m) => ({
18774
+ id: m.id,
18775
+ sha256: `${m.sha256.slice(0, 8)}\u2026`,
18776
+ // Cast: contracts AttachmentKind doesn't include 'llmtxt-doc' (contracts gap T1529)
18777
+ kind: m.attachment.kind,
18778
+ mime: m.attachment.kind === "local-file" || m.attachment.kind === "blob" ? m.attachment.mime : m.attachment.mime ?? "\u2014",
18779
+ size: m.attachment.kind === "local-file" || m.attachment.kind === "blob" ? m.attachment.size : void 0,
18780
+ description: m.attachment.description,
18781
+ labels: m.attachment.labels,
18782
+ createdAt: m.createdAt,
18783
+ refCount: m.refCount
18784
+ })),
18785
+ // Cast: core returns 'llmtxt'|'legacy'; contracts uses 'legacy'|'llmstxt-v2' (drift T1529)
18786
+ attachmentBackend: backend
18787
+ },
18788
+ "list"
18789
+ );
18790
+ },
18791
+ // ── docs.generate ──────────────────────────────────────────────────────────
18792
+ generate: async (params) => {
18793
+ const forId = params.for;
18794
+ if (!forId) {
18795
+ return lafsError("E_INVALID_INPUT", "--for <taskId|epicId> is required", "generate");
18796
+ }
18797
+ const cwd = getProjectRoot4();
18798
+ const result = await generateDocsLlmsTxt({ ownerId: forId, cwd });
18799
+ let attachmentId;
18800
+ let attachmentSha256;
18801
+ if (params.attach) {
18802
+ const store = createAttachmentStore();
18803
+ const ownerType = inferOwnerType(forId);
18804
+ const contentBytes = Buffer.from(result.content, "utf-8");
18805
+ const llmsTxtDescriptor = {
18806
+ kind: "llms-txt",
18807
+ source: "generated",
18808
+ content: result.content,
18809
+ description: `llms.txt for ${forId} (${result.attachmentCount} docs)`,
18810
+ labels: ["llms-txt", "generated"]
18811
+ };
18812
+ const meta = await store.put(
18813
+ contentBytes,
18814
+ llmsTxtDescriptor,
18815
+ ownerType,
18816
+ forId,
18817
+ "cleo-docs-generate",
18818
+ cwd
18819
+ );
18820
+ attachmentId = meta.id;
18821
+ attachmentSha256 = meta.sha256;
18822
+ }
18823
+ return lafsSuccess(
18824
+ {
18825
+ forId,
18826
+ content: result.content,
18827
+ attachmentCount: result.attachmentCount,
18828
+ usedLlmtxtPackage: result.usedLlmtxtPackage,
18829
+ ...attachmentId !== void 0 ? {
18830
+ attached: true,
18831
+ attachmentId,
18832
+ attachmentSha256
18833
+ } : { attached: false }
18834
+ },
18835
+ "generate"
18836
+ );
18837
+ },
18838
+ // ── docs.fetch ─────────────────────────────────────────────────────────────
18839
+ fetch: async (params) => {
18840
+ const ref = params.attachmentRef;
18841
+ if (!ref) {
18842
+ return lafsError(
18843
+ "E_INVALID_INPUT",
18844
+ "attachmentRef is required (attachment ID or SHA-256 hex)",
18845
+ "fetch"
18846
+ );
18847
+ }
18848
+ const store = createAttachmentStore();
18849
+ const isSha256 = /^[0-9a-f]{64}$/i.test(ref);
18850
+ let fetchResult = null;
18851
+ let metadata = await store.getMetadata(ref);
18852
+ if (metadata) {
18853
+ fetchResult = await store.get(metadata.sha256);
18854
+ } else if (isSha256) {
18855
+ fetchResult = await store.get(ref);
18856
+ if (fetchResult) {
18857
+ metadata = fetchResult.metadata;
18858
+ }
18859
+ }
18860
+ if (!fetchResult || !metadata) {
18861
+ return lafsError("E_NOT_FOUND", `Attachment not found: ${ref}`, "fetch");
18862
+ }
18863
+ const cwd = getProjectRoot4();
18864
+ const cleoDir = getCleoDirAbsolute(cwd);
18865
+ let storagePath;
18866
+ if (metadata.attachment.kind === "local-file") {
18867
+ storagePath = metadata.attachment.path;
18868
+ } else if (metadata.attachment.kind === "blob") {
18869
+ const prefix = metadata.sha256.slice(0, 2);
18870
+ const rest = metadata.sha256.slice(2);
18871
+ const extMap = {
18872
+ "text/markdown": ".md",
18873
+ "text/plain": ".txt",
18874
+ "application/json": ".json",
18875
+ "application/pdf": ".pdf"
18876
+ };
18877
+ const mime = metadata.attachment.kind === "blob" ? metadata.attachment.mime : "application/octet-stream";
18878
+ const ext = extMap[mime] ?? ".bin";
18879
+ storagePath = resolve2(cleoDir, "attachments", "sha256", prefix, `${rest}${ext}`);
18880
+ }
18881
+ const MAX_INLINE = 1024 * 1024;
18882
+ const bytesBase64 = fetchResult.bytes.length <= MAX_INLINE ? fetchResult.bytes.toString("base64") : void 0;
18883
+ const backend = await resolveAttachmentBackend();
18884
+ return lafsSuccess(
18885
+ {
18886
+ // Cast: core's AttachmentMetadata vs contracts/operations/docs AttachmentMetadata differ
18887
+ // in their nested attachment field structure (T1529 contracts gap). The runtime
18888
+ // value is compatible for all callers; the two interfaces diverged at the type level.
18889
+ metadata,
18890
+ path: storagePath,
18891
+ sizeBytes: fetchResult.bytes.length,
18892
+ ...bytesBase64 !== void 0 ? { bytesBase64 } : {},
18893
+ inlined: bytesBase64 !== void 0,
18894
+ // Cast: core returns 'llmtxt'|'legacy'; contracts uses 'legacy'|'llmstxt-v2' (T1529)
18895
+ attachmentBackend: backend
18896
+ },
18897
+ "fetch"
18898
+ );
18899
+ },
18900
+ // ── docs.add ───────────────────────────────────────────────────────────────
18901
+ add: async (params) => {
18902
+ const {
18903
+ ownerId,
18904
+ file: filePath,
18905
+ url,
18906
+ desc: description,
18907
+ labels: rawLabels,
18908
+ attachedBy: rawAttachedBy
18909
+ } = params;
18910
+ if (!ownerId) {
18911
+ return lafsError("E_INVALID_INPUT", "ownerId is required", "add");
18912
+ }
18913
+ if (!filePath && !url) {
18914
+ return lafsError(
18915
+ "E_INVALID_INPUT",
18916
+ "Provide either a file path (positional or --file) or --url",
18917
+ "add"
18918
+ );
18919
+ }
18920
+ const labels = parseLabels(rawLabels);
18921
+ const attachedBy = rawAttachedBy ?? "human";
18922
+ const ownerType = inferOwnerType(ownerId);
18923
+ const store = createAttachmentStore();
18924
+ if (filePath) {
18925
+ const absPath = resolve2(filePath);
18926
+ let bytes;
18927
+ try {
18928
+ bytes = await readFile(absPath);
18929
+ } catch {
18930
+ return lafsError("E_FILE_ERROR", `Cannot read file: ${absPath}`, "add");
18931
+ }
18932
+ const mime = mimeFromPath(absPath);
18933
+ const attachment = {
18934
+ kind: "local-file",
18935
+ path: absPath,
18936
+ mime,
18937
+ size: bytes.length,
18938
+ ...description ? { description } : {},
18939
+ ...labels ? { labels } : {}
18940
+ };
18941
+ const meta = await store.put(bytes, attachment, ownerType, ownerId, attachedBy);
18942
+ let backend = "legacy";
18943
+ try {
18944
+ const v2 = createAttachmentStoreV2(getProjectRoot4());
18945
+ const v2Result = await v2.put(ownerId, {
18946
+ name: absPath.split(/[\\/]/).pop() ?? meta.sha256.slice(0, 12),
18947
+ data: new Uint8Array(bytes),
18948
+ contentType: mime
18949
+ });
18950
+ backend = v2Result.backend;
18951
+ } catch {
18952
+ backend = await resolveAttachmentBackend();
18953
+ }
18954
+ import("@cleocode/core/internal").then(
18955
+ ({ ensureLlmtxtNode }) => ensureLlmtxtNode(
18956
+ getProjectRoot4(),
18957
+ meta.sha256,
18958
+ `${ownerType}:${ownerId}`,
18959
+ absPath.split("/").pop() ?? meta.sha256.slice(0, 12)
18960
+ )
18961
+ ).catch(() => {
18962
+ });
18963
+ return lafsSuccess(
18964
+ {
18965
+ attachmentId: meta.id,
18966
+ sha256: meta.sha256,
18967
+ refCount: meta.refCount,
18968
+ kind: "local-file",
18969
+ ownerId,
18970
+ ownerType,
18971
+ // Cast: core returns 'llmtxt'|'legacy'; contracts uses 'legacy'|'llmstxt-v2' (T1529)
18972
+ attachmentBackend: backend
18973
+ },
18974
+ "add"
18975
+ );
18976
+ }
18977
+ if (url) {
18978
+ const attachment = {
18979
+ kind: "url",
18980
+ url,
18981
+ ...description ? { description } : {},
18982
+ ...labels ? { labels } : {}
18983
+ };
18984
+ const urlBytes = Buffer.from(url, "utf-8");
18985
+ const meta = await store.put(urlBytes, attachment, ownerType, ownerId, attachedBy);
18986
+ import("@cleocode/core/internal").then(
18987
+ ({ ensureLlmtxtNode }) => ensureLlmtxtNode(getProjectRoot4(), meta.sha256, `${ownerType}:${ownerId}`, url)
18988
+ ).catch(() => {
18989
+ });
18990
+ const backend = "legacy";
18991
+ return lafsSuccess(
18992
+ {
18993
+ attachmentId: meta.id,
18994
+ sha256: meta.sha256,
18995
+ refCount: meta.refCount,
18996
+ kind: "url",
18997
+ url,
18998
+ ownerId,
18999
+ ownerType,
19000
+ // Cast: core returns 'llmtxt'|'legacy'; contracts uses 'legacy'|'llmstxt-v2' (T1529)
19001
+ attachmentBackend: backend
19002
+ },
19003
+ "add"
19004
+ );
19005
+ }
19006
+ return lafsError("E_INVALID_INPUT", "Unreachable: no file or url", "add");
19007
+ },
19008
+ // ── docs.remove ────────────────────────────────────────────────────────────
19009
+ remove: async (params) => {
19010
+ const { attachmentRef: ref, from: fromOwner } = params;
19011
+ if (!ref) {
19012
+ return lafsError(
19013
+ "E_INVALID_INPUT",
19014
+ "attachmentRef is required (attachment ID or SHA-256 hex)",
19015
+ "remove"
19016
+ );
19017
+ }
19018
+ if (!fromOwner) {
19019
+ return lafsError("E_INVALID_INPUT", "--from <ownerId> is required", "remove");
19020
+ }
19021
+ const store = createAttachmentStore();
19022
+ const ownerType = inferOwnerType(fromOwner);
19023
+ let attachmentId = ref;
19024
+ if (/^[0-9a-f]{64}$/i.test(ref)) {
19025
+ const result = await store.get(ref);
19026
+ if (!result) {
19027
+ return lafsError("E_NOT_FOUND", `No attachment found with SHA-256: ${ref}`, "remove");
19028
+ }
19029
+ attachmentId = result.metadata.id;
19030
+ }
19031
+ const derefResult = await store.deref(attachmentId, ownerType, fromOwner);
19032
+ if (derefResult.status === "not-found") {
19033
+ return lafsError(
19034
+ "E_NOT_FOUND",
19035
+ `Attachment ref not found: ${attachmentId} on owner ${fromOwner}`,
19036
+ "remove"
19037
+ );
19038
+ }
19039
+ const blobPurged = derefResult.status === "removed";
19040
+ const refCountAfter = derefResult.status === "derefd" ? derefResult.refCountAfter : 0;
19041
+ try {
19042
+ const v2 = createAttachmentStoreV2(getProjectRoot4());
19043
+ await v2.remove(attachmentId, fromOwner);
19044
+ } catch {
19045
+ }
19046
+ const backend = await resolveAttachmentBackend();
19047
+ return lafsSuccess(
19048
+ {
19049
+ removed: blobPurged,
19050
+ attachmentId,
19051
+ from: fromOwner,
19052
+ refCountAfter,
19053
+ blobPurged,
19054
+ // Cast: core returns 'llmtxt'|'legacy'; contracts uses 'legacy'|'llmstxt-v2' (T1529)
19055
+ attachmentBackend: backend
19056
+ },
19057
+ "remove"
19058
+ );
19059
+ }
19060
+ });
19061
+ QUERY_OPS3 = /* @__PURE__ */ new Set(["list", "fetch", "generate"]);
19062
+ MUTATE_OPS3 = /* @__PURE__ */ new Set(["add", "remove"]);
18599
19063
  DocsHandler = class {
18600
19064
  // -----------------------------------------------------------------------
18601
19065
  // Query
18602
19066
  // -----------------------------------------------------------------------
19067
+ /**
19068
+ * Execute a read-only docs query operation.
19069
+ *
19070
+ * @param operation - The docs query op name (e.g. 'list', 'fetch', 'generate').
19071
+ * @param params - Raw params from the dispatcher (narrowed internally).
19072
+ */
18603
19073
  async query(operation, params) {
18604
19074
  const startTime = Date.now();
19075
+ if (!QUERY_OPS3.has(operation)) {
19076
+ return unsupportedOp("query", "docs", operation, startTime);
19077
+ }
18605
19078
  try {
18606
- switch (operation) {
18607
- // ── docs.list ────────────────────────────────────────────────────
18608
- case "list": {
18609
- const taskId = params?.task;
18610
- const sessionId = params?.session;
18611
- const observationId = params?.observation;
18612
- const ownerId = taskId ?? sessionId ?? observationId;
18613
- if (!ownerId) {
18614
- return errorResult(
18615
- "query",
18616
- "docs",
18617
- operation,
18618
- "E_INVALID_INPUT",
18619
- "Provide one of --task, --session, or --observation to scope the list.",
18620
- startTime
18621
- );
18622
- }
18623
- const ownerType = inferOwnerType(ownerId);
18624
- const store = createAttachmentStore();
18625
- const attachments = await store.listByOwner(ownerType, ownerId);
18626
- const backend = await resolveAttachmentBackend();
18627
- return {
18628
- meta: {
18629
- ...dispatchMeta("query", "docs", operation, startTime),
18630
- attachmentBackend: backend
18631
- },
18632
- success: true,
18633
- data: {
18634
- ownerId,
18635
- ownerType,
18636
- count: attachments.length,
18637
- attachments: attachments.map((m) => ({
18638
- id: m.id,
18639
- sha256: `${m.sha256.slice(0, 8)}\u2026`,
18640
- kind: m.attachment.kind,
18641
- mime: m.attachment.kind === "local-file" || m.attachment.kind === "blob" ? m.attachment.mime : m.attachment.mime ?? "\u2014",
18642
- size: m.attachment.kind === "local-file" || m.attachment.kind === "blob" ? m.attachment.size : void 0,
18643
- description: m.attachment.description,
18644
- labels: m.attachment.labels,
18645
- createdAt: m.createdAt,
18646
- refCount: m.refCount
18647
- }))
18648
- }
18649
- };
18650
- }
18651
- // ── docs.generate ────────────────────────────────────────────────
18652
- case "generate": {
18653
- const forId = params?.for;
18654
- if (!forId) {
18655
- return errorResult(
18656
- "query",
18657
- "docs",
18658
- operation,
18659
- "E_INVALID_INPUT",
18660
- "--for <taskId|epicId> is required",
18661
- startTime
18662
- );
18663
- }
18664
- const attach = params?.attach;
18665
- const cwd = getProjectRoot4();
18666
- const result = await generateDocsLlmsTxt({
18667
- ownerId: forId,
18668
- cwd
18669
- });
18670
- let attachmentId;
18671
- let attachmentSha256;
18672
- if (attach) {
18673
- const store = createAttachmentStore();
18674
- const ownerType = inferOwnerType(forId);
18675
- const contentBytes = Buffer.from(result.content, "utf-8");
18676
- const llmsTxtDescriptor = {
18677
- kind: "llms-txt",
18678
- source: "generated",
18679
- content: result.content,
18680
- description: `llms.txt for ${forId} (${result.attachmentCount} docs)`,
18681
- labels: ["llms-txt", "generated"]
18682
- };
18683
- const meta = await store.put(
18684
- contentBytes,
18685
- llmsTxtDescriptor,
18686
- ownerType,
18687
- forId,
18688
- "cleo-docs-generate",
18689
- cwd
18690
- );
18691
- attachmentId = meta.id;
18692
- attachmentSha256 = meta.sha256;
18693
- }
18694
- return {
18695
- meta: dispatchMeta("query", "docs", operation, startTime),
18696
- success: true,
18697
- data: {
18698
- forId,
18699
- content: result.content,
18700
- attachmentCount: result.attachmentCount,
18701
- usedLlmtxtPackage: result.usedLlmtxtPackage,
18702
- ...attachmentId !== void 0 ? {
18703
- attached: true,
18704
- attachmentId,
18705
- attachmentSha256
18706
- } : { attached: false }
18707
- }
18708
- };
18709
- }
18710
- // ── docs.fetch ───────────────────────────────────────────────────
18711
- case "fetch": {
18712
- const ref = params?.attachmentRef;
18713
- if (!ref) {
18714
- return errorResult(
18715
- "query",
18716
- "docs",
18717
- operation,
18718
- "E_INVALID_INPUT",
18719
- "attachmentRef is required (attachment ID or SHA-256 hex)",
18720
- startTime
18721
- );
18722
- }
18723
- const store = createAttachmentStore();
18724
- const isSha256 = /^[0-9a-f]{64}$/i.test(ref);
18725
- let result = null;
18726
- let metadata = await store.getMetadata(ref);
18727
- if (metadata) {
18728
- result = await store.get(metadata.sha256);
18729
- } else if (isSha256) {
18730
- result = await store.get(ref);
18731
- if (result) {
18732
- metadata = result.metadata;
18733
- }
18734
- }
18735
- if (!result || !metadata) {
18736
- return errorResult(
18737
- "query",
18738
- "docs",
18739
- operation,
18740
- "E_NOT_FOUND",
18741
- `Attachment not found: ${ref}`,
18742
- startTime
18743
- );
18744
- }
18745
- const cwd = getProjectRoot4();
18746
- const cleoDir = getCleoDirAbsolute(cwd);
18747
- let storagePath;
18748
- if (metadata.attachment.kind === "local-file") {
18749
- storagePath = metadata.attachment.path;
18750
- } else if (metadata.attachment.kind === "blob") {
18751
- const prefix = metadata.sha256.slice(0, 2);
18752
- const rest = metadata.sha256.slice(2);
18753
- const extMap = {
18754
- "text/markdown": ".md",
18755
- "text/plain": ".txt",
18756
- "application/json": ".json",
18757
- "application/pdf": ".pdf"
18758
- };
18759
- const mime = metadata.attachment.kind === "blob" ? metadata.attachment.mime : "application/octet-stream";
18760
- const ext = extMap[mime] ?? ".bin";
18761
- storagePath = resolve2(cleoDir, "attachments", "sha256", prefix, `${rest}${ext}`);
18762
- }
18763
- const MAX_INLINE = 1024 * 1024;
18764
- const bytesBase64 = result.bytes.length <= MAX_INLINE ? result.bytes.toString("base64") : void 0;
18765
- const backend = await resolveAttachmentBackend();
18766
- return {
18767
- meta: {
18768
- ...dispatchMeta("query", "docs", operation, startTime),
18769
- attachmentBackend: backend
18770
- },
18771
- success: true,
18772
- data: {
18773
- metadata,
18774
- path: storagePath,
18775
- sizeBytes: result.bytes.length,
18776
- ...bytesBase64 !== void 0 ? { bytesBase64 } : {},
18777
- inlined: bytesBase64 !== void 0
18778
- }
18779
- };
18780
- }
18781
- default:
18782
- return unsupportedOp("query", "docs", operation, startTime);
18783
- }
19079
+ const envelope = await typedDispatch(
19080
+ _docsTypedHandler,
19081
+ operation,
19082
+ params ?? {}
19083
+ );
19084
+ return docsEnvelopeToResponse(envelope, "query", operation, startTime);
18784
19085
  } catch (error) {
18785
19086
  return handleErrorResult("query", "docs", operation, error, startTime);
18786
19087
  }
@@ -18788,220 +19089,24 @@ var init_docs = __esm({
18788
19089
  // -----------------------------------------------------------------------
18789
19090
  // Mutate
18790
19091
  // -----------------------------------------------------------------------
19092
+ /**
19093
+ * Execute a state-modifying docs mutation operation.
19094
+ *
19095
+ * @param operation - The docs mutate op name (e.g. 'add', 'remove').
19096
+ * @param params - Raw params from the dispatcher (narrowed internally).
19097
+ */
18791
19098
  async mutate(operation, params) {
18792
19099
  const startTime = Date.now();
19100
+ if (!MUTATE_OPS3.has(operation)) {
19101
+ return unsupportedOp("mutate", "docs", operation, startTime);
19102
+ }
18793
19103
  try {
18794
- switch (operation) {
18795
- // ── docs.add ─────────────────────────────────────────────────────
18796
- case "add": {
18797
- const ownerId = params?.ownerId;
18798
- if (!ownerId) {
18799
- return errorResult(
18800
- "mutate",
18801
- "docs",
18802
- operation,
18803
- "E_INVALID_INPUT",
18804
- "ownerId is required",
18805
- startTime
18806
- );
18807
- }
18808
- const filePath = params?.file;
18809
- const url = params?.url;
18810
- if (!filePath && !url) {
18811
- return errorResult(
18812
- "mutate",
18813
- "docs",
18814
- operation,
18815
- "E_INVALID_INPUT",
18816
- "Provide either a file path (positional or --file) or --url",
18817
- startTime
18818
- );
18819
- }
18820
- const description = params?.desc;
18821
- const labels = parseLabels(params?.labels);
18822
- const attachedBy = params?.attachedBy ?? "human";
18823
- const ownerType = inferOwnerType(ownerId);
18824
- const store = createAttachmentStore();
18825
- if (filePath) {
18826
- const absPath = resolve2(filePath);
18827
- let bytes;
18828
- try {
18829
- bytes = await readFile(absPath);
18830
- } catch {
18831
- return errorResult(
18832
- "mutate",
18833
- "docs",
18834
- operation,
18835
- "E_FILE_ERROR",
18836
- `Cannot read file: ${absPath}`,
18837
- startTime
18838
- );
18839
- }
18840
- const mime = mimeFromPath(absPath);
18841
- const attachment = {
18842
- kind: "local-file",
18843
- path: absPath,
18844
- mime,
18845
- size: bytes.length,
18846
- ...description ? { description } : {},
18847
- ...labels ? { labels } : {}
18848
- };
18849
- const meta = await store.put(bytes, attachment, ownerType, ownerId, attachedBy);
18850
- let backend = "legacy";
18851
- try {
18852
- const v2 = createAttachmentStoreV2(getProjectRoot4());
18853
- const v2Result = await v2.put(ownerId, {
18854
- name: absPath.split(/[\\/]/).pop() ?? meta.sha256.slice(0, 12),
18855
- data: new Uint8Array(bytes),
18856
- contentType: mime
18857
- });
18858
- backend = v2Result.backend;
18859
- } catch {
18860
- backend = await resolveAttachmentBackend();
18861
- }
18862
- import("@cleocode/core/internal").then(
18863
- ({ ensureLlmtxtNode }) => ensureLlmtxtNode(
18864
- getProjectRoot4(),
18865
- meta.sha256,
18866
- `${ownerType}:${ownerId}`,
18867
- absPath.split("/").pop() ?? meta.sha256.slice(0, 12)
18868
- )
18869
- ).catch(() => {
18870
- });
18871
- return {
18872
- meta: {
18873
- ...dispatchMeta("mutate", "docs", operation, startTime),
18874
- attachmentBackend: backend
18875
- },
18876
- success: true,
18877
- data: {
18878
- attachmentId: meta.id,
18879
- sha256: meta.sha256,
18880
- refCount: meta.refCount,
18881
- kind: "local-file",
18882
- ownerId,
18883
- ownerType
18884
- }
18885
- };
18886
- }
18887
- if (url) {
18888
- const attachment = {
18889
- kind: "url",
18890
- url,
18891
- ...description ? { description } : {},
18892
- ...labels ? { labels } : {}
18893
- };
18894
- const urlBytes = Buffer.from(url, "utf-8");
18895
- const meta = await store.put(urlBytes, attachment, ownerType, ownerId, attachedBy);
18896
- import("@cleocode/core/internal").then(
18897
- ({ ensureLlmtxtNode }) => ensureLlmtxtNode(getProjectRoot4(), meta.sha256, `${ownerType}:${ownerId}`, url)
18898
- ).catch(() => {
18899
- });
18900
- const backend = "legacy";
18901
- return {
18902
- meta: {
18903
- ...dispatchMeta("mutate", "docs", operation, startTime),
18904
- attachmentBackend: backend
18905
- },
18906
- success: true,
18907
- data: {
18908
- attachmentId: meta.id,
18909
- sha256: meta.sha256,
18910
- refCount: meta.refCount,
18911
- kind: "url",
18912
- url,
18913
- ownerId,
18914
- ownerType
18915
- }
18916
- };
18917
- }
18918
- return errorResult(
18919
- "mutate",
18920
- "docs",
18921
- operation,
18922
- "E_INVALID_INPUT",
18923
- "Unreachable: no file or url",
18924
- startTime
18925
- );
18926
- }
18927
- // ── docs.remove ──────────────────────────────────────────────────
18928
- case "remove": {
18929
- const ref = params?.attachmentRef;
18930
- const fromOwner = params?.from;
18931
- if (!ref) {
18932
- return errorResult(
18933
- "mutate",
18934
- "docs",
18935
- operation,
18936
- "E_INVALID_INPUT",
18937
- "attachmentRef is required (attachment ID or SHA-256 hex)",
18938
- startTime
18939
- );
18940
- }
18941
- if (!fromOwner) {
18942
- return errorResult(
18943
- "mutate",
18944
- "docs",
18945
- operation,
18946
- "E_INVALID_INPUT",
18947
- "--from <ownerId> is required",
18948
- startTime
18949
- );
18950
- }
18951
- const store = createAttachmentStore();
18952
- const ownerType = inferOwnerType(fromOwner);
18953
- let attachmentId = ref;
18954
- if (/^[0-9a-f]{64}$/i.test(ref)) {
18955
- const result = await store.get(ref);
18956
- if (!result) {
18957
- return errorResult(
18958
- "mutate",
18959
- "docs",
18960
- operation,
18961
- "E_NOT_FOUND",
18962
- `No attachment found with SHA-256: ${ref}`,
18963
- startTime
18964
- );
18965
- }
18966
- attachmentId = result.metadata.id;
18967
- }
18968
- const derefResult = await store.deref(attachmentId, ownerType, fromOwner);
18969
- if (derefResult.status === "not-found") {
18970
- return errorResult(
18971
- "mutate",
18972
- "docs",
18973
- operation,
18974
- "E_NOT_FOUND",
18975
- `Attachment ref not found: ${attachmentId} on owner ${fromOwner}`,
18976
- startTime
18977
- );
18978
- }
18979
- const blobPurged = derefResult.status === "removed";
18980
- const refCountAfter = derefResult.status === "derefd" ? derefResult.refCountAfter : 0;
18981
- try {
18982
- const v2 = createAttachmentStoreV2(getProjectRoot4());
18983
- await v2.remove(attachmentId, fromOwner);
18984
- } catch {
18985
- }
18986
- const backend = await resolveAttachmentBackend();
18987
- return {
18988
- meta: {
18989
- ...dispatchMeta("mutate", "docs", operation, startTime),
18990
- attachmentBackend: backend
18991
- },
18992
- success: true,
18993
- data: {
18994
- removed: blobPurged,
18995
- attachmentId,
18996
- from: fromOwner,
18997
- refCountAfter,
18998
- blobPurged
18999
- }
19000
- };
19001
- }
19002
- default:
19003
- return unsupportedOp("mutate", "docs", operation, startTime);
19004
- }
19104
+ const envelope = await typedDispatch(
19105
+ _docsTypedHandler,
19106
+ operation,
19107
+ params ?? {}
19108
+ );
19109
+ return docsEnvelopeToResponse(envelope, "mutate", operation, startTime);
19005
19110
  } catch (error) {
19006
19111
  return handleErrorResult("mutate", "docs", operation, error, startTime);
19007
19112
  }
@@ -19009,6 +19114,7 @@ var init_docs = __esm({
19009
19114
  // -----------------------------------------------------------------------
19010
19115
  // Supported operations
19011
19116
  // -----------------------------------------------------------------------
19117
+ /** Declared operations for introspection and validation. */
19012
19118
  getSupportedOperations() {
19013
19119
  return {
19014
19120
  query: ["list", "fetch", "generate"],
@@ -19273,7 +19379,7 @@ var init_memory2 = __esm({
19273
19379
  switch (operation) {
19274
19380
  case "find": {
19275
19381
  const query = paramStringRequired(params, "query");
19276
- if (!query) {
19382
+ if (!query)
19277
19383
  return errorResult(
19278
19384
  "query",
19279
19385
  "memory",
@@ -19282,24 +19388,27 @@ var init_memory2 = __esm({
19282
19388
  "query is required",
19283
19389
  startTime
19284
19390
  );
19285
- }
19286
- const result = await memoryFind(
19287
- {
19288
- query,
19289
- limit: paramNumber(params, "limit"),
19290
- tables: paramStringArray(params, "tables"),
19291
- dateStart: paramString(params, "dateStart"),
19292
- dateEnd: paramString(params, "dateEnd"),
19293
- // T418: optional agent filter for per-agent mental model retrieval
19294
- agent: paramString(params, "agent")
19295
- },
19296
- projectRoot
19391
+ return wrapResult(
19392
+ await memoryFind(
19393
+ {
19394
+ query,
19395
+ limit: paramNumber(params, "limit"),
19396
+ tables: paramStringArray(params, "tables"),
19397
+ dateStart: paramString(params, "dateStart"),
19398
+ dateEnd: paramString(params, "dateEnd"),
19399
+ agent: paramString(params, "agent")
19400
+ },
19401
+ projectRoot
19402
+ ),
19403
+ "query",
19404
+ "memory",
19405
+ operation,
19406
+ startTime
19297
19407
  );
19298
- return wrapResult(result, "query", "memory", operation, startTime);
19299
19408
  }
19300
19409
  case "timeline": {
19301
19410
  const anchor = paramStringRequired(params, "anchor");
19302
- if (!anchor) {
19411
+ if (!anchor)
19303
19412
  return errorResult(
19304
19413
  "query",
19305
19414
  "memory",
@@ -19308,20 +19417,24 @@ var init_memory2 = __esm({
19308
19417
  "anchor is required",
19309
19418
  startTime
19310
19419
  );
19311
- }
19312
- const result = await memoryTimeline(
19313
- {
19314
- anchor,
19315
- depthBefore: paramNumber(params, "depthBefore"),
19316
- depthAfter: paramNumber(params, "depthAfter")
19317
- },
19318
- projectRoot
19420
+ return wrapResult(
19421
+ await memoryTimeline(
19422
+ {
19423
+ anchor,
19424
+ depthBefore: paramNumber(params, "depthBefore"),
19425
+ depthAfter: paramNumber(params, "depthAfter")
19426
+ },
19427
+ projectRoot
19428
+ ),
19429
+ "query",
19430
+ "memory",
19431
+ operation,
19432
+ startTime
19319
19433
  );
19320
- return wrapResult(result, "query", "memory", operation, startTime);
19321
19434
  }
19322
19435
  case "fetch": {
19323
19436
  const ids = paramStringArray(params, "ids");
19324
- if (!ids || ids.length === 0) {
19437
+ if (!ids || ids.length === 0)
19325
19438
  return errorResult(
19326
19439
  "query",
19327
19440
  "memory",
@@ -19330,9 +19443,13 @@ var init_memory2 = __esm({
19330
19443
  "ids is required (non-empty array)",
19331
19444
  startTime
19332
19445
  );
19333
- }
19334
- const result = await memoryFetch({ ids }, projectRoot);
19335
- return wrapResult(result, "query", "memory", operation, startTime);
19446
+ return wrapResult(
19447
+ await memoryFetch({ ids }, projectRoot),
19448
+ "query",
19449
+ "memory",
19450
+ operation,
19451
+ startTime
19452
+ );
19336
19453
  }
19337
19454
  case "decision.find": {
19338
19455
  const result = await memoryDecisionFind(
@@ -20786,6 +20903,10 @@ var init_memory2 = __esm({
20786
20903
  return handleErrorResult("mutate", "memory", operation, rollbackErr, startTime);
20787
20904
  }
20788
20905
  }
20906
+ // T1147 W7 — sweep mutate operations (approve, rollback) delegate to query handler
20907
+ // which already handles all sweep sub-commands via a unified case block.
20908
+ case "sweep":
20909
+ return this.query(operation, params);
20789
20910
  default:
20790
20911
  return unsupportedOp("mutate", "memory", operation, startTime);
20791
20912
  }
@@ -20862,6 +20983,8 @@ var init_memory2 = __esm({
20862
20983
  "precompact-flush",
20863
20984
  // T1006 — write a diary-typed observation
20864
20985
  "diary.write",
20986
+ // T1147 W7 — sweep mutate operations (approve, rollback)
20987
+ "sweep",
20865
20988
  // T1003 — staged backfill operations
20866
20989
  "backfill.run",
20867
20990
  "backfill.approve",
@@ -21692,6 +21815,45 @@ import {
21692
21815
  getNexusNativeDb as getNexusNativeDb2,
21693
21816
  getProjectRoot as getProjectRoot7
21694
21817
  } from "@cleocode/core/internal";
21818
+ function nexusQueryEnvelopeToResponse(envelope, operation, startTime) {
21819
+ const env = envelope;
21820
+ let pageMetadata = env.page;
21821
+ let resultData = env.data;
21822
+ if (!pageMetadata && env.success && resultData && typeof resultData === "object") {
21823
+ const dataObj = resultData;
21824
+ if ("page" in dataObj && dataObj.page) {
21825
+ pageMetadata = dataObj.page;
21826
+ const { page: _removed, ...cleanData } = dataObj;
21827
+ resultData = cleanData;
21828
+ }
21829
+ }
21830
+ return wrapResult(
21831
+ {
21832
+ success: env.success,
21833
+ data: resultData,
21834
+ page: pageMetadata,
21835
+ error: env.error ? { code: String(env.error.code), message: env.error.message } : void 0
21836
+ },
21837
+ "query",
21838
+ "nexus",
21839
+ operation,
21840
+ startTime
21841
+ );
21842
+ }
21843
+ function nexusMutateEnvelopeToResponse(envelope, operation, startTime) {
21844
+ const env = envelope;
21845
+ return wrapResult(
21846
+ {
21847
+ success: env.success,
21848
+ data: env.data,
21849
+ error: env.error ? { code: String(env.error.code), message: env.error.message } : void 0
21850
+ },
21851
+ "mutate",
21852
+ "nexus",
21853
+ operation,
21854
+ startTime
21855
+ );
21856
+ }
21695
21857
  async function handleTopEntries(operation, params, startTime) {
21696
21858
  const rawLimit = params?.limit;
21697
21859
  const limit = typeof rawLimit === "number" && Number.isFinite(rawLimit) && rawLimit > 0 ? Math.floor(rawLimit) : 20;
@@ -22038,7 +22200,7 @@ async function handleImpact(operation, params, startTime) {
22038
22200
  return handleErrorResult("query", "nexus", operation, dbErr, startTime);
22039
22201
  }
22040
22202
  }
22041
- var _nexusTypedHandler, QUERY_OPS3, MUTATE_OPS3, NexusHandler, IMPACT_REVERSE_TYPES;
22203
+ var _nexusTypedHandler, QUERY_OPS4, MUTATE_OPS4, NexusHandler, IMPACT_REVERSE_TYPES;
22042
22204
  var init_nexus2 = __esm({
22043
22205
  "packages/cleo/src/dispatch/domains/nexus.ts"() {
22044
22206
  "use strict";
@@ -22354,7 +22516,7 @@ var init_nexus2 = __esm({
22354
22516
  },
22355
22517
  "sigil.sync": async (_params) => wrapCoreResult(await nexusSigilSync(), "sigil.sync")
22356
22518
  });
22357
- QUERY_OPS3 = /* @__PURE__ */ new Set([
22519
+ QUERY_OPS4 = /* @__PURE__ */ new Set([
22358
22520
  "share.status",
22359
22521
  "status",
22360
22522
  "list",
@@ -22386,7 +22548,7 @@ var init_nexus2 = __esm({
22386
22548
  "profile.get",
22387
22549
  "sigil.list"
22388
22550
  ]);
22389
- MUTATE_OPS3 = /* @__PURE__ */ new Set([
22551
+ MUTATE_OPS4 = /* @__PURE__ */ new Set([
22390
22552
  "share.snapshot.export",
22391
22553
  "share.snapshot.import",
22392
22554
  "init",
@@ -22415,7 +22577,7 @@ var init_nexus2 = __esm({
22415
22577
  */
22416
22578
  async query(operation, params) {
22417
22579
  const startTime = Date.now();
22418
- if (!QUERY_OPS3.has(operation)) {
22580
+ if (!QUERY_OPS4.has(operation)) {
22419
22581
  return unsupportedOp("query", "nexus", operation, startTime);
22420
22582
  }
22421
22583
  if (operation === "top-entries") {
@@ -22430,29 +22592,7 @@ var init_nexus2 = __esm({
22430
22592
  operation,
22431
22593
  params ?? {}
22432
22594
  );
22433
- const env = envelope;
22434
- let pageMetadata = env.page;
22435
- let resultData = env.data;
22436
- if (!pageMetadata && env.success && resultData && typeof resultData === "object") {
22437
- const dataObj = resultData;
22438
- if ("page" in dataObj && dataObj.page) {
22439
- pageMetadata = dataObj.page;
22440
- const { page: _removed, ...cleanData } = dataObj;
22441
- resultData = cleanData;
22442
- }
22443
- }
22444
- return wrapResult(
22445
- {
22446
- success: env.success,
22447
- data: resultData,
22448
- page: pageMetadata,
22449
- error: env.error ? { code: String(env.error.code), message: env.error.message } : void 0
22450
- },
22451
- "query",
22452
- "nexus",
22453
- operation,
22454
- startTime
22455
- );
22595
+ return nexusQueryEnvelopeToResponse(envelope, operation, startTime);
22456
22596
  } catch (error) {
22457
22597
  getLogger9("domain:nexus").error(
22458
22598
  { gateway: "query", domain: "nexus", operation, err: error },
@@ -22469,7 +22609,7 @@ var init_nexus2 = __esm({
22469
22609
  */
22470
22610
  async mutate(operation, params) {
22471
22611
  const startTime = Date.now();
22472
- if (!MUTATE_OPS3.has(operation)) {
22612
+ if (!MUTATE_OPS4.has(operation)) {
22473
22613
  return unsupportedOp("mutate", "nexus", operation, startTime);
22474
22614
  }
22475
22615
  try {
@@ -22478,18 +22618,7 @@ var init_nexus2 = __esm({
22478
22618
  operation,
22479
22619
  params ?? {}
22480
22620
  );
22481
- const env = envelope;
22482
- return wrapResult(
22483
- {
22484
- success: env.success,
22485
- data: env.data,
22486
- error: env.error ? { code: String(env.error.code), message: env.error.message } : void 0
22487
- },
22488
- "mutate",
22489
- "nexus",
22490
- operation,
22491
- startTime
22492
- );
22621
+ return nexusMutateEnvelopeToResponse(envelope, operation, startTime);
22493
22622
  } catch (error) {
22494
22623
  getLogger9("domain:nexus").error(
22495
22624
  { gateway: "mutate", domain: "nexus", operation, err: error },
@@ -22501,8 +22630,8 @@ var init_nexus2 = __esm({
22501
22630
  /** Declared operations for introspection and validation. */
22502
22631
  getSupportedOperations() {
22503
22632
  return {
22504
- query: Array.from(QUERY_OPS3),
22505
- mutate: Array.from(MUTATE_OPS3)
22633
+ query: Array.from(QUERY_OPS4),
22634
+ mutate: Array.from(MUTATE_OPS4)
22506
22635
  };
22507
22636
  }
22508
22637
  };
@@ -27407,7 +27536,7 @@ async function lookupApprovalByTokenForDispatch(token) {
27407
27536
  const db = await acquireDb();
27408
27537
  return getPlaybookApprovalByToken(db, token);
27409
27538
  }
27410
- var __playbookRuntimeOverrides, _playbookTypedHandler, QUERY_OPS4, MUTATE_OPS4, PlaybookHandler;
27539
+ var __playbookRuntimeOverrides, _playbookTypedHandler, QUERY_OPS5, MUTATE_OPS5, PlaybookHandler;
27411
27540
  var init_playbook2 = __esm({
27412
27541
  "packages/cleo/src/dispatch/domains/playbook.ts"() {
27413
27542
  "use strict";
@@ -27673,15 +27802,15 @@ var init_playbook2 = __esm({
27673
27802
  }
27674
27803
  }
27675
27804
  });
27676
- QUERY_OPS4 = /* @__PURE__ */ new Set(["status", "list", "validate"]);
27677
- MUTATE_OPS4 = /* @__PURE__ */ new Set(["run", "resume"]);
27805
+ QUERY_OPS5 = /* @__PURE__ */ new Set(["status", "list", "validate"]);
27806
+ MUTATE_OPS5 = /* @__PURE__ */ new Set(["run", "resume"]);
27678
27807
  PlaybookHandler = class {
27679
27808
  /**
27680
27809
  * Query gateway — `status`, `list`, and `validate`.
27681
27810
  */
27682
27811
  async query(operation, params) {
27683
27812
  const startTime = Date.now();
27684
- if (!QUERY_OPS4.has(operation)) {
27813
+ if (!QUERY_OPS5.has(operation)) {
27685
27814
  return unsupportedOp("query", "playbook", operation, startTime);
27686
27815
  }
27687
27816
  try {
@@ -27709,7 +27838,7 @@ var init_playbook2 = __esm({
27709
27838
  */
27710
27839
  async mutate(operation, params) {
27711
27840
  const startTime = Date.now();
27712
- if (!MUTATE_OPS4.has(operation)) {
27841
+ if (!MUTATE_OPS5.has(operation)) {
27713
27842
  return unsupportedOp("mutate", "playbook", operation, startTime);
27714
27843
  }
27715
27844
  try {
@@ -28220,6 +28349,31 @@ async function handleWorktreeCleanup(projectRoot, taskIds, startTime) {
28220
28349
  return handleErrorResult("mutate", "orchestrate", "worktree.cleanup", error, startTime);
28221
28350
  }
28222
28351
  }
28352
+ async function handleWorktreePrune(projectRoot, taskId, startTime) {
28353
+ try {
28354
+ const { pruneWorktree, pruneOrphanedWorktrees } = await import("@cleocode/core/internal");
28355
+ if (taskId) {
28356
+ const result2 = pruneWorktree(taskId, projectRoot);
28357
+ return {
28358
+ meta: dispatchMeta("mutate", "orchestrate", "worktree.prune", startTime),
28359
+ success: true,
28360
+ data: result2
28361
+ };
28362
+ }
28363
+ const result = pruneOrphanedWorktrees(projectRoot, void 0);
28364
+ return {
28365
+ meta: dispatchMeta("mutate", "orchestrate", "worktree.prune", startTime),
28366
+ success: true,
28367
+ data: { ...result, mode: "bulk" }
28368
+ };
28369
+ } catch (error) {
28370
+ getLogger11("domain:orchestrate").error(
28371
+ { operation: "worktree.prune", taskId, err: error },
28372
+ error instanceof Error ? error.message : String(error)
28373
+ );
28374
+ return handleErrorResult("mutate", "orchestrate", "worktree.prune", error, startTime);
28375
+ }
28376
+ }
28223
28377
  var ivtrHandler, OrchestrateHandler, FANOUT_MANIFEST_MAX_SIZE, fanoutManifestStore;
28224
28378
  var init_orchestrate2 = __esm({
28225
28379
  "packages/cleo/src/dispatch/domains/orchestrate.ts"() {
@@ -28287,9 +28441,10 @@ var init_orchestrate2 = __esm({
28287
28441
  const result = await orchestrateAnalyze(epicId, projectRoot, mode);
28288
28442
  return wrapResult(result, "query", "orchestrate", "analyze", startTime);
28289
28443
  }
28444
+ // T408: prompt-based CANT team routing (ADR-030 §5: query, idempotent, advisory)
28290
28445
  case "classify": {
28291
28446
  const request = params?.request;
28292
- if (!request) {
28447
+ if (!request)
28293
28448
  return errorResult(
28294
28449
  "query",
28295
28450
  "orchestrate",
@@ -28298,10 +28453,13 @@ var init_orchestrate2 = __esm({
28298
28453
  "request is required",
28299
28454
  startTime
28300
28455
  );
28301
- }
28302
- const context = params?.context;
28303
- const result = await orchestrateClassify(request, context, projectRoot);
28304
- return wrapResult(result, "query", "orchestrate", operation, startTime);
28456
+ return wrapResult(
28457
+ await orchestrateClassify(request, params?.context, projectRoot),
28458
+ "query",
28459
+ "orchestrate",
28460
+ operation,
28461
+ startTime
28462
+ );
28305
28463
  }
28306
28464
  case "fanout.status": {
28307
28465
  const manifestEntryId = params?.manifestEntryId;
@@ -28594,6 +28752,11 @@ var init_orchestrate2 = __esm({
28594
28752
  const taskIds = params?.taskIds;
28595
28753
  return handleWorktreeCleanup(projectRoot, taskIds, startTime);
28596
28754
  }
28755
+ // T1462 — Single-task worktree prune (used by `cleo orchestrate prune`)
28756
+ case "worktree.prune": {
28757
+ const taskId = params?.taskId;
28758
+ return handleWorktreePrune(projectRoot, taskId, startTime);
28759
+ }
28597
28760
  case "parallel": {
28598
28761
  return routeByParam(params, "action", {
28599
28762
  start: async () => {
@@ -28650,9 +28813,10 @@ var init_orchestrate2 = __esm({
28650
28813
  }
28651
28814
  });
28652
28815
  }
28816
+ // T409: Promise.allSettled fanout wrapper (ADR-030 §5: not idempotent, concurrent)
28653
28817
  case "fanout": {
28654
28818
  const items = params?.items;
28655
- if (!items || !Array.isArray(items) || items.length === 0) {
28819
+ if (!items || !Array.isArray(items) || items.length === 0)
28656
28820
  return errorResult(
28657
28821
  "mutate",
28658
28822
  "orchestrate",
@@ -28661,9 +28825,13 @@ var init_orchestrate2 = __esm({
28661
28825
  "items array is required and must be non-empty",
28662
28826
  startTime
28663
28827
  );
28664
- }
28665
- const result = await orchestrateFanout(items, projectRoot);
28666
- return wrapResult(result, "mutate", "orchestrate", operation, startTime);
28828
+ return wrapResult(
28829
+ await orchestrateFanout(items, projectRoot),
28830
+ "mutate",
28831
+ "orchestrate",
28832
+ operation,
28833
+ startTime
28834
+ );
28667
28835
  }
28668
28836
  case "tessera.instantiate": {
28669
28837
  const templateId = params?.templateId;
@@ -28785,7 +28953,9 @@ var init_orchestrate2 = __esm({
28785
28953
  "reject",
28786
28954
  // T1118 L1 — Worktree lifecycle
28787
28955
  "worktree.complete",
28788
- "worktree.cleanup"
28956
+ "worktree.cleanup",
28957
+ // T1462 — Single-task worktree prune
28958
+ "worktree.prune"
28789
28959
  ]
28790
28960
  };
28791
28961
  }
@@ -29003,6 +29173,44 @@ async function chainAdvanceOp(params) {
29003
29173
  getProjectRoot10()
29004
29174
  );
29005
29175
  }
29176
+ function pipelinePhaseListResponse(envelope, params, operation, startTime) {
29177
+ const listData = envelope.data ?? {};
29178
+ const phases = listData?.phases ?? [];
29179
+ const total = listData?.summary?.total ?? phases.length;
29180
+ const { limit, offset } = getListParams(params);
29181
+ const page = paginate5(phases, limit, offset);
29182
+ return {
29183
+ meta: dispatchMeta("query", "pipeline", operation, startTime),
29184
+ success: true,
29185
+ data: { ...listData, phases: page.items, total, filtered: total },
29186
+ page: page.page
29187
+ };
29188
+ }
29189
+ function pipelineChainListResponse(envelope, params, operation, startTime) {
29190
+ const rawData = envelope.data ?? { _chains: [] };
29191
+ const chains = rawData._chains ?? [];
29192
+ const { limit, offset } = getListParams(params);
29193
+ const page = paginate5(chains, limit, offset);
29194
+ return {
29195
+ meta: dispatchMeta("query", "pipeline", operation, startTime),
29196
+ success: true,
29197
+ data: { chains: page.items, total: chains.length, filtered: chains.length },
29198
+ page: page.page
29199
+ };
29200
+ }
29201
+ function pipelineEnvelopeResponse(envelope, operation, startTime) {
29202
+ const envelopeData = envelope.data;
29203
+ const enginePage = envelopeData?._enginePage;
29204
+ const responseData = envelopeData?._enginePage !== void 0 ? (({ _enginePage: _p, ...rest }) => rest)(
29205
+ envelopeData
29206
+ ) : envelopeData;
29207
+ return {
29208
+ meta: dispatchMeta("query", "pipeline", operation, startTime),
29209
+ success: true,
29210
+ data: responseData,
29211
+ ...enginePage ? { page: enginePage } : {}
29212
+ };
29213
+ }
29006
29214
  var coreOps, _pipelineTypedHandler, PipelineHandler;
29007
29215
  var init_pipeline3 = __esm({
29008
29216
  "packages/cleo/src/dispatch/domains/pipeline.ts"() {
@@ -29369,52 +29577,11 @@ var init_pipeline3 = __esm({
29369
29577
  }
29370
29578
  };
29371
29579
  }
29372
- if (operation === "phase.list") {
29373
- const rawData = envelope.data;
29374
- const listData = rawData;
29375
- const phases = listData?.phases ?? [];
29376
- const total = listData?.summary?.total ?? phases.length;
29377
- const { limit, offset } = getListParams(params);
29378
- const page = paginate5(phases, limit, offset);
29379
- return {
29380
- meta: dispatchMeta("query", "pipeline", operation, startTime),
29381
- success: true,
29382
- data: {
29383
- ...listData,
29384
- phases: page.items,
29385
- total,
29386
- filtered: total
29387
- },
29388
- page: page.page
29389
- };
29390
- }
29391
- if (operation === "chain.list") {
29392
- const rawData = envelope.data;
29393
- const chains = rawData._chains ?? [];
29394
- const { limit, offset } = getListParams(params);
29395
- const page = paginate5(chains, limit, offset);
29396
- return {
29397
- meta: dispatchMeta("query", "pipeline", operation, startTime),
29398
- success: true,
29399
- data: {
29400
- chains: page.items,
29401
- total: chains.length,
29402
- filtered: chains.length
29403
- },
29404
- page: page.page
29405
- };
29406
- }
29407
- const envelopeData = envelope.data;
29408
- const enginePage = envelopeData?._enginePage;
29409
- const responseData = envelopeData?._enginePage !== void 0 ? (({ _enginePage: _p, ...rest }) => rest)(
29410
- envelopeData
29411
- ) : envelopeData;
29412
- return {
29413
- meta: dispatchMeta("query", "pipeline", operation, startTime),
29414
- success: true,
29415
- data: responseData,
29416
- ...enginePage ? { page: enginePage } : {}
29417
- };
29580
+ if (operation === "phase.list")
29581
+ return pipelinePhaseListResponse(envelope, params, operation, startTime);
29582
+ if (operation === "chain.list")
29583
+ return pipelineChainListResponse(envelope, params, operation, startTime);
29584
+ return pipelineEnvelopeResponse(envelope, operation, startTime);
29418
29585
  } catch (error) {
29419
29586
  getLogger12("domain:pipeline").error(
29420
29587
  { gateway: "query", domain: "pipeline", operation, err: error },
@@ -29549,12 +29716,10 @@ var init_release2 = __esm({
29549
29716
  const startTime = Date.now();
29550
29717
  try {
29551
29718
  switch (operation) {
29552
- // ------------------------------------------------------------------
29553
29719
  // release.gate — IVTR gate check (RELEASE-03)
29554
- // ------------------------------------------------------------------
29555
29720
  case "gate": {
29556
29721
  const epicId = params?.["epicId"];
29557
- if (!epicId) {
29722
+ if (!epicId)
29558
29723
  return errorResult(
29559
29724
  "query",
29560
29725
  "release",
@@ -29563,18 +29728,18 @@ var init_release2 = __esm({
29563
29728
  "epicId is required",
29564
29729
  startTime
29565
29730
  );
29566
- }
29567
- const force = params?.["force"] === true;
29568
- const projectRoot = getProjectRoot11();
29569
- const result = await releaseGateCheck(epicId, force, projectRoot);
29570
- return wrapResult(result, "query", "release", operation, startTime);
29731
+ return wrapResult(
29732
+ await releaseGateCheck(epicId, params?.["force"] === true, getProjectRoot11()),
29733
+ "query",
29734
+ "release",
29735
+ operation,
29736
+ startTime
29737
+ );
29571
29738
  }
29572
- // ------------------------------------------------------------------
29573
29739
  // release.ivtr-suggest — IVTR auto-suggest (RELEASE-07)
29574
- // ------------------------------------------------------------------
29575
29740
  case "ivtr-suggest": {
29576
29741
  const taskId = params?.["taskId"];
29577
- if (!taskId) {
29742
+ if (!taskId)
29578
29743
  return errorResult(
29579
29744
  "query",
29580
29745
  "release",
@@ -29583,10 +29748,13 @@ var init_release2 = __esm({
29583
29748
  "taskId is required",
29584
29749
  startTime
29585
29750
  );
29586
- }
29587
- const projectRoot = getProjectRoot11();
29588
- const result = await releaseIvtrAutoSuggest(taskId, projectRoot);
29589
- return wrapResult(result, "query", "release", operation, startTime);
29751
+ return wrapResult(
29752
+ await releaseIvtrAutoSuggest(taskId, getProjectRoot11()),
29753
+ "query",
29754
+ "release",
29755
+ operation,
29756
+ startTime
29757
+ );
29590
29758
  }
29591
29759
  default:
29592
29760
  return errorResult(
@@ -29622,13 +29790,10 @@ var init_release2 = __esm({
29622
29790
  const startTime = Date.now();
29623
29791
  try {
29624
29792
  switch (operation) {
29625
- // ------------------------------------------------------------------
29626
- // release.gate — IVTR gate check (RELEASE-03)
29627
- // Pre-ship guard: blocks release.ship when tasks are not IVTR released.
29628
- // ------------------------------------------------------------------
29793
+ // release.gate — IVTR gate check (RELEASE-03, no DB writes)
29629
29794
  case "gate": {
29630
29795
  const epicId = params?.["epicId"];
29631
- if (!epicId) {
29796
+ if (!epicId)
29632
29797
  return errorResult(
29633
29798
  "mutate",
29634
29799
  "release",
@@ -29637,19 +29802,18 @@ var init_release2 = __esm({
29637
29802
  "epicId is required",
29638
29803
  startTime
29639
29804
  );
29640
- }
29641
- const force = params?.["force"] === true;
29642
- const projectRoot = getProjectRoot11();
29643
- const result = await releaseGateCheck(epicId, force, projectRoot);
29644
- return wrapResult(result, "mutate", "release", operation, startTime);
29805
+ return wrapResult(
29806
+ await releaseGateCheck(epicId, params?.["force"] === true, getProjectRoot11()),
29807
+ "mutate",
29808
+ "release",
29809
+ operation,
29810
+ startTime
29811
+ );
29645
29812
  }
29646
- // ------------------------------------------------------------------
29647
- // release.ivtr-suggest — IVTR auto-suggest (RELEASE-07)
29648
- // Triggered after ivtr.release succeeds; checks if all siblings are done.
29649
- // ------------------------------------------------------------------
29813
+ // release.ivtr-suggest — IVTR auto-suggest (RELEASE-07, no DB writes)
29650
29814
  case "ivtr-suggest": {
29651
29815
  const taskId = params?.["taskId"];
29652
- if (!taskId) {
29816
+ if (!taskId)
29653
29817
  return errorResult(
29654
29818
  "mutate",
29655
29819
  "release",
@@ -29658,10 +29822,13 @@ var init_release2 = __esm({
29658
29822
  "taskId is required",
29659
29823
  startTime
29660
29824
  );
29661
- }
29662
- const projectRoot = getProjectRoot11();
29663
- const result = await releaseIvtrAutoSuggest(taskId, projectRoot);
29664
- return wrapResult(result, "mutate", "release", operation, startTime);
29825
+ return wrapResult(
29826
+ await releaseIvtrAutoSuggest(taskId, getProjectRoot11()),
29827
+ "mutate",
29828
+ "release",
29829
+ operation,
29830
+ startTime
29831
+ );
29665
29832
  }
29666
29833
  default:
29667
29834
  return errorResult(
@@ -29718,7 +29885,7 @@ function envelopeToEngineResult3(envelope) {
29718
29885
  }
29719
29886
  };
29720
29887
  }
29721
- var coreOps2, _sentientTypedHandler, QUERY_OPS5, MUTATE_OPS5, SentientHandler;
29888
+ var coreOps2, _sentientTypedHandler, QUERY_OPS6, MUTATE_OPS6, SentientHandler;
29722
29889
  var init_sentient2 = __esm({
29723
29890
  "packages/cleo/src/dispatch/domains/sentient.ts"() {
29724
29891
  "use strict";
@@ -29838,8 +30005,8 @@ var init_sentient2 = __esm({
29838
30005
  }
29839
30006
  }
29840
30007
  });
29841
- QUERY_OPS5 = /* @__PURE__ */ new Set(["propose.list", "propose.diff", "allowlist.list"]);
29842
- MUTATE_OPS5 = /* @__PURE__ */ new Set([
30008
+ QUERY_OPS6 = /* @__PURE__ */ new Set(["propose.list", "propose.diff", "allowlist.list"]);
30009
+ MUTATE_OPS6 = /* @__PURE__ */ new Set([
29843
30010
  "propose.accept",
29844
30011
  "propose.reject",
29845
30012
  "propose.run",
@@ -29872,7 +30039,7 @@ var init_sentient2 = __esm({
29872
30039
  */
29873
30040
  async query(operation, params) {
29874
30041
  const startTime = Date.now();
29875
- if (!QUERY_OPS5.has(operation)) {
30042
+ if (!QUERY_OPS6.has(operation)) {
29876
30043
  return unsupportedOp("query", "sentient", operation, startTime);
29877
30044
  }
29878
30045
  try {
@@ -29900,7 +30067,7 @@ var init_sentient2 = __esm({
29900
30067
  */
29901
30068
  async mutate(operation, params) {
29902
30069
  const startTime = Date.now();
29903
- if (!MUTATE_OPS5.has(operation)) {
30070
+ if (!MUTATE_OPS6.has(operation)) {
29904
30071
  return unsupportedOp("mutate", "sentient", operation, startTime);
29905
30072
  }
29906
30073
  try {
@@ -30040,7 +30207,7 @@ async function storeSessionOwnerAuthToken(projectRoot, sessionId, token) {
30040
30207
  const db = await getDb(projectRoot);
30041
30208
  db.update(sessions).set({ ownerAuthToken: token }).where(eq(sessions.id, sessionId)).run();
30042
30209
  }
30043
- var coreOps3, _sessionTypedHandler, QUERY_OPS6, MUTATE_OPS6, SessionHandler;
30210
+ var coreOps3, _sessionTypedHandler, QUERY_OPS7, MUTATE_OPS7, SessionHandler;
30044
30211
  var init_session3 = __esm({
30045
30212
  "packages/cleo/src/dispatch/domains/session.ts"() {
30046
30213
  "use strict";
@@ -30070,10 +30237,12 @@ var init_session3 = __esm({
30070
30237
  // Query ops
30071
30238
  // -------------------------------------------------------------------------
30072
30239
  // Engine guarantees data on success; fallback mirrors empty-state shape.
30240
+ // overrideCount included per T1501 / P0-5.
30073
30241
  status: async (_params) => wrapCoreResult(await coreOps3.status(), "status", {
30074
30242
  hasActiveSession: false,
30075
30243
  session: null,
30076
- taskWork: null
30244
+ taskWork: null,
30245
+ overrideCount: 0
30077
30246
  }),
30078
30247
  list: async (params) => wrapCoreResult(await coreOps3.list(params), "list"),
30079
30248
  // session.show absorbs debrief.show via include param (T5615)
@@ -30254,7 +30423,7 @@ var init_session3 = __esm({
30254
30423
  return wrapCoreResult(result, "record.assumption");
30255
30424
  }
30256
30425
  });
30257
- QUERY_OPS6 = /* @__PURE__ */ new Set([
30426
+ QUERY_OPS7 = /* @__PURE__ */ new Set([
30258
30427
  "status",
30259
30428
  "list",
30260
30429
  "show",
@@ -30264,7 +30433,7 @@ var init_session3 = __esm({
30264
30433
  "handoff.show",
30265
30434
  "briefing.show"
30266
30435
  ]);
30267
- MUTATE_OPS6 = /* @__PURE__ */ new Set([
30436
+ MUTATE_OPS7 = /* @__PURE__ */ new Set([
30268
30437
  "start",
30269
30438
  "end",
30270
30439
  "resume",
@@ -30285,7 +30454,7 @@ var init_session3 = __esm({
30285
30454
  */
30286
30455
  async query(operation, params) {
30287
30456
  const startTime = Date.now();
30288
- if (!QUERY_OPS6.has(operation)) {
30457
+ if (!QUERY_OPS7.has(operation)) {
30289
30458
  return unsupportedOp("query", "session", operation, startTime);
30290
30459
  }
30291
30460
  try {
@@ -30314,7 +30483,7 @@ var init_session3 = __esm({
30314
30483
  */
30315
30484
  async mutate(operation, params) {
30316
30485
  const startTime = Date.now();
30317
- if (!MUTATE_OPS6.has(operation)) {
30486
+ if (!MUTATE_OPS7.has(operation)) {
30318
30487
  return unsupportedOp("mutate", "session", operation, startTime);
30319
30488
  }
30320
30489
  try {
@@ -30362,6 +30531,7 @@ var init_session3 = __esm({
30362
30531
  });
30363
30532
 
30364
30533
  // packages/cleo/src/dispatch/engines/sticky-engine.ts
30534
+ import { paginate as paginate6 } from "@cleocode/core";
30365
30535
  import {
30366
30536
  addSticky,
30367
30537
  archiveSticky,
@@ -30381,10 +30551,17 @@ async function stickyAdd(projectRoot, params) {
30381
30551
  return engineError("E_INTERNAL", String(error));
30382
30552
  }
30383
30553
  }
30384
- async function stickyList(projectRoot, params = {}) {
30554
+ async function stickyListFiltered(projectRoot, filters, limit, offset) {
30385
30555
  try {
30386
- const stickies = await listStickies(params, projectRoot);
30387
- return { success: true, data: { stickies, total: stickies.length } };
30556
+ const filteredStickies = await listStickies(filters, projectRoot);
30557
+ const hasFilter = filters.status !== void 0 || filters.color !== void 0 || filters.priority !== void 0 || filters.tags !== void 0 && filters.tags.length > 0;
30558
+ const total = hasFilter ? (await listStickies({}, projectRoot)).length : filteredStickies.length;
30559
+ const page = paginate6(filteredStickies, limit, offset);
30560
+ return {
30561
+ success: true,
30562
+ data: { stickies: page.items, total, filtered: filteredStickies.length },
30563
+ page: page.page
30564
+ };
30388
30565
  } catch (error) {
30389
30566
  return engineError("E_INTERNAL", String(error));
30390
30567
  }
@@ -30474,14 +30651,13 @@ var init_sticky_engine = __esm({
30474
30651
  });
30475
30652
 
30476
30653
  // packages/cleo/src/dispatch/domains/sticky.ts
30477
- import { getLogger as getLogger15, getProjectRoot as getProjectRoot14, paginate as paginate6 } from "@cleocode/core";
30654
+ import { getLogger as getLogger15, getProjectRoot as getProjectRoot14 } from "@cleocode/core";
30478
30655
  var StickyHandler;
30479
30656
  var init_sticky = __esm({
30480
30657
  "packages/cleo/src/dispatch/domains/sticky.ts"() {
30481
30658
  "use strict";
30482
30659
  init_sticky_engine();
30483
30660
  init_base();
30484
- init_meta2();
30485
30661
  StickyHandler = class {
30486
30662
  // -----------------------------------------------------------------------
30487
30663
  // Query
@@ -30492,36 +30668,18 @@ var init_sticky = __esm({
30492
30668
  try {
30493
30669
  switch (operation) {
30494
30670
  case "list": {
30495
- const tags = params?.tags;
30496
- const filters = {
30497
- status: params?.status,
30498
- color: params?.color,
30499
- priority: params?.priority,
30500
- tags
30501
- };
30502
- const result = await stickyList(projectRoot, filters);
30503
- if (!result.success) {
30504
- return wrapResult(result, "query", "sticky", operation, startTime);
30505
- }
30506
- const filteredStickies = result.data?.stickies ?? [];
30507
- const hasFilter = filters.status !== void 0 || filters.color !== void 0 || filters.priority !== void 0 || tags !== void 0 && tags.length > 0;
30508
- const totalResult = hasFilter ? await stickyList(projectRoot, {}) : result;
30509
- if (!totalResult.success) {
30510
- return wrapResult(totalResult, "query", "sticky", operation, startTime);
30511
- }
30512
- const limit = params?.limit;
30513
- const offset = params?.offset;
30514
- const page = paginate6(filteredStickies, limit, offset);
30515
- return {
30516
- meta: dispatchMeta("query", "sticky", operation, startTime),
30517
- success: true,
30518
- data: {
30519
- stickies: page.items,
30520
- total: totalResult.data?.total ?? filteredStickies.length,
30521
- filtered: filteredStickies.length
30671
+ const result = await stickyListFiltered(
30672
+ projectRoot,
30673
+ {
30674
+ status: params?.status,
30675
+ color: params?.color,
30676
+ priority: params?.priority,
30677
+ tags: params?.tags
30522
30678
  },
30523
- page: page.page
30524
- };
30679
+ params?.limit,
30680
+ params?.offset
30681
+ );
30682
+ return wrapResult(result, "query", "sticky", operation, startTime);
30525
30683
  }
30526
30684
  case "show": {
30527
30685
  const stickyId = params?.stickyId;
@@ -30707,7 +30865,7 @@ function envelopeToEngineResult5(envelope) {
30707
30865
  }
30708
30866
  };
30709
30867
  }
30710
- var _tasksTypedHandler, QUERY_OPS7, MUTATE_OPS7, TasksHandler;
30868
+ var _tasksTypedHandler, QUERY_OPS8, MUTATE_OPS8, TasksHandler;
30711
30869
  var init_tasks3 = __esm({
30712
30870
  "packages/cleo/src/dispatch/domains/tasks.ts"() {
30713
30871
  "use strict";
@@ -31046,7 +31204,7 @@ var init_tasks3 = __esm({
31046
31204
  return wrapCoreResult(await taskUnclaim(projectRoot, params.taskId), "unclaim");
31047
31205
  }
31048
31206
  });
31049
- QUERY_OPS7 = /* @__PURE__ */ new Set([
31207
+ QUERY_OPS8 = /* @__PURE__ */ new Set([
31050
31208
  "show",
31051
31209
  "list",
31052
31210
  "find",
@@ -31064,7 +31222,7 @@ var init_tasks3 = __esm({
31064
31222
  "label.list",
31065
31223
  "sync.links"
31066
31224
  ]);
31067
- MUTATE_OPS7 = /* @__PURE__ */ new Set([
31225
+ MUTATE_OPS8 = /* @__PURE__ */ new Set([
31068
31226
  "add",
31069
31227
  "update",
31070
31228
  "complete",
@@ -31094,7 +31252,7 @@ var init_tasks3 = __esm({
31094
31252
  */
31095
31253
  async query(operation, params) {
31096
31254
  const startTime = Date.now();
31097
- if (!QUERY_OPS7.has(operation)) {
31255
+ if (!QUERY_OPS8.has(operation)) {
31098
31256
  return unsupportedOp("query", "tasks", operation, startTime);
31099
31257
  }
31100
31258
  if (operation === "impact" && !params?.change) {
@@ -31133,7 +31291,7 @@ var init_tasks3 = __esm({
31133
31291
  */
31134
31292
  async mutate(operation, params) {
31135
31293
  const startTime = Date.now();
31136
- if (!MUTATE_OPS7.has(operation)) {
31294
+ if (!MUTATE_OPS8.has(operation)) {
31137
31295
  return unsupportedOp("mutate", "tasks", operation, startTime);
31138
31296
  }
31139
31297
  try {
@@ -52305,6 +52463,29 @@ var fanoutCommand = defineCommand({
52305
52463
  );
52306
52464
  }
52307
52465
  });
52466
+ var pruneCommand = defineCommand({
52467
+ meta: {
52468
+ name: "prune",
52469
+ description: "Remove stale agent worktrees (after task completion or crash)"
52470
+ },
52471
+ args: {
52472
+ taskId: {
52473
+ type: "positional",
52474
+ description: "Task ID whose worktree should be pruned (omit for bulk prune)",
52475
+ required: false
52476
+ }
52477
+ },
52478
+ async run({ args }) {
52479
+ const taskId = typeof args.taskId === "string" && args.taskId.length > 0 ? args.taskId : void 0;
52480
+ await dispatchFromCli(
52481
+ "mutate",
52482
+ "orchestrate",
52483
+ "worktree.prune",
52484
+ { taskId },
52485
+ { command: "orchestrate" }
52486
+ );
52487
+ }
52488
+ });
52308
52489
  var conduitStatusCommand = defineCommand({
52309
52490
  meta: { name: "conduit-status", description: "Get conduit messaging status" },
52310
52491
  async run() {
@@ -52486,6 +52667,7 @@ var orchestrateCommand = defineCommand({
52486
52667
  handoff: handoffCommand,
52487
52668
  "spawn-execute": spawnExecuteCommand,
52488
52669
  fanout: fanoutCommand,
52670
+ prune: pruneCommand,
52489
52671
  "conduit-status": conduitStatusCommand,
52490
52672
  "conduit-peek": conduitPeekCommand,
52491
52673
  "conduit-start": conduitStartCommand,
@@ -58622,7 +58804,7 @@ var migrateCommand2 = defineCommand({
58622
58804
  }
58623
58805
  }
58624
58806
  });
58625
- var pruneCommand = defineCommand({
58807
+ var pruneCommand2 = defineCommand({
58626
58808
  meta: {
58627
58809
  name: "prune",
58628
58810
  description: "Prune session transcripts older than the specified duration. Dry-run by default."
@@ -58749,7 +58931,7 @@ var transcriptCommand = defineCommand({
58749
58931
  scan: scanCommand,
58750
58932
  extract: extractCommand,
58751
58933
  migrate: migrateCommand2,
58752
- prune: pruneCommand
58934
+ prune: pruneCommand2
58753
58935
  },
58754
58936
  async run({ cmd, rawArgs }) {
58755
58937
  const firstArg = rawArgs?.find((a) => !a.startsWith("-"));
@@ -59095,6 +59277,10 @@ var verifyCommand2 = defineCommand({
59095
59277
  explain: {
59096
59278
  type: "boolean",
59097
59279
  description: "Enrich read-only view with per-gate evidence breakdown, re-validation status, and blockers[] preventing `cleo complete` (T1013 / ADR-051)."
59280
+ },
59281
+ "shared-evidence": {
59282
+ type: "boolean",
59283
+ description: "Acknowledge that the same evidence atom is applied to >3 distinct tasks in this session (T1502 / ADR-059). Without this flag, such reuse triggers a warning; in strict mode (CLEO_STRICT_EVIDENCE=1) it is a hard reject."
59098
59284
  }
59099
59285
  },
59100
59286
  async run({ args, cmd }) {
@@ -59116,7 +59302,8 @@ var verifyCommand2 = defineCommand({
59116
59302
  agent: args.agent,
59117
59303
  all: args.all,
59118
59304
  reset: args.reset,
59119
- evidence: args.evidence
59305
+ evidence: args.evidence,
59306
+ sharedEvidence: args["shared-evidence"] ?? false
59120
59307
  },
59121
59308
  { command: "verify" }
59122
59309
  );