@cleocode/cleo 2026.5.120 → 2026.5.122

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
@@ -1730,7 +1730,7 @@ var init_branch_lock = __esm({
1730
1730
 
1731
1731
  // packages/contracts/src/changesets.ts
1732
1732
  import { z as z3 } from "zod";
1733
- var CHANGESET_KINDS, TASK_ID_RE, ChangesetEntrySchema;
1733
+ var CHANGESET_KINDS, CHANGESET_RELEASE_NOTE_SECTIONS, CHANGESET_RELEASE_NOTE_AUDIENCES, CHANGESET_RELEASE_NOTE_SCOPES, nonEmptyReleaseNoteText, nonEmptyReleaseNoteList, ChangesetReleaseNotesMetadataSchema, TASK_ID_RE, ChangesetEntrySchema;
1734
1734
  var init_changesets = __esm({
1735
1735
  "packages/contracts/src/changesets.ts"() {
1736
1736
  "use strict";
@@ -1744,10 +1744,60 @@ var init_changesets = __esm({
1744
1744
  "chore",
1745
1745
  "breaking"
1746
1746
  ];
1747
+ CHANGESET_RELEASE_NOTE_SECTIONS = [
1748
+ "added",
1749
+ "changed",
1750
+ "fixed",
1751
+ "deprecated",
1752
+ "removed",
1753
+ "security",
1754
+ "breaking"
1755
+ ];
1756
+ CHANGESET_RELEASE_NOTE_AUDIENCES = [
1757
+ "users",
1758
+ "operators",
1759
+ "developers",
1760
+ "maintainers"
1761
+ ];
1762
+ CHANGESET_RELEASE_NOTE_SCOPES = [
1763
+ "project",
1764
+ "package",
1765
+ "component",
1766
+ "docs",
1767
+ "ops",
1768
+ "security"
1769
+ ];
1770
+ nonEmptyReleaseNoteText = z3.string().min(1, "release-note metadata text must be non-empty");
1771
+ nonEmptyReleaseNoteList = z3.array(nonEmptyReleaseNoteText).min(1, "release-note metadata list must contain at least one item");
1772
+ ChangesetReleaseNotesMetadataSchema = z3.object({
1773
+ /** Keep-a-Changelog style section/category override. */
1774
+ section: z3.enum(CHANGESET_RELEASE_NOTE_SECTIONS).optional(),
1775
+ /** Intended readers for the note. */
1776
+ audience: z3.array(z3.enum(CHANGESET_RELEASE_NOTE_AUDIENCES)).min(1).optional(),
1777
+ /** Release-note scope. */
1778
+ scope: z3.enum(CHANGESET_RELEASE_NOTE_SCOPES).optional(),
1779
+ /** Package/project/component targets affected by this entry. */
1780
+ targets: nonEmptyReleaseNoteList.optional(),
1781
+ /** User- or operator-visible impact statement. */
1782
+ impact: nonEmptyReleaseNoteText.optional(),
1783
+ /** Deterministic migration/action text, separate from breaking changes. */
1784
+ migration: nonEmptyReleaseNoteText.optional(),
1785
+ /** Deprecation detail for Deprecated sections. */
1786
+ deprecation: nonEmptyReleaseNoteText.optional(),
1787
+ /** Security detail for Security sections. */
1788
+ security: nonEmptyReleaseNoteText.optional(),
1789
+ /** Operator-facing rollout/verification note. */
1790
+ operatorNotes: nonEmptyReleaseNoteText.optional(),
1791
+ /** Explicit inclusion toggle for future release-scope filters. */
1792
+ includeInChangelog: z3.boolean().optional()
1793
+ }).strict();
1747
1794
  TASK_ID_RE = /^(T\d+(-[A-Z][A-Za-z0-9]*)?|E-\d+(-[A-Z][A-Za-z0-9]*)?)$/;
1748
1795
  ChangesetEntrySchema = z3.object({
1749
- /** Filename slug (without the `.md` extension). */
1750
- id: z3.string().min(1, "id must be non-empty").regex(/^[a-z0-9][a-z0-9-]*$/, "id must be kebab-case (lowercase, digits, hyphens)"),
1796
+ /** Filename identifier (without the `.md` extension); lowercase kebab-case for new files, legacy uppercase task IDs accepted. */
1797
+ id: z3.string().min(1, "id must be non-empty").regex(
1798
+ /^[A-Za-z0-9][A-Za-z0-9-]*$/,
1799
+ "id must contain only ASCII letters, digits, and hyphens"
1800
+ ),
1751
1801
  /** One or more CLEO task IDs this change is anchored to. */
1752
1802
  tasks: z3.array(z3.string().regex(TASK_ID_RE, "task ID must match T#### or E-#### format")).min(1, "tasks must contain at least one task ID"),
1753
1803
  /** Type of change. */
@@ -1759,7 +1809,9 @@ var init_changesets = __esm({
1759
1809
  /** Markdown body — longer-form explanation. */
1760
1810
  notes: z3.string().optional(),
1761
1811
  /** Migration note. Required iff `kind === 'breaking'`. */
1762
- breaking: z3.string().optional()
1812
+ breaking: z3.string().optional(),
1813
+ /** Structured author-provided metadata for deterministic release notes. */
1814
+ releaseNotes: ChangesetReleaseNotesMetadataSchema.optional()
1763
1815
  }).refine((entry) => entry.kind !== "breaking" || (entry.breaking?.length ?? 0) > 0, {
1764
1816
  message: "breaking entries must include a non-empty `breaking` migration note",
1765
1817
  path: ["breaking"]
@@ -9367,6 +9419,35 @@ var init_operations_registry = __esm({
9367
9419
  }
9368
9420
  ]
9369
9421
  },
9422
+ // release query: validate-changelog (T9937 / Saga T9862 — canonical CHANGELOG
9423
+ // header validator that replaces the brittle inline grep step in
9424
+ // .github/workflows/release.yml). Read-only — exposed only under the query
9425
+ // gateway because no DB or filesystem mutation occurs.
9426
+ {
9427
+ gateway: "query",
9428
+ domain: "release",
9429
+ operation: "validate-changelog",
9430
+ description: "release.validate-changelog (query) \u2014 validate that CHANGELOG.md contains the canonical `## [VERSION]` header per ADR-028 \xA72.5. Replaces the brittle inline grep in .github/workflows/release.yml (T9937 / Saga T9862).",
9431
+ tier: 1,
9432
+ idempotent: true,
9433
+ sessionRequired: false,
9434
+ requiredParams: ["version"],
9435
+ params: [
9436
+ {
9437
+ name: "version",
9438
+ type: "string",
9439
+ required: true,
9440
+ description: "Release version (accepts v2026.5.94 or 2026.5.94)",
9441
+ cli: { positional: true }
9442
+ },
9443
+ {
9444
+ name: "changelogPath",
9445
+ type: "string",
9446
+ required: false,
9447
+ description: "Override the CHANGELOG file path (default: <projectRoot>/CHANGELOG.md)"
9448
+ }
9449
+ ]
9450
+ },
9370
9451
  // ---------------------------------------------------------------------------
9371
9452
  // Provenance domain — `cleo provenance` CLI surface (T9528 · Phase 2 of T9493)
9372
9453
  // ---------------------------------------------------------------------------
@@ -10519,6 +10600,7 @@ var init_exit_codes = __esm({
10519
10600
  ExitCode2[ExitCode2["LAFS_VIOLATION"] = 104] = "LAFS_VIOLATION";
10520
10601
  ExitCode2[ExitCode2["DECISION_VALIDATOR_FAILED"] = 106] = "DECISION_VALIDATOR_FAILED";
10521
10602
  ExitCode2[ExitCode2["LEAD_BYPASS_DETECTED"] = 107] = "LEAD_BYPASS_DETECTED";
10603
+ ExitCode2[ExitCode2["AC_COVERAGE_INCOMPLETE"] = 108] = "AC_COVERAGE_INCOMPLETE";
10522
10604
  return ExitCode2;
10523
10605
  })(ExitCode || {});
10524
10606
  }
@@ -10546,7 +10628,7 @@ var init_errors = __esm({
10546
10628
 
10547
10629
  // packages/contracts/src/evidence-atom-schema.ts
10548
10630
  import { z as z6 } from "zod";
10549
- var commitAtomSchema, filesAtomSchema, testRunAtomSchema, toolAtomSchema, urlAtomSchema, noteAtomSchema, decisionAtomSchema, prAtomSchema, locDropAtomSchema, callsiteCoverageAtomSchema, EvidenceAtomSchema, GATE_EVIDENCE_REQUIREMENTS;
10631
+ var commitAtomSchema, filesAtomSchema, testRunAtomSchema, toolAtomSchema, urlAtomSchema, noteAtomSchema, decisionAtomSchema, prAtomSchema, locDropAtomSchema, callsiteCoverageAtomSchema, AC_UUID_REGEX, AC_ALIAS_REGEX, SATISFIES_TASK_ID_REGEX, SATISFIES_VERSION_PIN_REGEX, satisfiesAtomSchema, EvidenceAtomSchema, GATE_EVIDENCE_REQUIREMENTS, ATOM_EXAMPLES;
10550
10632
  var init_evidence_atom_schema = __esm({
10551
10633
  "packages/contracts/src/evidence-atom-schema.ts"() {
10552
10634
  "use strict";
@@ -10592,6 +10674,24 @@ var init_evidence_atom_schema = __esm({
10592
10674
  symbolName: z6.string().min(1, "callsite-coverage atom requires a non-empty symbolName"),
10593
10675
  relativeSourcePath: z6.string().min(1, "callsite-coverage atom requires a non-empty relativeSourcePath")
10594
10676
  });
10677
+ AC_UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
10678
+ AC_ALIAS_REGEX = /^AC[0-9]{1,4}$/;
10679
+ SATISFIES_TASK_ID_REGEX = /^T[0-9]{1,7}$/;
10680
+ SATISFIES_VERSION_PIN_REGEX = /^[0-9]{14}$/;
10681
+ satisfiesAtomSchema = z6.object({
10682
+ kind: z6.literal("satisfies"),
10683
+ /** Target task ID — `T<1-7 digits>` per ADR-079-r2 §2.1. */
10684
+ targetTaskId: z6.string().regex(SATISFIES_TASK_ID_REGEX, "satisfies atom targetTaskId must match /^T[0-9]{1,7}$/"),
10685
+ /** Lowercase UUIDv4 — populated for the canonical form; undefined for alias form. */
10686
+ targetAcId: z6.string().regex(AC_UUID_REGEX, "satisfies atom targetAcId must be a lowercase UUIDv4").optional(),
10687
+ /** Positional alias `AC<1-4 digits>` — populated for alias form; undefined for UUID form. */
10688
+ targetAcAlias: z6.string().regex(AC_ALIAS_REGEX, "satisfies atom targetAcAlias must match /^AC[0-9]{1,4}$/").optional(),
10689
+ /** Optional `@<14-digit YYYYMMDDhhmmss>` pin captured at mint time. */
10690
+ versionPin: z6.string().regex(
10691
+ SATISFIES_VERSION_PIN_REGEX,
10692
+ "satisfies atom versionPin must be 14 digits (YYYYMMDDhhmmss)"
10693
+ ).optional()
10694
+ });
10595
10695
  EvidenceAtomSchema = z6.discriminatedUnion("kind", [
10596
10696
  commitAtomSchema,
10597
10697
  filesAtomSchema,
@@ -10602,7 +10702,8 @@ var init_evidence_atom_schema = __esm({
10602
10702
  decisionAtomSchema,
10603
10703
  prAtomSchema,
10604
10704
  locDropAtomSchema,
10605
- callsiteCoverageAtomSchema
10705
+ callsiteCoverageAtomSchema,
10706
+ satisfiesAtomSchema
10606
10707
  ]);
10607
10708
  GATE_EVIDENCE_REQUIREMENTS = Object.freeze({
10608
10709
  implemented: {
@@ -10621,6 +10722,19 @@ var init_evidence_atom_schema = __esm({
10621
10722
  cleanupDone: { oneOf: [["note"]] },
10622
10723
  nexusImpact: { oneOf: [["tool"], ["note"]] }
10623
10724
  });
10725
+ ATOM_EXAMPLES = Object.freeze({
10726
+ commit: "commit:<sha>",
10727
+ files: "files:path/a.ts,path/b.ts",
10728
+ "test-run": "test-run:/tmp/vitest-out.json",
10729
+ tool: "tool:test",
10730
+ url: "url:https://example.com/docs",
10731
+ note: "note:<short description>",
10732
+ decision: "decision:D-arch-001",
10733
+ pr: "pr:357",
10734
+ "loc-drop": "loc-drop:<fromLines>:<toLines>",
10735
+ "callsite-coverage": "callsite-coverage:<symbolName>:<relativeSourcePath>",
10736
+ satisfies: "satisfies:T1234#AC2"
10737
+ });
10624
10738
  }
10625
10739
  });
10626
10740
 
@@ -12435,6 +12549,52 @@ var init_manifest2 = __esm({
12435
12549
  }
12436
12550
  });
12437
12551
 
12552
+ // packages/contracts/src/validator/index.ts
12553
+ import { z as z14 } from "zod";
12554
+ var VALIDATOR_ID_REGEX, validatorFindingSchema, validatorAttestationSchema, validatorRejectionSchema, validatorVerdictSchema;
12555
+ var init_validator = __esm({
12556
+ "packages/contracts/src/validator/index.ts"() {
12557
+ "use strict";
12558
+ VALIDATOR_ID_REGEX = /^validator-[a-z0-9][a-z0-9-]*$/;
12559
+ validatorFindingSchema = z14.object({
12560
+ acId: z14.string().min(1, "acId must be non-empty"),
12561
+ status: z14.enum(["pass", "fail", "inconclusive"]),
12562
+ reasoning: z14.string().min(1, "reasoning must be non-empty"),
12563
+ evidenceRefs: z14.array(z14.string()).optional(),
12564
+ checkedAt: z14.string().min(1, "checkedAt must be a non-empty ISO-8601 string")
12565
+ });
12566
+ validatorAttestationSchema = z14.object({
12567
+ verdict: z14.literal("attest"),
12568
+ taskId: z14.string().min(1),
12569
+ validatorId: z14.string().regex(VALIDATOR_ID_REGEX, "validatorId must match the pattern validator-<discriminator>"),
12570
+ findings: z14.array(validatorFindingSchema).min(1, "attestation must contain at least one finding").refine(
12571
+ (findings) => findings.every((f) => f.status === "pass"),
12572
+ 'attestation requires every finding to have status="pass"'
12573
+ ),
12574
+ summary: z14.string().optional(),
12575
+ attestedAt: z14.string().min(1),
12576
+ schemaVersion: z14.literal("1")
12577
+ });
12578
+ validatorRejectionSchema = z14.object({
12579
+ verdict: z14.literal("reject"),
12580
+ taskId: z14.string().min(1),
12581
+ validatorId: z14.string().regex(VALIDATOR_ID_REGEX, "validatorId must match the pattern validator-<discriminator>"),
12582
+ findings: z14.array(validatorFindingSchema).min(1, "rejection must contain at least one finding").refine(
12583
+ (findings) => findings.some((f) => f.status !== "pass"),
12584
+ 'rejection requires at least one finding with status "fail" or "inconclusive"'
12585
+ ),
12586
+ summary: z14.string().min(1, "rejection summary must be non-empty"),
12587
+ remediationHints: z14.array(z14.string()).optional(),
12588
+ rejectedAt: z14.string().min(1),
12589
+ schemaVersion: z14.literal("1")
12590
+ });
12591
+ validatorVerdictSchema = z14.discriminatedUnion("verdict", [
12592
+ validatorAttestationSchema,
12593
+ validatorRejectionSchema
12594
+ ]);
12595
+ }
12596
+ });
12597
+
12438
12598
  // packages/contracts/src/index.ts
12439
12599
  var init_src2 = __esm({
12440
12600
  "packages/contracts/src/index.ts"() {
@@ -12478,6 +12638,7 @@ var init_src2 = __esm({
12478
12638
  init_task_evidence();
12479
12639
  init_archive();
12480
12640
  init_manifest2();
12641
+ init_validator();
12481
12642
  }
12482
12643
  });
12483
12644
 
@@ -13807,6 +13968,7 @@ __export(engine_exports, {
13807
13968
  taskWorkHistory: () => taskWorkHistory,
13808
13969
  tasksAddBatchOp: () => tasksAddBatchOp,
13809
13970
  validateBatchValidate: () => coreBatchValidate,
13971
+ validateChangelog: () => validateChangelog,
13810
13972
  validateCoherenceCheck: () => coreCoherenceCheck,
13811
13973
  validateComplianceRecord: () => coreComplianceRecord,
13812
13974
  validateComplianceSummary: () => coreComplianceSummary,
@@ -14032,6 +14194,7 @@ import {
14032
14194
  taskUnclaim,
14033
14195
  taskUpdate,
14034
14196
  taskWorkHistory,
14197
+ validateChangelog,
14035
14198
  validateGateVerify,
14036
14199
  validateProtocolArchitectureDecision,
14037
14200
  validateProtocolArtifactPublish,
@@ -14915,8 +15078,8 @@ var init_admin2 = __esm({
14915
15078
  const projectRoot = getProjectRoot2();
14916
15079
  const taskId = params.taskId;
14917
15080
  try {
14918
- const { getTaskAccessor: getTaskAccessor4, getLastHandoff, retrieveWithBudget } = await import("@cleocode/core/internal");
14919
- const accessor = await getTaskAccessor4(projectRoot);
15081
+ const { getTaskAccessor: getTaskAccessor5, getLastHandoff, retrieveWithBudget } = await import("@cleocode/core/internal");
15082
+ const accessor = await getTaskAccessor5(projectRoot);
14920
15083
  const task = await accessor.loadSingleTask(taskId);
14921
15084
  if (!task) {
14922
15085
  return lafsError("E_NOT_FOUND", `Task ${taskId} not found`, "context.pull");
@@ -26728,8 +26891,8 @@ async function loadPlaybookByName(name) {
26728
26891
  return null;
26729
26892
  }
26730
26893
  try {
26731
- const { getProjectRoot: getProjectRoot54 } = await import("@cleocode/core/internal");
26732
- const projectRoot = __playbookRuntimeOverrides.projectRoot ?? getProjectRoot54();
26894
+ const { getProjectRoot: getProjectRoot56 } = await import("@cleocode/core/internal");
26895
+ const projectRoot = __playbookRuntimeOverrides.projectRoot ?? getProjectRoot56();
26733
26896
  const resolved = resolvePlaybook(name, {
26734
26897
  projectRoot,
26735
26898
  globalPlaybooksDir: __playbookRuntimeOverrides.globalPlaybooksDir,
@@ -26773,8 +26936,8 @@ async function acquireDb() {
26773
26936
  async function buildDefaultDispatcher() {
26774
26937
  if (__playbookRuntimeOverrides.dispatcher) return __playbookRuntimeOverrides.dispatcher;
26775
26938
  const { orchestrateSpawnExecute: orchestrateSpawnExecute2 } = await Promise.resolve().then(() => (init_engine(), engine_exports));
26776
- const { getProjectRoot: getProjectRoot54 } = await import("@cleocode/core/internal");
26777
- const projectRoot = getProjectRoot54();
26939
+ const { getProjectRoot: getProjectRoot56 } = await import("@cleocode/core/internal");
26940
+ const projectRoot = getProjectRoot56();
26778
26941
  return {
26779
26942
  async dispatch(input2) {
26780
26943
  try {
@@ -26964,8 +27127,8 @@ var init_playbook2 = __esm({
26964
27127
  projectRoot = __playbookRuntimeOverrides.projectRoot;
26965
27128
  } else {
26966
27129
  try {
26967
- const { getProjectRoot: getProjectRoot54 } = await import("@cleocode/core/internal");
26968
- projectRoot = getProjectRoot54();
27130
+ const { getProjectRoot: getProjectRoot56 } = await import("@cleocode/core/internal");
27131
+ projectRoot = getProjectRoot56();
26969
27132
  } catch {
26970
27133
  projectRoot = void 0;
26971
27134
  }
@@ -27029,14 +27192,14 @@ var init_playbook2 = __esm({
27029
27192
  const dispatcher = await buildDefaultDispatcher();
27030
27193
  let result;
27031
27194
  try {
27032
- const { getProjectRoot: getProjectRoot54 } = await import("@cleocode/core/internal");
27195
+ const { getProjectRoot: getProjectRoot56 } = await import("@cleocode/core/internal");
27033
27196
  const opts = {
27034
27197
  db,
27035
27198
  playbook: parsed.definition,
27036
27199
  playbookHash: parsed.sourceHash,
27037
27200
  initialContext,
27038
27201
  dispatcher,
27039
- projectRoot: getProjectRoot54()
27202
+ projectRoot: getProjectRoot56()
27040
27203
  };
27041
27204
  if (__playbookRuntimeOverrides.approvalSecret !== void 0) {
27042
27205
  opts.approvalSecret = __playbookRuntimeOverrides.approvalSecret;
@@ -27401,16 +27564,16 @@ async function orchestrateRejectOp(params) {
27401
27564
  async function orchestrateClassify(request, context, projectRoot) {
27402
27565
  try {
27403
27566
  const { getCleoCantWorkflowsDir } = await import("@cleocode/core/internal");
27404
- const { readFileSync: readFileSync21, readdirSync: readdirSync3, existsSync: existsSync19 } = await import("node:fs");
27405
- const { join: join37 } = await import("node:path");
27567
+ const { readFileSync: readFileSync21, readdirSync: readdirSync3, existsSync: existsSync20 } = await import("node:fs");
27568
+ const { join: join38 } = await import("node:path");
27406
27569
  const workflowsDir = getCleoCantWorkflowsDir();
27407
27570
  const combined = `${request} ${context ?? ""}`.toLowerCase();
27408
27571
  const matches = [];
27409
- if (existsSync19(workflowsDir)) {
27572
+ if (existsSync20(workflowsDir)) {
27410
27573
  const files = readdirSync3(workflowsDir).filter((f) => f.endsWith(".cant"));
27411
27574
  for (const file of files) {
27412
27575
  try {
27413
- const src = readFileSync21(join37(workflowsDir, file), "utf-8");
27576
+ const src = readFileSync21(join38(workflowsDir, file), "utf-8");
27414
27577
  const teamMatch = /^team\s+(\S+):/m.exec(src);
27415
27578
  if (!teamMatch) continue;
27416
27579
  const teamName = teamMatch[1];
@@ -27425,12 +27588,12 @@ async function orchestrateClassify(request, context, projectRoot) {
27425
27588
  }
27426
27589
  }
27427
27590
  }
27428
- const localCantDir = join37(projectRoot, CLEO_DIR_NAME, WORKFLOWS_SUBDIR);
27429
- if (existsSync19(localCantDir)) {
27591
+ const localCantDir = join38(projectRoot, CLEO_DIR_NAME, WORKFLOWS_SUBDIR);
27592
+ if (existsSync20(localCantDir)) {
27430
27593
  const files = readdirSync3(localCantDir).filter((f) => f.endsWith(".cant"));
27431
27594
  for (const file of files) {
27432
27595
  try {
27433
- const src = readFileSync21(join37(localCantDir, file), "utf-8");
27596
+ const src = readFileSync21(join38(localCantDir, file), "utf-8");
27434
27597
  const teamMatch = /^team\s+(\S+):/m.exec(src);
27435
27598
  if (!teamMatch) continue;
27436
27599
  const teamName = teamMatch[1];
@@ -27572,8 +27735,8 @@ async function orchestrateAnalyzeParallelSafety(taskIds, projectRoot) {
27572
27735
  return !closureA.has(b) && !closureB.has(a);
27573
27736
  };
27574
27737
  var transitiveClose = transitiveClose2, parallelSafe = parallelSafe2;
27575
- const { getTaskAccessor: getTaskAccessor4 } = await import("@cleocode/core/internal");
27576
- const accessor = await getTaskAccessor4(projectRoot);
27738
+ const { getTaskAccessor: getTaskAccessor5 } = await import("@cleocode/core/internal");
27739
+ const accessor = await getTaskAccessor5(projectRoot);
27577
27740
  const result = await accessor.queryTasks({});
27578
27741
  const allTasks = result?.tasks ?? [];
27579
27742
  const depMap = /* @__PURE__ */ new Map();
@@ -27622,11 +27785,11 @@ async function orchestrateAnalyzeParallelSafety(taskIds, projectRoot) {
27622
27785
  };
27623
27786
  }
27624
27787
  }
27625
- async function handleWorktreeComplete(taskId, projectRoot, resolve8) {
27788
+ async function handleWorktreeComplete(taskId, projectRoot, resolve9) {
27626
27789
  try {
27627
27790
  const { completeWorktreeForTask } = await import("@cleocode/core/internal");
27628
27791
  const result = completeWorktreeForTask(taskId, projectRoot, {
27629
- resolve: resolve8 ?? "auto"
27792
+ resolve: resolve9 ?? "auto"
27630
27793
  });
27631
27794
  if (result.outcome === "conflict") {
27632
27795
  return {
@@ -28306,10 +28469,10 @@ var init_orchestrate2 = __esm({
28306
28469
  startTime
28307
28470
  );
28308
28471
  const rawResolve = params.resolve;
28309
- const resolve8 = rawResolve === "manual" ? "manual" : rawResolve === "auto" ? "auto" : void 0;
28472
+ const resolve9 = rawResolve === "manual" ? "manual" : rawResolve === "auto" ? "auto" : void 0;
28310
28473
  const p = {
28311
28474
  taskId: params.taskId,
28312
- ...resolve8 !== void 0 ? { resolve: resolve8 } : {}
28475
+ ...resolve9 !== void 0 ? { resolve: resolve9 } : {}
28313
28476
  };
28314
28477
  return wrapResult(
28315
28478
  await coreOps2["worktree.complete"](p),
@@ -29450,6 +29613,65 @@ var init_release2 = __esm({
29450
29613
  startTime
29451
29614
  );
29452
29615
  }
29616
+ // release.validate-changelog — canonical CHANGELOG.md header validator
29617
+ // (T9937 / Saga T9862). Replaces the brittle `grep -qF "## [VERSION]"`
29618
+ // step in .github/workflows/release.yml. Read-only.
29619
+ //
29620
+ // The core verb returns a plain `ValidateChangelogResult` envelope
29621
+ // (NOT an EngineResult discriminated union) so direct SDK consumers
29622
+ // can branch on `result.valid`. At the dispatch boundary we translate
29623
+ // `valid=false` into `E_CHANGELOG_MISSING_SECTION` so the CLI emits a
29624
+ // non-zero exit code — exactly the behaviour CI workflows depend on
29625
+ // (the legacy `grep -qF "## [VERSION]" || exit 1` had the same
29626
+ // contract).
29627
+ case "validate-changelog": {
29628
+ const version = typeof params?.version === "string" ? params.version : void 0;
29629
+ if (!version)
29630
+ return errorResult(
29631
+ "query",
29632
+ "release",
29633
+ operation,
29634
+ "E_INVALID_INPUT",
29635
+ "version is required",
29636
+ startTime
29637
+ );
29638
+ const typed = {
29639
+ version,
29640
+ projectRoot: getProjectRoot14(),
29641
+ ...typeof params?.changelogPath === "string" ? { changelogPath: params.changelogPath } : {}
29642
+ };
29643
+ const validation = await validateChangelog(typed);
29644
+ if (validation.valid) {
29645
+ return wrapResult(
29646
+ { success: true, data: validation },
29647
+ "query",
29648
+ "release",
29649
+ operation,
29650
+ startTime
29651
+ );
29652
+ }
29653
+ return wrapResult(
29654
+ {
29655
+ success: false,
29656
+ error: {
29657
+ code: "E_CHANGELOG_MISSING_SECTION",
29658
+ message: validation.reason ?? `CHANGELOG.md missing canonical header for v${validation.normalizedVersion}`,
29659
+ details: {
29660
+ version: validation.version,
29661
+ normalizedVersion: validation.normalizedVersion,
29662
+ changelogPath: validation.changelogPath,
29663
+ headerFound: validation.headerFound
29664
+ },
29665
+ fix: `Run \`cleo release plan v${validation.normalizedVersion}\` locally to write the section, then re-push.`,
29666
+ exitCode: 1
29667
+ }
29668
+ },
29669
+ "query",
29670
+ "release",
29671
+ operation,
29672
+ startTime
29673
+ );
29674
+ }
29453
29675
  default:
29454
29676
  return unsupportedOp("query", "release", operation, startTime);
29455
29677
  }
@@ -29617,7 +29839,7 @@ var init_release2 = __esm({
29617
29839
  /** Return declared operations for introspection and registry validation. */
29618
29840
  getSupportedOperations() {
29619
29841
  return {
29620
- query: ["gate", "ivtr-suggest"],
29842
+ query: ["gate", "ivtr-suggest", "validate-changelog"],
29621
29843
  mutate: ["gate", "ivtr-suggest", "reconcile", "plan", "open"]
29622
29844
  };
29623
29845
  }
@@ -30600,7 +30822,7 @@ var init_sticky2 = __esm({
30600
30822
 
30601
30823
  // packages/cleo/src/dispatch/domains/tasks.ts
30602
30824
  import { getLogger as getLogger15, getProjectRoot as getProjectRoot18, TASKS_SUGGESTED_NEXT_BUILDERS } from "@cleocode/core";
30603
- import { createAttachmentStore as createAttachmentStore4 } from "@cleocode/core/internal";
30825
+ import { createAttachmentStore as createAttachmentStore4, getTaskAccessor as getTaskAccessor3 } from "@cleocode/core/internal";
30604
30826
  import {
30605
30827
  sagaAdd as coreSagaAdd,
30606
30828
  sagaCreate as coreSagaCreate,
@@ -30631,6 +30853,20 @@ async function fetchTaskAttachments(projectRoot, taskId) {
30631
30853
  return [];
30632
30854
  }
30633
30855
  }
30856
+ async function fetchTaskAcRows(projectRoot, taskId) {
30857
+ try {
30858
+ const accessor = await getTaskAccessor3(projectRoot);
30859
+ const rows = await accessor.getAcRows(taskId);
30860
+ return rows.map((row) => ({
30861
+ id: row.id,
30862
+ alias: `AC${row.ordinal}`,
30863
+ ordinal: row.ordinal,
30864
+ text: row.text
30865
+ }));
30866
+ } catch {
30867
+ return [];
30868
+ }
30869
+ }
30634
30870
  async function sagaCreate(params) {
30635
30871
  const title = typeof params.title === "string" ? params.title : "";
30636
30872
  const description = typeof params.description === "string" ? params.description : void 0;
@@ -30715,9 +30951,10 @@ var init_tasks2 = __esm({
30715
30951
  if (params.history) {
30716
30952
  return wrapCoreResult(await taskShowWithHistory(projectRoot, params.taskId, true), "show");
30717
30953
  }
30718
- const [coreResult, attachments] = await Promise.all([
30954
+ const [coreResult, attachments, acRows] = await Promise.all([
30719
30955
  taskShow(projectRoot, params.taskId),
30720
- fetchTaskAttachments(projectRoot, params.taskId)
30956
+ fetchTaskAttachments(projectRoot, params.taskId),
30957
+ fetchTaskAcRows(projectRoot, params.taskId)
30721
30958
  ]);
30722
30959
  if (!coreResult.success) {
30723
30960
  return wrapCoreResult(coreResult, "show");
@@ -30725,7 +30962,8 @@ var init_tasks2 = __esm({
30725
30962
  const showResult = {
30726
30963
  task: coreResult.data.task,
30727
30964
  view: coreResult.data.view,
30728
- attachments
30965
+ attachments,
30966
+ ...acRows.length > 0 ? { acRows } : {}
30729
30967
  };
30730
30968
  return { success: true, data: showResult };
30731
30969
  },
@@ -30769,7 +31007,13 @@ var init_tasks2 = __esm({
30769
31007
  // T944/T9072: kind filter
30770
31008
  kind: params.kind,
30771
31009
  // T9905: unified urgency surface
30772
- urgent: params.urgent
31010
+ urgent: params.urgent,
31011
+ // T9904: label filter — `cleo find --label <name>` (closes GH#393).
31012
+ label: params.label,
31013
+ // T10108: parent filter — `cleo find --parent <id>`. Saga-aware via
31014
+ // resolveSagaMemberIds (ADR-073 §1) so saga members surface through
31015
+ // the same routing as `cleo list --parent`.
31016
+ parent: params.parent
30773
31017
  }),
30774
31018
  "find"
30775
31019
  );
@@ -30977,7 +31221,10 @@ var init_tasks2 = __esm({
30977
31221
  const result = await completeTaskStrict(projectRoot, params.taskId, {
30978
31222
  notes: params.notes,
30979
31223
  overrideReason: params.overrideReason,
30980
- acknowledgeRisk: params.acknowledgeRisk
31224
+ acknowledgeRisk: params.acknowledgeRisk,
31225
+ // T10509 — AC-coverage gate waiver path
31226
+ waiveAc: params.waiveAc,
31227
+ waiveReason: params.waiveReason
30981
31228
  });
30982
31229
  setImmediate(async () => {
30983
31230
  try {
@@ -32145,7 +32392,8 @@ import {
32145
32392
  getLogger as getLogger18,
32146
32393
  getProjectRoot as getProjectRoot21,
32147
32394
  listWorktrees,
32148
- pruneOrphanedWorktreesByStatus
32395
+ pruneOrphanedWorktreesByStatus,
32396
+ recoverPartialWorktree
32149
32397
  } from "@cleocode/core/internal";
32150
32398
  function coerceStatusFilter(value) {
32151
32399
  if (value === void 0 || value === null) return void 0;
@@ -32220,7 +32468,7 @@ var init_worktree2 = __esm({
32220
32468
  *
32221
32469
  * Supported operations:
32222
32470
  * - `adopt` — register an externally-created worktree in the SSoT. Params:
32223
- * `{ worktreePath, source?, taskId?, actor? }`. Returns an
32471
+ * `{ worktreePath, source?, taskId?, actor?, recover? }`. Returns an
32224
32472
  * {@link AdoptWorktreeResult} envelope. (T9804)
32225
32473
  * - `destroy` — explicitly destroy a single agent worktree. Params:
32226
32474
  * `{ taskId, force?, deleteBranch?, reason? }`. Returns a
@@ -32256,14 +32504,44 @@ var init_worktree2 = __esm({
32256
32504
  const source = typeof rawSource === "string" && validSources.includes(rawSource) ? rawSource : void 0;
32257
32505
  const rawTaskId = params?.["taskId"];
32258
32506
  const taskId = rawTaskId === null ? null : typeof rawTaskId === "string" && rawTaskId.length > 0 ? rawTaskId : void 0;
32507
+ const projectRoot = getProjectRoot21();
32259
32508
  const opts = {
32260
- projectRoot: getProjectRoot21(),
32509
+ projectRoot,
32261
32510
  worktreePath,
32262
32511
  ...source !== void 0 ? { source } : {},
32263
32512
  ...taskId !== void 0 ? { taskId } : {},
32264
32513
  ...typeof params?.["actor"] === "string" && params["actor"].length > 0 ? { actor: params["actor"] } : {}
32265
32514
  };
32266
32515
  const result = await adoptWorktree(opts);
32516
+ if (result.success && params?.["recover"] === true) {
32517
+ const recovery = recoverPartialWorktree(
32518
+ projectRoot,
32519
+ worktreePath,
32520
+ result.data.taskId ?? taskId ?? "unknown"
32521
+ );
32522
+ const recoveredResult = recovery.success ? {
32523
+ success: true,
32524
+ data: {
32525
+ ...result.data,
32526
+ recovery
32527
+ }
32528
+ } : {
32529
+ success: false,
32530
+ error: {
32531
+ code: "E_WORKTREE_RECOVERY_FAILED",
32532
+ message: recovery.error ?? "Partial worktree recovery failed.",
32533
+ fix: "Inspect the worktree, then rerun `cleo worktree adopt <path> --recover` after resolving the reported recovery error.",
32534
+ details: { adopt: result.data, recovery }
32535
+ }
32536
+ };
32537
+ return wrapResult(
32538
+ recoveredResult,
32539
+ "mutate",
32540
+ "worktree",
32541
+ operation,
32542
+ startTime
32543
+ );
32544
+ }
32267
32545
  return wrapResult(
32268
32546
  result,
32269
32547
  "mutate",
@@ -32945,11 +33223,11 @@ var init_security = __esm({
32945
33223
  });
32946
33224
 
32947
33225
  // packages/cleo/src/dispatch/middleware/sanitizer.ts
32948
- function createSanitizer(getProjectRoot54) {
33226
+ function createSanitizer(getProjectRoot56) {
32949
33227
  return async (req, next) => {
32950
33228
  if (req.params) {
32951
33229
  try {
32952
- const root = getProjectRoot54 ? getProjectRoot54() : void 0;
33230
+ const root = getProjectRoot56 ? getProjectRoot56() : void 0;
32953
33231
  req.params = sanitizeParams(req.params, root, {
32954
33232
  domain: req.domain,
32955
33233
  operation: req.operation
@@ -33500,7 +33778,7 @@ function wrapParseError(rawInput, parseErr, sourceLabel) {
33500
33778
  return new Error(`Invalid JSON in ${sourceLabel}: ${parseErr.message} (got: ${snippet2})`);
33501
33779
  }
33502
33780
  function readStdinJson(stdin2) {
33503
- return new Promise((resolve8, reject) => {
33781
+ return new Promise((resolve9, reject) => {
33504
33782
  const chunks = [];
33505
33783
  stdin2.on("data", (chunk) => {
33506
33784
  chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
@@ -33511,7 +33789,7 @@ function readStdinJson(stdin2) {
33511
33789
  stdin2.on("end", () => {
33512
33790
  const raw = Buffer.concat(chunks).toString("utf8");
33513
33791
  try {
33514
- resolve8(JSON.parse(raw));
33792
+ resolve9(JSON.parse(raw));
33515
33793
  } catch (err) {
33516
33794
  reject(wrapParseError(raw, err, "stdin"));
33517
33795
  }
@@ -34740,12 +35018,12 @@ var init_agent = __esm({
34740
35018
  transportConfig: {},
34741
35019
  isActive: true
34742
35020
  });
34743
- const { existsSync: existsSync19, mkdirSync: mkdirSync7, writeFileSync: writeFileSync7 } = await import("node:fs");
34744
- const { join: join37 } = await import("node:path");
34745
- const cantDir = join37(CLEO_DIR_NAME, AGENTS_SUBDIR);
34746
- const cantPath = join37(cantDir, `${agentId}.cant`);
35021
+ const { existsSync: existsSync20, mkdirSync: mkdirSync7, writeFileSync: writeFileSync7 } = await import("node:fs");
35022
+ const { join: join38 } = await import("node:path");
35023
+ const cantDir = join38(CLEO_DIR_NAME, AGENTS_SUBDIR);
35024
+ const cantPath = join38(cantDir, `${agentId}.cant`);
34747
35025
  let cantScaffolded = false;
34748
- if (!existsSync19(cantPath)) {
35026
+ if (!existsSync20(cantPath)) {
34749
35027
  mkdirSync7(cantDir, { recursive: true });
34750
35028
  const role = classification ?? "specialist";
34751
35029
  const cantContent = `---
@@ -34805,7 +35083,7 @@ agent ${agentId}:
34805
35083
  data: {
34806
35084
  agentId: credential.agentId,
34807
35085
  displayName: credential.displayName,
34808
- cantFile: cantScaffolded ? cantPath : existsSync19(cantPath) ? cantPath : null,
35086
+ cantFile: cantScaffolded ? cantPath : existsSync20(cantPath) ? cantPath : null,
34809
35087
  cantScaffolded
34810
35088
  }
34811
35089
  },
@@ -34924,8 +35202,8 @@ agent ${agentId}:
34924
35202
  try {
34925
35203
  const { AgentRegistryAccessor } = await import("@cleocode/core/agents");
34926
35204
  const { createRuntime } = await import("@cleocode/runtime");
34927
- const { existsSync: existsSync19, readFileSync: readFileSync21 } = await import("node:fs");
34928
- const { join: join37 } = await import("node:path");
35205
+ const { existsSync: existsSync20, readFileSync: readFileSync21 } = await import("node:fs");
35206
+ const { join: join38 } = await import("node:path");
34929
35207
  await openCleoDb("tasks");
34930
35208
  const registry = new AgentRegistryAccessor(getProjectRoot24());
34931
35209
  const credential = await registry.get(args.agentId);
@@ -34945,8 +35223,8 @@ agent ${agentId}:
34945
35223
  }
34946
35224
  let profile = null;
34947
35225
  let cantValidation = null;
34948
- const cantPath = args.cant ?? join37(CLEO_DIR_NAME, AGENTS_SUBDIR, `${args.agentId}.cant`);
34949
- if (existsSync19(cantPath)) {
35226
+ const cantPath = args.cant ?? join38(CLEO_DIR_NAME, AGENTS_SUBDIR, `${args.agentId}.cant`);
35227
+ if (existsSync20(cantPath)) {
34950
35228
  profile = readFileSync21(cantPath, "utf-8");
34951
35229
  try {
34952
35230
  const cantModule = await import("@cleocode/cant");
@@ -35470,8 +35748,8 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
35470
35748
  try {
35471
35749
  const { AgentRegistryAccessor } = await import("@cleocode/core/agents");
35472
35750
  const { createRuntime } = await import("@cleocode/runtime");
35473
- const { existsSync: existsSync19 } = await import("node:fs");
35474
- const { join: join37 } = await import("node:path");
35751
+ const { existsSync: existsSync20 } = await import("node:fs");
35752
+ const { join: join38 } = await import("node:path");
35475
35753
  await openCleoDb("tasks");
35476
35754
  const registry = new AgentRegistryAccessor(getProjectRoot24());
35477
35755
  const credential = await registry.get(args.agentId);
@@ -35488,8 +35766,8 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
35488
35766
  }
35489
35767
  await registry.update(args.agentId, { isActive: true });
35490
35768
  await registry.markUsed(args.agentId);
35491
- const cantPath = join37(CLEO_DIR_NAME, AGENTS_SUBDIR, `${args.agentId}.cant`);
35492
- const hasProfile = existsSync19(cantPath);
35769
+ const cantPath = join38(CLEO_DIR_NAME, AGENTS_SUBDIR, `${args.agentId}.cant`);
35770
+ const hasProfile = existsSync20(cantPath);
35493
35771
  const runtime = await createRuntime(registry, {
35494
35772
  agentId: args.agentId,
35495
35773
  pollIntervalMs: 5e3,
@@ -36285,10 +36563,10 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
36285
36563
  async run({ args }) {
36286
36564
  let tempDir = null;
36287
36565
  try {
36288
- const { existsSync: existsSync19 } = await import("node:fs");
36289
- const { basename, resolve: resolve8 } = await import("node:path");
36290
- const resolvedPath = resolve8(args.path);
36291
- if (!existsSync19(resolvedPath)) {
36566
+ const { existsSync: existsSync20 } = await import("node:fs");
36567
+ const { basename, resolve: resolve9 } = await import("node:path");
36568
+ const resolvedPath = resolve9(args.path);
36569
+ if (!existsSync20(resolvedPath)) {
36292
36570
  cliOutput(
36293
36571
  {
36294
36572
  success: false,
@@ -36413,11 +36691,11 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
36413
36691
  },
36414
36692
  async run({ args }) {
36415
36693
  try {
36416
- const { existsSync: existsSync19, statSync } = await import("node:fs");
36417
- const { resolve: resolve8, basename, dirname: dirname12 } = await import("node:path");
36694
+ const { existsSync: existsSync20, statSync } = await import("node:fs");
36695
+ const { resolve: resolve9, basename, dirname: dirname12 } = await import("node:path");
36418
36696
  const { execFileSync: execFileSync5 } = await import("node:child_process");
36419
- const resolvedDir = resolve8(args.dir);
36420
- if (!existsSync19(resolvedDir) || !statSync(resolvedDir).isDirectory()) {
36697
+ const resolvedDir = resolve9(args.dir);
36698
+ if (!existsSync20(resolvedDir) || !statSync(resolvedDir).isDirectory()) {
36421
36699
  cliOutput(
36422
36700
  {
36423
36701
  success: false,
@@ -36431,9 +36709,9 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
36431
36709
  process.exitCode = 4;
36432
36710
  return;
36433
36711
  }
36434
- const { join: join37 } = await import("node:path");
36435
- const personaPath = join37(resolvedDir, "persona.cant");
36436
- if (!existsSync19(personaPath)) {
36712
+ const { join: join38 } = await import("node:path");
36713
+ const personaPath = join38(resolvedDir, "persona.cant");
36714
+ if (!existsSync20(personaPath)) {
36437
36715
  cliOutput(
36438
36716
  {
36439
36717
  success: false,
@@ -36449,7 +36727,7 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
36449
36727
  }
36450
36728
  const agentName = basename(resolvedDir);
36451
36729
  const archiveName = `${agentName}.cantz`;
36452
- const archivePath = resolve8(archiveName);
36730
+ const archivePath = resolve9(archiveName);
36453
36731
  const parentDir = dirname12(resolvedDir);
36454
36732
  try {
36455
36733
  execFileSync5("zip", ["-r", archivePath, agentName], {
@@ -36480,7 +36758,7 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
36480
36758
  if (entry.isFile()) {
36481
36759
  fileCount++;
36482
36760
  } else if (entry.isDirectory()) {
36483
- countFiles(join37(dirPath, entry.name));
36761
+ countFiles(join38(dirPath, entry.name));
36484
36762
  }
36485
36763
  }
36486
36764
  };
@@ -36728,17 +37006,17 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
36728
37006
  },
36729
37007
  async run({ args }) {
36730
37008
  try {
36731
- const { existsSync: existsSync19, readFileSync: readFileSync21, mkdirSync: mkdirSync7 } = await import("node:fs");
36732
- const { resolve: resolve8, join: join37 } = await import("node:path");
36733
- const specPath = resolve8(args.spec);
36734
- if (!existsSync19(specPath)) {
37009
+ const { existsSync: existsSync20, readFileSync: readFileSync21, mkdirSync: mkdirSync7 } = await import("node:fs");
37010
+ const { resolve: resolve9, join: join38 } = await import("node:path");
37011
+ const specPath = resolve9(args.spec);
37012
+ if (!existsSync20(specPath)) {
36735
37013
  cliError(`spec file not found: ${specPath}`, 4, { name: "E_NOT_FOUND" });
36736
37014
  process.exitCode = 4;
36737
37015
  return;
36738
37016
  }
36739
37017
  const specContent = readFileSync21(specPath, "utf-8");
36740
37018
  const projectRoot = getProjectRoot24();
36741
- const outputDir = args["output-dir"] ? resolve8(args["output-dir"]) : join37(projectRoot, ".cleo", "cant", "agents");
37019
+ const outputDir = args["output-dir"] ? resolve9(args["output-dir"]) : join38(projectRoot, ".cleo", "cant", "agents");
36742
37020
  mkdirSync7(outputDir, { recursive: true });
36743
37021
  if (args["dry-run"]) {
36744
37022
  cliOutput(
@@ -37489,8 +37767,8 @@ function detectAuthType(provider, token) {
37489
37767
  async function promptYesNo(question) {
37490
37768
  const rl = createInterface({ input: process.stdin, output: process.stderr });
37491
37769
  try {
37492
- const answer = await new Promise((resolve8) => {
37493
- rl.question(question, (a) => resolve8(a));
37770
+ const answer = await new Promise((resolve9) => {
37771
+ rl.question(question, (a) => resolve9(a));
37494
37772
  });
37495
37773
  const clean = answer.trim().toLowerCase();
37496
37774
  return clean === "y" || clean === "yes";
@@ -38426,12 +38704,12 @@ async function promptPassphrase() {
38426
38704
  "Cannot prompt for passphrase: stdin is not a TTY. Set the CLEO_BACKUP_PASSPHRASE environment variable for non-interactive use."
38427
38705
  );
38428
38706
  }
38429
- return new Promise((resolve8) => {
38707
+ return new Promise((resolve9) => {
38430
38708
  process.stdout.write("Passphrase: ");
38431
38709
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
38432
38710
  rl.question("", (answer) => {
38433
38711
  rl.close();
38434
- resolve8(answer.trim());
38712
+ resolve9(answer.trim());
38435
38713
  });
38436
38714
  });
38437
38715
  }
@@ -38567,9 +38845,9 @@ var init_backup = __esm({
38567
38845
  async run({ args }) {
38568
38846
  const scope = args.scope;
38569
38847
  const { packBundle } = await import("@cleocode/core/store/backup-pack.js");
38570
- const { getProjectRoot: getProjectRoot54 } = await import("@cleocode/core");
38848
+ const { getProjectRoot: getProjectRoot56 } = await import("@cleocode/core");
38571
38849
  const includesProject = scope === "project" || scope === "all";
38572
- const projectRoot = includesProject ? getProjectRoot54() : void 0;
38850
+ const projectRoot = includesProject ? getProjectRoot56() : void 0;
38573
38851
  let passphrase;
38574
38852
  if (args.encrypt === true) {
38575
38853
  passphrase = process.env["CLEO_BACKUP_PASSPHRASE"];
@@ -38645,12 +38923,12 @@ var init_backup = __esm({
38645
38923
  },
38646
38924
  async run({ args }) {
38647
38925
  const bundlePath = args.bundle;
38648
- const { getProjectRoot: getProjectRoot54, getCleoHome: getCleoHome6, getCleoVersion } = await import("@cleocode/core");
38926
+ const { getProjectRoot: getProjectRoot56, getCleoHome: getCleoHome6, getCleoVersion } = await import("@cleocode/core");
38649
38927
  const { BundleError, cleanupStaging, unpackBundle } = await import("@cleocode/core/store/backup-unpack.js");
38650
38928
  const { regenerateConfigJson, regenerateProjectContextJson, regenerateProjectInfoJson } = await import("@cleocode/core/store/regenerators.js");
38651
38929
  const { regenerateAndCompare } = await import("@cleocode/core/store/restore-json-merge.js");
38652
38930
  const { buildConflictReport, writeConflictReport } = await import("@cleocode/core/store/restore-conflict-report.js");
38653
- const projectRoot = getProjectRoot54();
38931
+ const projectRoot = getProjectRoot56();
38654
38932
  if (args.force !== true) {
38655
38933
  const existing = checkForExistingData(projectRoot, getCleoHome6());
38656
38934
  if (existing.length > 0) {
@@ -39541,11 +39819,11 @@ var init_caamp = __esm({
39541
39819
  }
39542
39820
  if (args["dry-run"]) {
39543
39821
  const { parseCaampBlocks } = await import("@cleocode/caamp");
39544
- const { existsSync: existsSync19 } = await import("node:fs");
39822
+ const { existsSync: existsSync20 } = await import("node:fs");
39545
39823
  const { readFile: readFile8 } = await import("node:fs/promises");
39546
39824
  const dryResults = [];
39547
39825
  for (const filePath of filePaths) {
39548
- if (!existsSync19(filePath)) {
39826
+ if (!existsSync20(filePath)) {
39549
39827
  dryResults.push({ filePath, exists: false, blockCount: 0, wouldRemove: 0 });
39550
39828
  continue;
39551
39829
  }
@@ -40600,11 +40878,11 @@ var init_check2 = __esm({
40600
40878
  },
40601
40879
  async run({ args }) {
40602
40880
  const { spawnSync } = await import("node:child_process");
40603
- const { existsSync: existsSync19 } = await import("node:fs");
40604
- const { join: join37, resolve: resolve8 } = await import("node:path");
40881
+ const { existsSync: existsSync20 } = await import("node:fs");
40882
+ const { join: join38, resolve: resolve9 } = await import("node:path");
40605
40883
  const strict = Boolean(args.strict);
40606
40884
  const jsonOnly = Boolean(args.json);
40607
- const repoRoot = resolve8(process.cwd());
40885
+ const repoRoot = resolve9(process.cwd());
40608
40886
  const gates = [
40609
40887
  {
40610
40888
  id: "gate-1",
@@ -40641,8 +40919,8 @@ var init_check2 = __esm({
40641
40919
  const results = [];
40642
40920
  let anyFailed = false;
40643
40921
  for (const gate of gates) {
40644
- const scriptPath = join37(repoRoot, gate.script);
40645
- if (!existsSync19(scriptPath)) {
40922
+ const scriptPath = join38(repoRoot, gate.script);
40923
+ if (!existsSync20(scriptPath)) {
40646
40924
  results.push({
40647
40925
  id: gate.id,
40648
40926
  task: gate.task,
@@ -40957,9 +41235,9 @@ var init_code = __esm({
40957
41235
  async run({ args }) {
40958
41236
  await requireTreeSitter();
40959
41237
  const { smartOutline } = await import("@cleocode/core/internal");
40960
- const { join: join37 } = await import("node:path");
41238
+ const { join: join38 } = await import("node:path");
40961
41239
  const root = process.cwd();
40962
- const absPath = args.file.startsWith("/") ? args.file : join37(root, args.file);
41240
+ const absPath = args.file.startsWith("/") ? args.file : join38(root, args.file);
40963
41241
  const result = smartOutline(absPath, root);
40964
41242
  if (result.errors.length > 0 && result.symbols.length === 0) {
40965
41243
  cliError(result.errors.join(", "), 1, { name: "E_OUTLINE_FAILED" });
@@ -41050,9 +41328,9 @@ var init_code = __esm({
41050
41328
  async run({ args }) {
41051
41329
  await requireTreeSitter();
41052
41330
  const { smartUnfold } = await import("@cleocode/core/internal");
41053
- const { join: join37 } = await import("node:path");
41331
+ const { join: join38 } = await import("node:path");
41054
41332
  const root = process.cwd();
41055
- const absPath = args.file.startsWith("/") ? args.file : join37(root, args.file);
41333
+ const absPath = args.file.startsWith("/") ? args.file : join38(root, args.file);
41056
41334
  const result = smartUnfold(absPath, args.symbol, root);
41057
41335
  if (!result.found) {
41058
41336
  const errs = result.errors.length > 0 ? `: ${result.errors.join(", ")}` : "";
@@ -41115,6 +41393,15 @@ var init_complete = __esm({
41115
41393
  "override-reason": {
41116
41394
  type: "string",
41117
41395
  description: "Reason for bypassing E_EPIC_HAS_PENDING_CHILDREN guard (audited to .cleo/audit/premature-close.jsonl)"
41396
+ },
41397
+ // T10509 — AC-coverage gate (load-bearing IVTR closure)
41398
+ "waive-ac": {
41399
+ type: "string",
41400
+ description: "Comma-separated AC tokens (UUIDs or AC<n> aliases) to waive from the AC-coverage gate. Requires --waive-reason. Audited to .cleo/audit/ac-waiver.jsonl."
41401
+ },
41402
+ "waive-reason": {
41403
+ type: "string",
41404
+ description: "Mandatory justification text for --waive-ac. Captured verbatim in the audit row."
41118
41405
  }
41119
41406
  },
41120
41407
  async run({ args }) {
@@ -41124,7 +41411,10 @@ var init_complete = __esm({
41124
41411
  changeset: args.changeset,
41125
41412
  verificationNote: args["verification-note"],
41126
41413
  acknowledgeRisk: args["acknowledge-risk"],
41127
- overrideReason: args["override-reason"]
41414
+ overrideReason: args["override-reason"],
41415
+ // T10509 — AC-coverage gate waiver path
41416
+ waiveAc: args["waive-ac"],
41417
+ waiveReason: args["waive-reason"]
41128
41418
  });
41129
41419
  if (!response.success) {
41130
41420
  handleRawError(response, { command: "complete", operation: "tasks.complete" });
@@ -47221,6 +47511,269 @@ var init_doctor_projects = __esm({
47221
47511
  }
47222
47512
  });
47223
47513
 
47514
+ // packages/cleo/src/cli/commands/doctor-release-readiness.ts
47515
+ var doctor_release_readiness_exports = {};
47516
+ __export(doctor_release_readiness_exports, {
47517
+ doctorReleaseReadinessCommand: () => doctorReleaseReadinessCommand
47518
+ });
47519
+ import { existsSync as existsSync13 } from "node:fs";
47520
+ import { join as join22, resolve as resolve6 } from "node:path";
47521
+ async function runCheck(name, cmd, args, cwd) {
47522
+ const { spawnSync } = await import("node:child_process");
47523
+ const start = Date.now();
47524
+ const result = spawnSync(cmd, args, {
47525
+ encoding: "utf8",
47526
+ stdio: ["ignore", "pipe", "pipe"],
47527
+ cwd
47528
+ });
47529
+ const durationMs = Date.now() - start;
47530
+ const passed = result.status === 0;
47531
+ return {
47532
+ name,
47533
+ status: passed ? "pass" : "fail",
47534
+ exitCode: result.status,
47535
+ durationMs,
47536
+ stdout: (result.stdout ?? "").trim(),
47537
+ stderr: (result.stderr ?? "").trim()
47538
+ };
47539
+ }
47540
+ var doctorReleaseReadinessCommand;
47541
+ var init_doctor_release_readiness = __esm({
47542
+ "packages/cleo/src/cli/commands/doctor-release-readiness.ts"() {
47543
+ "use strict";
47544
+ init_define_cli_command();
47545
+ init_renderers();
47546
+ doctorReleaseReadinessCommand = defineCommand({
47547
+ meta: {
47548
+ name: "release-readiness",
47549
+ description: "Pre-flight release readiness check \u2014 lint matrix + changelog + changeset + npm OIDC + tag-trigger sanity (T10458)"
47550
+ },
47551
+ args: {
47552
+ json: { type: "boolean", description: "Output as JSON" },
47553
+ human: { type: "boolean", description: "Force human-readable output" },
47554
+ quiet: { type: "boolean", description: "Suppress non-essential output" }
47555
+ },
47556
+ async run({ args }) {
47557
+ const isHuman = args.human === true || !!process.stdout.isTTY && args.json !== true;
47558
+ const repoRoot = resolve6(process.cwd());
47559
+ const startTotal = Date.now();
47560
+ const checks = [];
47561
+ const biomePath = join22(repoRoot, "node_modules", ".bin", "biome");
47562
+ const biomeAvailable = existsSync13(biomePath);
47563
+ if (biomeAvailable) {
47564
+ checks.push(await runCheck("biome-lint", biomePath, ["ci", "."], repoRoot));
47565
+ } else {
47566
+ checks.push({
47567
+ name: "biome-lint",
47568
+ status: "skip",
47569
+ exitCode: null,
47570
+ durationMs: 0,
47571
+ stdout: "",
47572
+ stderr: "biome not found in node_modules/.bin \u2014 skipping"
47573
+ });
47574
+ }
47575
+ const changesetLintScript = join22(repoRoot, "scripts", "lint-changesets.mjs");
47576
+ if (existsSync13(changesetLintScript)) {
47577
+ checks.push(await runCheck("changeset-lint", "node", [changesetLintScript], repoRoot));
47578
+ } else {
47579
+ checks.push({
47580
+ name: "changeset-lint",
47581
+ status: "skip",
47582
+ exitCode: null,
47583
+ durationMs: 0,
47584
+ stdout: "",
47585
+ stderr: "scripts/lint-changesets.mjs not found \u2014 skipping"
47586
+ });
47587
+ }
47588
+ const changelogPath = join22(repoRoot, "CHANGELOG.md");
47589
+ const changelogExists = existsSync13(changelogPath);
47590
+ const changelogCheck = {
47591
+ name: "changelog-exists",
47592
+ status: changelogExists ? "pass" : "fail",
47593
+ exitCode: changelogExists ? 0 : 1,
47594
+ durationMs: 0,
47595
+ stdout: changelogExists ? `Found ${changelogPath}` : "",
47596
+ stderr: changelogExists ? "" : `CHANGELOG.md not found at ${changelogPath}`
47597
+ };
47598
+ checks.push(changelogCheck);
47599
+ const packageJsonPath = join22(repoRoot, "package.json");
47600
+ let oidcCheck;
47601
+ if (existsSync13(packageJsonPath)) {
47602
+ try {
47603
+ const pkg = JSON.parse(
47604
+ await import("node:fs").then((m) => m.readFileSync(packageJsonPath, "utf8"))
47605
+ );
47606
+ if (pkg.private === true) {
47607
+ oidcCheck = {
47608
+ name: "npm-oidc-sanity",
47609
+ status: "pass",
47610
+ exitCode: 0,
47611
+ durationMs: 0,
47612
+ stdout: "root package.json is private \u2014 skipping (per-package check applies at publish time)",
47613
+ stderr: ""
47614
+ };
47615
+ } else {
47616
+ const hasPublishConfig = typeof pkg.publishConfig === "object" && pkg.publishConfig !== null;
47617
+ const accessPublic = hasPublishConfig && pkg.publishConfig.access === "public";
47618
+ oidcCheck = {
47619
+ name: "npm-oidc-sanity",
47620
+ status: accessPublic ? "pass" : "fail",
47621
+ exitCode: accessPublic ? 0 : 1,
47622
+ durationMs: 0,
47623
+ stdout: accessPublic ? "package.json has publishConfig.access=public" : "",
47624
+ stderr: accessPublic ? "" : "package.json missing publishConfig.access=public \u2014 required for npm OIDC Trusted Publishing"
47625
+ };
47626
+ }
47627
+ } catch {
47628
+ oidcCheck = {
47629
+ name: "npm-oidc-sanity",
47630
+ status: "fail",
47631
+ exitCode: 1,
47632
+ durationMs: 0,
47633
+ stdout: "",
47634
+ stderr: "Failed to parse package.json"
47635
+ };
47636
+ }
47637
+ } else {
47638
+ oidcCheck = {
47639
+ name: "npm-oidc-sanity",
47640
+ status: "fail",
47641
+ exitCode: 1,
47642
+ durationMs: 0,
47643
+ stdout: "",
47644
+ stderr: "package.json not found"
47645
+ };
47646
+ }
47647
+ checks.push(oidcCheck);
47648
+ const tagWorkflowPath = join22(repoRoot, ".github", "workflows", "auto-tag-on-release-merge.yml");
47649
+ const tagWorkflowExists = existsSync13(tagWorkflowPath);
47650
+ let tagTriggerCheck;
47651
+ if (tagWorkflowExists) {
47652
+ try {
47653
+ const content = await import("node:fs").then(
47654
+ (m) => m.readFileSync(tagWorkflowPath, "utf8")
47655
+ );
47656
+ const hasName = content.includes("name:");
47657
+ const hasOnTrigger = content.includes("on:") || content.includes("pull_request:");
47658
+ const valid = hasName && hasOnTrigger;
47659
+ tagTriggerCheck = {
47660
+ name: "tag-trigger-sanity",
47661
+ status: valid ? "pass" : "fail",
47662
+ exitCode: valid ? 0 : 1,
47663
+ durationMs: 0,
47664
+ stdout: valid ? `Valid workflow at ${tagWorkflowPath}` : "",
47665
+ stderr: valid ? "" : "auto-tag-on-release-merge.yml appears malformed"
47666
+ };
47667
+ } catch {
47668
+ tagTriggerCheck = {
47669
+ name: "tag-trigger-sanity",
47670
+ status: "fail",
47671
+ exitCode: 1,
47672
+ durationMs: 0,
47673
+ stdout: "",
47674
+ stderr: "Failed to read auto-tag-on-release-merge.yml"
47675
+ };
47676
+ }
47677
+ } else {
47678
+ tagTriggerCheck = {
47679
+ name: "tag-trigger-sanity",
47680
+ status: "fail",
47681
+ exitCode: 1,
47682
+ durationMs: 0,
47683
+ stdout: "",
47684
+ stderr: `.github/workflows/auto-tag-on-release-merge.yml not found`
47685
+ };
47686
+ }
47687
+ checks.push(tagTriggerCheck);
47688
+ const tsconfigPath = join22(repoRoot, "tsconfig.json");
47689
+ if (existsSync13(tsconfigPath)) {
47690
+ const tscPath = join22(repoRoot, "node_modules", ".bin", "tsc");
47691
+ if (existsSync13(tscPath)) {
47692
+ checks.push(await runCheck("typecheck", tscPath, ["--noEmit"], repoRoot));
47693
+ } else {
47694
+ checks.push({
47695
+ name: "typecheck",
47696
+ status: "skip",
47697
+ exitCode: null,
47698
+ durationMs: 0,
47699
+ stdout: "",
47700
+ stderr: "tsc not found in node_modules/.bin \u2014 skipping"
47701
+ });
47702
+ }
47703
+ } else {
47704
+ checks.push({
47705
+ name: "typecheck",
47706
+ status: "skip",
47707
+ exitCode: null,
47708
+ durationMs: 0,
47709
+ stdout: "",
47710
+ stderr: "tsconfig.json not found \u2014 skipping"
47711
+ });
47712
+ }
47713
+ const fastLintScripts = [
47714
+ { name: "contracts-dep-lint", script: "scripts/lint-contracts-dep.mjs" },
47715
+ { name: "format-error-lint", script: "scripts/lint-format-error-misuse.mjs" },
47716
+ { name: "json-stream-lint", script: "scripts/lint-json-stream-hygiene.mjs" }
47717
+ ];
47718
+ for (const lint of fastLintScripts) {
47719
+ const scriptPath = join22(repoRoot, lint.script);
47720
+ if (existsSync13(scriptPath)) {
47721
+ checks.push(await runCheck(lint.name, "node", [scriptPath], repoRoot));
47722
+ } else {
47723
+ checks.push({
47724
+ name: lint.name,
47725
+ status: "skip",
47726
+ exitCode: null,
47727
+ durationMs: 0,
47728
+ stdout: "",
47729
+ stderr: `${lint.script} not found \u2014 skipping`
47730
+ });
47731
+ }
47732
+ }
47733
+ const passCount = checks.filter((c) => c.status === "pass").length;
47734
+ const failCount = checks.filter((c) => c.status === "fail").length;
47735
+ const skipCount = checks.filter((c) => c.status === "skip").length;
47736
+ const totalDurationMs = Date.now() - startTotal;
47737
+ const ready = failCount === 0;
47738
+ const result = {
47739
+ ready,
47740
+ checks,
47741
+ summary: {
47742
+ pass: passCount,
47743
+ fail: failCount,
47744
+ skip: skipCount,
47745
+ total: checks.length,
47746
+ durationMs: totalDurationMs
47747
+ }
47748
+ };
47749
+ if (isHuman && args.json !== true) {
47750
+ humanLine("\nRelease Readiness Check (T10458)\n");
47751
+ humanLine(`${"\u2500".repeat(60)}`);
47752
+ for (const c of checks) {
47753
+ const icon = c.status === "pass" ? "PASS" : c.status === "fail" ? "FAIL" : "SKIP";
47754
+ humanLine(` [${icon}] ${c.name} (${c.durationMs}ms)`);
47755
+ if (c.status === "fail" && c.stderr) {
47756
+ const lines = c.stderr.split("\n").slice(0, 3);
47757
+ for (const line of lines) {
47758
+ humanLine(` ${line}`);
47759
+ }
47760
+ }
47761
+ }
47762
+ humanLine(`${"\u2500".repeat(60)}`);
47763
+ humanLine(` Result: ${passCount} passed, ${failCount} failed, ${skipCount} skipped`);
47764
+ humanLine(` Total time: ${totalDurationMs}ms`);
47765
+ humanLine(` Ready: ${ready ? "YES" : "NO"}
47766
+ `);
47767
+ }
47768
+ cliOutput(result, { command: "doctor", operation: "doctor.release-readiness" });
47769
+ if (!ready) {
47770
+ process.exitCode = 1;
47771
+ }
47772
+ }
47773
+ });
47774
+ }
47775
+ });
47776
+
47224
47777
  // packages/cleo/src/cli/progress.ts
47225
47778
  import { stderr } from "node:process";
47226
47779
  function createSelfUpdateProgress(enabled) {
@@ -47353,8 +47906,8 @@ __export(migrate_agents_v2_exports, {
47353
47906
  walkAgentsDir: () => walkAgentsDir
47354
47907
  });
47355
47908
  import { createHash as createHash2 } from "node:crypto";
47356
- import { appendFileSync as appendFileSync2, existsSync as existsSync13, mkdirSync as mkdirSync3, readdirSync as readdirSync2, readFileSync as readFileSync13 } from "node:fs";
47357
- import { join as join22 } from "node:path";
47909
+ import { appendFileSync as appendFileSync2, existsSync as existsSync14, mkdirSync as mkdirSync3, readdirSync as readdirSync2, readFileSync as readFileSync13 } from "node:fs";
47910
+ import { join as join23 } from "node:path";
47358
47911
  import { getProjectRoot as getProjectRoot41, installAgentFromCant } from "@cleocode/core/internal";
47359
47912
  import { openCleoDb as openCleoDb2 } from "@cleocode/core/store/open-cleo-db";
47360
47913
  function sha256Hex(bytes) {
@@ -47374,15 +47927,15 @@ function extractAgentName(source) {
47374
47927
  return headerMatch[1] ?? null;
47375
47928
  }
47376
47929
  function appendAuditLog(projectRoot, entry) {
47377
- const auditPath = join22(projectRoot, AUDIT_LOG_RELATIVE);
47378
- const auditDir = join22(auditPath, "..");
47379
- if (!existsSync13(auditDir)) {
47930
+ const auditPath = join23(projectRoot, AUDIT_LOG_RELATIVE);
47931
+ const auditDir = join23(auditPath, "..");
47932
+ if (!existsSync14(auditDir)) {
47380
47933
  mkdirSync3(auditDir, { recursive: true });
47381
47934
  }
47382
47935
  appendFileSync2(auditPath, JSON.stringify(entry) + "\n", "utf8");
47383
47936
  }
47384
47937
  function walkAgentsDir(db, scanDir, projectRoot, summary, verbose) {
47385
- if (!existsSync13(scanDir)) return;
47938
+ if (!existsSync14(scanDir)) return;
47386
47939
  let files;
47387
47940
  try {
47388
47941
  files = readdirSync2(scanDir).filter((f) => f.endsWith(".cant"));
@@ -47393,7 +47946,7 @@ function walkAgentsDir(db, scanDir, projectRoot, summary, verbose) {
47393
47946
  return;
47394
47947
  }
47395
47948
  for (const filename of files) {
47396
- const cantPath = join22(scanDir, filename);
47949
+ const cantPath = join23(scanDir, filename);
47397
47950
  const relPath = cantPath.replace(`${projectRoot}/`, "");
47398
47951
  let sourceBytes;
47399
47952
  let sourceText;
@@ -47490,9 +48043,9 @@ async function runMigrateAgentsV2(projectRoot, verbose = true) {
47490
48043
  const { db: _sdDb } = await openCleoDb2("signaldock");
47491
48044
  const db = _sdDb;
47492
48045
  try {
47493
- const canonicalDir = join22(projectRoot, ".cleo", "cant", "agents");
48046
+ const canonicalDir = join23(projectRoot, ".cleo", "cant", "agents");
47494
48047
  walkAgentsDir(db, canonicalDir, projectRoot, summary, verbose);
47495
- const legacyDir = join22(projectRoot, ".cleo", "agents");
48048
+ const legacyDir = join23(projectRoot, ".cleo", "agents");
47496
48049
  walkAgentsDir(db, legacyDir, projectRoot, summary, verbose);
47497
48050
  } finally {
47498
48051
  db.close();
@@ -47500,8 +48053,8 @@ async function runMigrateAgentsV2(projectRoot, verbose = true) {
47500
48053
  return summary;
47501
48054
  }
47502
48055
  function readMigrationConflicts(projectRoot) {
47503
- const auditPath = join22(projectRoot, AUDIT_LOG_RELATIVE);
47504
- if (!existsSync13(auditPath)) return [];
48056
+ const auditPath = join23(projectRoot, AUDIT_LOG_RELATIVE);
48057
+ if (!existsSync14(auditPath)) return [];
47505
48058
  let raw;
47506
48059
  try {
47507
48060
  raw = readFileSync13(auditPath, "utf8");
@@ -47585,7 +48138,7 @@ __export(doctor_exports, {
47585
48138
  doctorCommand: () => doctorCommand2
47586
48139
  });
47587
48140
  import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "node:fs";
47588
- import { join as join23 } from "node:path";
48141
+ import { join as join24 } from "node:path";
47589
48142
  import { getProjectRoot as getProjectRoot42, pushWarning as pushWarning4 } from "@cleocode/core";
47590
48143
  import { renderInvariantAuditLines } from "@cleocode/core/doctor/invariant-audit-render.js";
47591
48144
  import {
@@ -47625,8 +48178,8 @@ async function scanTestFixturesInProd(projectRoot) {
47625
48178
  }
47626
48179
  async function quarantineTestFixtures(projectRoot, matches) {
47627
48180
  if (matches.length === 0) return 0;
47628
- const cleoDir = join23(projectRoot, ".cleo");
47629
- const quarantineDir = join23(
48181
+ const cleoDir = join24(projectRoot, ".cleo");
48182
+ const quarantineDir = join24(
47630
48183
  cleoDir,
47631
48184
  "quarantine",
47632
48185
  `fixture-scan-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`
@@ -47634,7 +48187,7 @@ async function quarantineTestFixtures(projectRoot, matches) {
47634
48187
  mkdirSync4(quarantineDir, { recursive: true });
47635
48188
  const manifest = matches.map((m) => ({ ...m, quarantinedAt: (/* @__PURE__ */ new Date()).toISOString() }));
47636
48189
  writeFileSync4(
47637
- join23(quarantineDir, "manifest.jsonl"),
48190
+ join24(quarantineDir, "manifest.jsonl"),
47638
48191
  manifest.map((m) => JSON.stringify(m)).join("\n") + "\n"
47639
48192
  );
47640
48193
  const { getNativeDb } = await import("@cleocode/core/store/sqlite.js");
@@ -47705,6 +48258,7 @@ var init_doctor = __esm({
47705
48258
  init_doctor_db_substrate();
47706
48259
  init_doctor_legacy_backups();
47707
48260
  init_doctor_projects();
48261
+ init_doctor_release_readiness();
47708
48262
  init_migrate_agents_v2();
47709
48263
  FIXTURE_ID_PATTERNS = [/^E\d+$/, /^T\d+EP$/];
47710
48264
  FIXTURE_TITLE_KEYWORDS = [
@@ -47719,7 +48273,9 @@ var init_doctor = __esm({
47719
48273
  // T10307 / Saga T10281 / Epic T10282 — DB-substrate walker
47720
48274
  "db-substrate": doctorDbSubstrateCommand,
47721
48275
  // T10309 / Saga T10281 / Epic T10282 — Legacy-backup walker
47722
- "legacy-backups": doctorLegacyBackupsCommand
48276
+ "legacy-backups": doctorLegacyBackupsCommand,
48277
+ // T10458 / Saga T10431 / Epic T10436 — Release-readiness preflight
48278
+ "release-readiness": doctorReleaseReadinessCommand
47723
48279
  },
47724
48280
  args: {
47725
48281
  detailed: {
@@ -48208,8 +48764,8 @@ var init_doctor = __esm({
48208
48764
  );
48209
48765
  return;
48210
48766
  }
48211
- const archiveDir = join23(projectRoot, ".cleo", "backups");
48212
- const auditLogPath = join23(projectRoot, ".cleo", "audit", "worktree-prune.jsonl");
48767
+ const archiveDir = join24(projectRoot, ".cleo", "backups");
48768
+ const auditLogPath = join24(projectRoot, ".cleo", "audit", "worktree-prune.jsonl");
48213
48769
  const result = await pruneWorktreeOrphans(orphans, {
48214
48770
  archiveDir,
48215
48771
  auditLogPath,
@@ -48373,7 +48929,7 @@ __export(event_exports, {
48373
48929
  orchestratorCommand: () => orchestratorCommand
48374
48930
  });
48375
48931
  import { readdir as readdir2 } from "node:fs/promises";
48376
- import { join as join24 } from "node:path";
48932
+ import { join as join25 } from "node:path";
48377
48933
  import { cwd as processCwd } from "node:process";
48378
48934
  import { appendEvent } from "@cleocode/core/events/event-bus.js";
48379
48935
  function resolveProjectRoot3(arg) {
@@ -48496,7 +49052,7 @@ var init_event = __esm({
48496
49052
  const agentIdFilter = args.agent;
48497
49053
  const showAll = args.all === true;
48498
49054
  const lines = parseInt(args.lines ?? "20", 10);
48499
- const eventsDir = join24(projectRoot, ".cleo", "agent-events");
49055
+ const eventsDir = join25(projectRoot, ".cleo", "agent-events");
48500
49056
  try {
48501
49057
  let files = [];
48502
49058
  try {
@@ -48534,7 +49090,7 @@ var init_event = __esm({
48534
49090
  for (const file of filesToTail) {
48535
49091
  const agentId = file.replace(".jsonl", "");
48536
49092
  const { readFileSync: readFileSync21 } = await import("node:fs");
48537
- const content = readFileSync21(join24(eventsDir, file), "utf-8");
49093
+ const content = readFileSync21(join25(eventsDir, file), "utf-8");
48538
49094
  const eventLines = content.trim().split("\n").filter(Boolean);
48539
49095
  const tail = eventLines.slice(-lines);
48540
49096
  if (jsonMode) {
@@ -48604,7 +49160,7 @@ var init_event = __esm({
48604
49160
  const epicFilter = args.epic;
48605
49161
  const follow = args.follow === true;
48606
49162
  const lines = parseInt(args.lines ?? "50", 10);
48607
- const eventsDir = join24(projectRoot, ".cleo", "agent-events");
49163
+ const eventsDir = join25(projectRoot, ".cleo", "agent-events");
48608
49164
  let files = [];
48609
49165
  try {
48610
49166
  const entries = await readdir2(eventsDir);
@@ -48630,7 +49186,7 @@ var init_event = __esm({
48630
49186
  const agentId = file.replace(".jsonl", "");
48631
49187
  try {
48632
49188
  const { readFileSync: readFileSync21 } = await import("node:fs");
48633
- const content = readFileSync21(join24(eventsDir, file), "utf-8");
49189
+ const content = readFileSync21(join25(eventsDir, file), "utf-8");
48634
49190
  const eventLines = content.trim().split("\n").filter(Boolean);
48635
49191
  const tail = eventLines.slice(-lines);
48636
49192
  if (jsonMode) {
@@ -49109,6 +49665,33 @@ var init_find = __esm({
49109
49665
  type: "boolean",
49110
49666
  description: "Surface urgent work across both axes: priority IN (critical,high) OR severity IN (P0,P1) (T9905)",
49111
49667
  alias: "u"
49668
+ },
49669
+ /**
49670
+ * Filter by label — `cleo find --label <name>` returns every task
49671
+ * whose `labels[]` includes the given value. Closes GH#393 and gives
49672
+ * `find` parity with the positional `cleo labels <name>` surface.
49673
+ * @task T9904
49674
+ */
49675
+ label: {
49676
+ type: "string",
49677
+ description: "Filter by label \u2014 return tasks whose labels[] includes this value (T9904)"
49678
+ },
49679
+ /**
49680
+ * Filter by parent task ID — `cleo find --parent <id>` returns only
49681
+ * tasks whose `parentId` matches. Mirrors the `--parent` axis on
49682
+ * `cleo list`. When the parent target is a Saga (Epic with
49683
+ * `label='saga'`), routing goes through `task_relations.type='groups'`
49684
+ * member IDs (ADR-073 §1) — same path as `cleo list --parent`.
49685
+ *
49686
+ * Closes T10108 — pre-fix the flag was missing entirely AND empty-string
49687
+ * queries bypassed every filter via `fuzzyScore('', '<title>')===80`.
49688
+ *
49689
+ * @task T10108
49690
+ * @saga T9862
49691
+ */
49692
+ parent: {
49693
+ type: "string",
49694
+ description: "Filter by parent task ID \u2014 Saga-aware via task_relations groups (ADR-073 \xA71) (T10108)"
49112
49695
  }
49113
49696
  },
49114
49697
  async run({ args }) {
@@ -49127,6 +49710,8 @@ var init_find = __esm({
49127
49710
  if (args.verbose !== void 0) params["verbose"] = args.verbose;
49128
49711
  if (args.kind !== void 0) params["kind"] = args.kind;
49129
49712
  if (args.urgent !== void 0) params["urgent"] = args.urgent;
49713
+ if (args.label !== void 0) params["label"] = args.label;
49714
+ if (args.parent !== void 0) params["parent"] = args.parent;
49130
49715
  const response = await dispatchRaw("query", "tasks", "find", params);
49131
49716
  if (!response.success) {
49132
49717
  handleRawError(response, { command: "find", operation: "tasks.find" });
@@ -49193,7 +49778,7 @@ __export(gc_exports, {
49193
49778
  gcCommand: () => gcCommand
49194
49779
  });
49195
49780
  import { homedir as homedir4, tmpdir } from "node:os";
49196
- import { join as join25 } from "node:path";
49781
+ import { join as join26 } from "node:path";
49197
49782
  import { pruneOrphanTempDirs, pruneOrphanWorktrees } from "@cleocode/core/gc/cleanup.js";
49198
49783
  import { runGC } from "@cleocode/core/gc/runner.js";
49199
49784
  import { readGCState } from "@cleocode/core/gc/state.js";
@@ -49276,7 +49861,7 @@ var init_gc = __esm({
49276
49861
  },
49277
49862
  async run({ args }) {
49278
49863
  const cleoDir = resolveLegacyCleoDir3(args["cleo-dir"]);
49279
- const statePath = join25(cleoDir, "gc-state.json");
49864
+ const statePath = join26(cleoDir, "gc-state.json");
49280
49865
  try {
49281
49866
  const state = await readGCState(statePath);
49282
49867
  const diskStr = state.lastDiskUsedPct !== null ? `${state.lastDiskUsedPct.toFixed(1)}%` : "unknown";
@@ -49329,8 +49914,8 @@ var init_gc = __esm({
49329
49914
  }
49330
49915
  },
49331
49916
  async run({ args }) {
49332
- const xdgData = process.env["XDG_DATA_HOME"] ?? join25(homedir4(), ".local", "share");
49333
- const worktreesRoot = args["worktrees-root"] ?? join25(xdgData, "cleo", "worktrees");
49917
+ const xdgData = process.env["XDG_DATA_HOME"] ?? join26(homedir4(), ".local", "share");
49918
+ const worktreesRoot = args["worktrees-root"] ?? join26(xdgData, "cleo", "worktrees");
49334
49919
  const projectHash = args["project-hash"];
49335
49920
  const dryRun = args["dry-run"];
49336
49921
  const preserveRaw = args["preserve-tasks"];
@@ -50381,6 +50966,50 @@ var init_history = __esm({
50381
50966
  }
50382
50967
  });
50383
50968
 
50969
+ // packages/cleo/src/cli/commands/hygiene.ts
50970
+ var hygiene_exports = {};
50971
+ __export(hygiene_exports, {
50972
+ hygieneCommand: () => hygieneCommand
50973
+ });
50974
+ import { getProjectRoot as getProjectRoot43 } from "@cleocode/core";
50975
+ import { runSpawnReadinessHygieneCli } from "@cleocode/core/hygiene/validate-spawn-readiness.js";
50976
+ var hygieneCommand;
50977
+ var init_hygiene = __esm({
50978
+ "packages/cleo/src/cli/commands/hygiene.ts"() {
50979
+ "use strict";
50980
+ init_dist();
50981
+ hygieneCommand = defineCommand({
50982
+ meta: {
50983
+ name: "hygiene",
50984
+ description: "Run spawn-readiness hygiene checks"
50985
+ },
50986
+ subCommands: {
50987
+ "validate-spawn-readiness": defineCommand({
50988
+ meta: {
50989
+ name: "validate-spawn-readiness",
50990
+ description: "Run all pre-spawn hygiene gates (changeset lint, changelog drift, worktree location)"
50991
+ },
50992
+ args: {
50993
+ "project-root": {
50994
+ type: "string",
50995
+ description: "Project root directory (default: auto-detect)"
50996
+ },
50997
+ "worktree-path": {
50998
+ type: "string",
50999
+ description: "Expected worktree path for location validation"
51000
+ }
51001
+ },
51002
+ async run({ args }) {
51003
+ const projectRoot = args["project-root"] || getProjectRoot43() || process.cwd();
51004
+ const worktreePath = args["worktree-path"];
51005
+ await runSpawnReadinessHygieneCli(projectRoot, worktreePath);
51006
+ }
51007
+ })
51008
+ }
51009
+ });
51010
+ }
51011
+ });
51012
+
50384
51013
  // packages/cleo/src/cli/commands/import-tasks.ts
50385
51014
  var import_tasks_exports = {};
50386
51015
  __export(import_tasks_exports, {
@@ -50542,8 +51171,8 @@ __export(init_exports, {
50542
51171
  getWorkflowTemplatesDir: () => getWorkflowTemplatesDir2,
50543
51172
  initCommand: () => initCommand2
50544
51173
  });
50545
- import { existsSync as existsSync14, readFileSync as readFileSync14 } from "node:fs";
50546
- import { join as join26 } from "node:path";
51174
+ import { existsSync as existsSync15, readFileSync as readFileSync14 } from "node:fs";
51175
+ import { join as join27 } from "node:path";
50547
51176
  import { fileURLToPath as fileURLToPath6 } from "node:url";
50548
51177
  import {
50549
51178
  CleoError as CleoError4,
@@ -50556,11 +51185,11 @@ import { getTemplatesByKind } from "@cleocode/core/templates/registry";
50556
51185
  function getGitignoreTemplate() {
50557
51186
  try {
50558
51187
  const thisFile = fileURLToPath6(import.meta.url);
50559
- const packageRoot = join26(thisFile, "..", "..", "..", "..");
50560
- const localTemplatePath = join26(packageRoot, "templates", "cleo-gitignore");
50561
- const monorepoTemplatePath = join26(packageRoot, "..", "..", "templates", "cleo-gitignore");
50562
- const templatePath = existsSync14(localTemplatePath) ? localTemplatePath : monorepoTemplatePath;
50563
- if (existsSync14(templatePath)) {
51188
+ const packageRoot = join27(thisFile, "..", "..", "..", "..");
51189
+ const localTemplatePath = join27(packageRoot, "templates", "cleo-gitignore");
51190
+ const monorepoTemplatePath = join27(packageRoot, "..", "..", "templates", "cleo-gitignore");
51191
+ const templatePath = existsSync15(localTemplatePath) ? localTemplatePath : monorepoTemplatePath;
51192
+ if (existsSync15(templatePath)) {
50564
51193
  return readFileSync14(templatePath, "utf-8");
50565
51194
  }
50566
51195
  } catch {
@@ -51172,7 +51801,17 @@ var init_labels = __esm({
51172
51801
  labelsCommand = defineCommand({
51173
51802
  meta: {
51174
51803
  name: "labels",
51175
- description: "List all labels with counts or show tasks with specific label"
51804
+ description: "List all labels (no args), or show tasks for a label (cleo labels <name>)"
51805
+ },
51806
+ args: {
51807
+ // Optional positional — when present, dispatches to tasks.list with the
51808
+ // label filter; when absent, falls through to the legacy label.list path.
51809
+ // Required:false keeps the bare `cleo labels` invocation working.
51810
+ name: {
51811
+ type: "positional",
51812
+ description: "Label name to filter tasks by (omit to list all labels)",
51813
+ required: false
51814
+ }
51176
51815
  },
51177
51816
  subCommands: {
51178
51817
  list: listCommand10,
@@ -51180,9 +51819,16 @@ var init_labels = __esm({
51180
51819
  stats: statsCommand2
51181
51820
  },
51182
51821
  async run(ctx) {
51183
- if (!ctx.rawArgs.some((a) => ["list", "show", "stats"].includes(a))) {
51184
- await dispatchFromCli("query", "tasks", "label.list", {}, { command: "labels" });
51822
+ const rawArgs = ctx.rawArgs ?? [];
51823
+ if (rawArgs.some((a) => ["list", "show", "stats"].includes(a))) {
51824
+ return;
51825
+ }
51826
+ const name = ctx.args.name;
51827
+ if (typeof name === "string" && name.length > 0) {
51828
+ await dispatchFromCli("query", "tasks", "list", { label: name }, { command: "labels" });
51829
+ return;
51185
51830
  }
51831
+ await dispatchFromCli("query", "tasks", "label.list", {}, { command: "labels" });
51186
51832
  }
51187
51833
  });
51188
51834
  }
@@ -51516,7 +52162,7 @@ var llm_cost_exports = {};
51516
52162
  __export(llm_cost_exports, {
51517
52163
  costCommand: () => costCommand
51518
52164
  });
51519
- import { getProjectRoot as getProjectRoot43 } from "@cleocode/core/internal";
52165
+ import { getProjectRoot as getProjectRoot44 } from "@cleocode/core/internal";
51520
52166
  import { computeCost } from "@cleocode/core/llm/usage-pricing";
51521
52167
  function resolveSessionId(raw) {
51522
52168
  if (raw === "current") {
@@ -51589,7 +52235,7 @@ var init_llm_cost = __esm({
51589
52235
  process.exit(6);
51590
52236
  }
51591
52237
  const sessionId = resolveSessionId(rawSessionId);
51592
- const projectRoot = getProjectRoot43(process.cwd());
52238
+ const projectRoot = getProjectRoot44(process.cwd());
51593
52239
  let breakdown;
51594
52240
  try {
51595
52241
  breakdown = await loadSessionCostBreakdown(projectRoot, sessionId);
@@ -51960,7 +52606,7 @@ async function _headlessPkceFlow(provider, authUrl) {
51960
52606
  ` After approving, paste the full redirect URL (http://localhost?code=\u2026&state=\u2026):
51961
52607
  `
51962
52608
  );
51963
- return new Promise((resolve8, reject) => {
52609
+ return new Promise((resolve9, reject) => {
51964
52610
  let buf = "";
51965
52611
  process.stdin.setEncoding("utf8");
51966
52612
  process.stdin.once("data", (chunk) => {
@@ -51972,7 +52618,7 @@ async function _headlessPkceFlow(provider, authUrl) {
51972
52618
  reject(new Error('Redirect URL is missing the "code" parameter'));
51973
52619
  return;
51974
52620
  }
51975
- resolve8(code);
52621
+ resolve9(code);
51976
52622
  } catch {
51977
52623
  reject(new Error(`Invalid redirect URL: ${buf}`));
51978
52624
  }
@@ -51980,7 +52626,7 @@ async function _headlessPkceFlow(provider, authUrl) {
51980
52626
  });
51981
52627
  }
51982
52628
  async function _localCallbackPkceFlow(provider, authUrl, expectedState, port) {
51983
- return new Promise((resolve8) => {
52629
+ return new Promise((resolve9) => {
51984
52630
  const server = createServer2((req, res) => {
51985
52631
  const url = new URL(req.url ?? "/", `http://localhost:${port}`);
51986
52632
  const code = url.searchParams.get("code");
@@ -51990,7 +52636,7 @@ async function _localCallbackPkceFlow(provider, authUrl, expectedState, port) {
51990
52636
  if (error) {
51991
52637
  res.end(`<h1>Authorization failed</h1><p>${error}</p><p>You may close this tab.</p>`);
51992
52638
  server.close();
51993
- resolve8({
52639
+ resolve9({
51994
52640
  error: {
51995
52641
  code: "E_PKCE_AUTH_DENIED",
51996
52642
  codeName: "E_PKCE_AUTH_DENIED",
@@ -52002,7 +52648,7 @@ async function _localCallbackPkceFlow(provider, authUrl, expectedState, port) {
52002
52648
  if (!code || state !== expectedState) {
52003
52649
  res.end("<h1>Invalid callback</h1><p>You may close this tab.</p>");
52004
52650
  server.close();
52005
- resolve8({
52651
+ resolve9({
52006
52652
  error: {
52007
52653
  code: "E_PKCE_INVALID_CALLBACK",
52008
52654
  codeName: "E_PKCE_INVALID_CALLBACK",
@@ -52013,7 +52659,7 @@ async function _localCallbackPkceFlow(provider, authUrl, expectedState, port) {
52013
52659
  }
52014
52660
  res.end("<h1>Authorized</h1><p>You may close this tab and return to your terminal.</p>");
52015
52661
  server.close();
52016
- resolve8({ code });
52662
+ resolve9({ code });
52017
52663
  });
52018
52664
  server.listen(port, "localhost", () => {
52019
52665
  process.stderr.write("\n");
@@ -52146,7 +52792,7 @@ function _generateState() {
52146
52792
  return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
52147
52793
  }
52148
52794
  function _findFreePort() {
52149
- return new Promise((resolve8, reject) => {
52795
+ return new Promise((resolve9, reject) => {
52150
52796
  const srv = createServer2();
52151
52797
  srv.listen(0, "localhost", () => {
52152
52798
  const addr = srv.address();
@@ -52156,7 +52802,7 @@ function _findFreePort() {
52156
52802
  return;
52157
52803
  }
52158
52804
  const port = addr.port;
52159
- srv.close(() => resolve8(port));
52805
+ srv.close(() => resolve9(port));
52160
52806
  });
52161
52807
  srv.on("error", reject);
52162
52808
  });
@@ -52778,14 +53424,14 @@ async function readStdin() {
52778
53424
  if (process.stdin.isTTY) {
52779
53425
  return "";
52780
53426
  }
52781
- return new Promise((resolve8, reject) => {
53427
+ return new Promise((resolve9, reject) => {
52782
53428
  let data = "";
52783
53429
  process.stdin.setEncoding("utf-8");
52784
53430
  process.stdin.on("data", (chunk) => {
52785
53431
  data += chunk;
52786
53432
  });
52787
53433
  process.stdin.on("end", () => {
52788
- resolve8(data.trim());
53434
+ resolve9(data.trim());
52789
53435
  });
52790
53436
  process.stdin.on("error", reject);
52791
53437
  });
@@ -53136,7 +53782,7 @@ var memory_exports = {};
53136
53782
  __export(memory_exports, {
53137
53783
  memoryCommand: () => memoryCommand
53138
53784
  });
53139
- import { getProjectRoot as getProjectRoot44 } from "@cleocode/core";
53785
+ import { getProjectRoot as getProjectRoot45 } from "@cleocode/core";
53140
53786
  import {
53141
53787
  getBrainDb as getBrainDb2,
53142
53788
  getDreamStatus,
@@ -54060,7 +54706,7 @@ var init_memory3 = __esm({
54060
54706
  },
54061
54707
  args: {},
54062
54708
  async run() {
54063
- const root = getProjectRoot44();
54709
+ const root = getProjectRoot45();
54064
54710
  try {
54065
54711
  const result = await runConsolidation(root);
54066
54712
  cliOutput(result, { command: "memory-consolidate", operation: "memory.consolidate" });
@@ -54084,7 +54730,7 @@ var init_memory3 = __esm({
54084
54730
  }
54085
54731
  },
54086
54732
  async run({ args }) {
54087
- const root = getProjectRoot44();
54733
+ const root = getProjectRoot45();
54088
54734
  if (args.status) {
54089
54735
  try {
54090
54736
  const status = await getDreamStatus(root);
@@ -54121,7 +54767,7 @@ var init_memory3 = __esm({
54121
54767
  }
54122
54768
  },
54123
54769
  async run({ args }) {
54124
- const root = getProjectRoot44();
54770
+ const root = getProjectRoot45();
54125
54771
  try {
54126
54772
  const { runObserver, runReflector } = await import("@cleocode/core/memory");
54127
54773
  const observerResult = await runObserver(root, args.session, {
@@ -54161,7 +54807,7 @@ var init_memory3 = __esm({
54161
54807
  }
54162
54808
  },
54163
54809
  async run({ args }) {
54164
- const root = getProjectRoot44();
54810
+ const root = getProjectRoot45();
54165
54811
  try {
54166
54812
  await getBrainDb2(root);
54167
54813
  const { totalDuplicateRows, groups } = await scanDuplicateEntries();
@@ -54207,7 +54853,7 @@ var init_memory3 = __esm({
54207
54853
  async run({ args }) {
54208
54854
  const sourceDir = args.from;
54209
54855
  const isDryRun = !!args["dry-run"];
54210
- const projectRoot = getProjectRoot44();
54856
+ const projectRoot = getProjectRoot45();
54211
54857
  try {
54212
54858
  const result = await importMemoryFiles({
54213
54859
  sourceDir,
@@ -54358,7 +55004,7 @@ var init_memory3 = __esm({
54358
55004
  },
54359
55005
  args: {},
54360
55006
  async run() {
54361
- const root = getProjectRoot44();
55007
+ const root = getProjectRoot45();
54362
55008
  try {
54363
55009
  await getBrainDb2(root);
54364
55010
  const result = await getTierStats(root);
@@ -54401,7 +55047,7 @@ var init_memory3 = __esm({
54401
55047
  }
54402
55048
  },
54403
55049
  async run({ args }) {
54404
- const root = getProjectRoot44();
55050
+ const root = getProjectRoot45();
54405
55051
  const targetTier = args.to;
54406
55052
  const reason = args.reason;
54407
55053
  const validTiers = ["medium", "long"];
@@ -54467,7 +55113,7 @@ var init_memory3 = __esm({
54467
55113
  }
54468
55114
  },
54469
55115
  async run({ args }) {
54470
- const root = getProjectRoot44();
55116
+ const root = getProjectRoot45();
54471
55117
  const targetTier = args.to;
54472
55118
  const reason = args.reason;
54473
55119
  const validTiers = ["short", "medium"];
@@ -54927,7 +55573,7 @@ var migrate_claude_mem_exports = {};
54927
55573
  __export(migrate_claude_mem_exports, {
54928
55574
  migrateClaudeMemCommand: () => migrateClaudeMemCommand
54929
55575
  });
54930
- import { getProjectRoot as getProjectRoot45, migrateClaudeMem } from "@cleocode/core/internal";
55576
+ import { getProjectRoot as getProjectRoot46, migrateClaudeMem } from "@cleocode/core/internal";
54931
55577
  import { ingestLooseAgentOutputs, ingestRcasdDirectories } from "@cleocode/core/memory";
54932
55578
  import { getDb as getDb2 } from "@cleocode/core/store/sqlite";
54933
55579
  var storageCommand, claudeMemCommand, manifestIngestCommand, migrateClaudeMemCommand;
@@ -54990,7 +55636,7 @@ var init_migrate_claude_mem = __esm({
54990
55636
  }
54991
55637
  },
54992
55638
  async run({ args }) {
54993
- const root = getProjectRoot45();
55639
+ const root = getProjectRoot46();
54994
55640
  try {
54995
55641
  const result = await migrateClaudeMem(root, {
54996
55642
  sourcePath: args.source,
@@ -55039,7 +55685,7 @@ var init_migrate_claude_mem = __esm({
55039
55685
  }
55040
55686
  },
55041
55687
  async run({ args }) {
55042
- const projectRoot = getProjectRoot45();
55688
+ const projectRoot = getProjectRoot46();
55043
55689
  try {
55044
55690
  const db = await getDb2(projectRoot);
55045
55691
  const rcasdFlag = Boolean(args.rcasd);
@@ -55143,7 +55789,7 @@ __export(nexus_exports, {
55143
55789
  import { appendFile as appendFile2, mkdir as mkdir3 } from "node:fs/promises";
55144
55790
  import { homedir as homedir5 } from "node:os";
55145
55791
  import path4 from "node:path";
55146
- import { getProjectRoot as getProjectRoot46 } from "@cleocode/core";
55792
+ import { getProjectRoot as getProjectRoot47 } from "@cleocode/core";
55147
55793
  import { getSymbolImpact } from "@cleocode/core/nexus";
55148
55794
  import { runNexusAnalysis } from "@cleocode/core/nexus/analyze-orchestrator.js";
55149
55795
  import { exportNexusGraph } from "@cleocode/core/nexus/export.js";
@@ -55258,7 +55904,7 @@ var init_nexus3 = __esm({
55258
55904
  async run({ args }) {
55259
55905
  applyJsonFlag2(args.json);
55260
55906
  const projectIdOverride = args["project-id"];
55261
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot46();
55907
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot47();
55262
55908
  const startTime = Date.now();
55263
55909
  try {
55264
55910
  const [{ getNexusDb, nexusSchema }, { getIndexStats }] = await Promise.all([
@@ -55773,7 +56419,7 @@ var init_nexus3 = __esm({
55773
56419
  applyJsonFlag2(args.json);
55774
56420
  const startTime = Date.now();
55775
56421
  const projectIdOverride = args["project-id"];
55776
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot46();
56422
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot47();
55777
56423
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
55778
56424
  const response = await dispatchRaw("query", "nexus", "clusters", { projectId, repoPath });
55779
56425
  const durationMs = Date.now() - startTime;
@@ -55817,7 +56463,7 @@ var init_nexus3 = __esm({
55817
56463
  applyJsonFlag2(args.json);
55818
56464
  const startTime = Date.now();
55819
56465
  const projectIdOverride = args["project-id"];
55820
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot46();
56466
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot47();
55821
56467
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
55822
56468
  const response = await dispatchRaw("query", "nexus", "flows", { projectId, repoPath });
55823
56469
  const durationMs = Date.now() - startTime;
@@ -55860,7 +56506,7 @@ var init_nexus3 = __esm({
55860
56506
  void appendDeprecationTelemetry("nexus.context", "cleo graph context");
55861
56507
  const startTime = Date.now();
55862
56508
  const projectIdOverride = args["project-id"];
55863
- const repoPath = getProjectRoot46();
56509
+ const repoPath = getProjectRoot47();
55864
56510
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
55865
56511
  const limit = parseInt(args.limit, 10);
55866
56512
  const symbolName = args.symbol;
@@ -55923,7 +56569,7 @@ var init_nexus3 = __esm({
55923
56569
  const startTime = Date.now();
55924
56570
  const whyFlag = !!args.why;
55925
56571
  const projectIdOverride = args["project-id"];
55926
- const repoPath = getProjectRoot46();
56572
+ const repoPath = getProjectRoot47();
55927
56573
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
55928
56574
  const maxDepth = Math.min(parseInt(args.depth, 10), 5);
55929
56575
  const symbolName = args.symbol;
@@ -55995,7 +56641,7 @@ var init_nexus3 = __esm({
55995
56641
  const projectIdOverride = args["project-id"];
55996
56642
  const isIncremental = !!args.incremental;
55997
56643
  const ctx = getFormatContext();
55998
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot46();
56644
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot47();
55999
56645
  humanInfo(`[nexus] Analyzing: ${repoPath}${isIncremental ? " (incremental)" : ""}`);
56000
56646
  if (!isIncremental) humanInfo("[nexus] Clearing existing index for project...");
56001
56647
  try {
@@ -56098,7 +56744,7 @@ var init_nexus3 = __esm({
56098
56744
  async run({ args }) {
56099
56745
  applyJsonFlag2(args.json);
56100
56746
  const startTime = Date.now();
56101
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot46();
56747
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot47();
56102
56748
  const name = args.name;
56103
56749
  const response = await dispatchRaw("mutate", "nexus", "projects.register", {
56104
56750
  path: repoPath,
@@ -56354,13 +57000,13 @@ var init_nexus3 = __esm({
56354
57000
  if (!skipPrompt) {
56355
57001
  const { createInterface: createInterface5 } = await import("node:readline");
56356
57002
  const rl = createInterface5({ input: process.stdin, output: process.stdout });
56357
- const confirmed = await new Promise((resolve8) => {
57003
+ const confirmed = await new Promise((resolve9) => {
56358
57004
  rl.question(
56359
57005
  `
56360
57006
  [nexus] Delete ${matchCount} project(s) from the registry? [y/N] `,
56361
57007
  (answer) => {
56362
57008
  rl.close();
56363
- resolve8(answer.trim().toLowerCase() === "y");
57009
+ resolve9(answer.trim().toLowerCase() === "y");
56364
57010
  }
56365
57011
  );
56366
57012
  });
@@ -56456,7 +57102,7 @@ var init_nexus3 = __esm({
56456
57102
  applyJsonFlag2(args.json);
56457
57103
  const startTime = Date.now();
56458
57104
  const projectIdOverride = args["project-id"];
56459
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot46();
57105
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot47();
56460
57106
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
56461
57107
  const response = await dispatchRaw("mutate", "nexus", "refresh-bridge", {
56462
57108
  repoPath,
@@ -56562,7 +57208,7 @@ var init_nexus3 = __esm({
56562
57208
  async run({ args }) {
56563
57209
  applyJsonFlag2(args.json);
56564
57210
  const startTime = Date.now();
56565
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot46();
57211
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot47();
56566
57212
  const projectIdOverride = args["project-id"];
56567
57213
  const beforeRef = args.before ?? "HEAD~1";
56568
57214
  const afterRef = args.after ?? "HEAD";
@@ -56680,7 +57326,7 @@ var init_nexus3 = __esm({
56680
57326
  applyJsonFlag2(args.json);
56681
57327
  const startTime = Date.now();
56682
57328
  const projectIdOverride = args["project-id"];
56683
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot46();
57329
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot47();
56684
57330
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
56685
57331
  const response = await dispatchRaw("query", "nexus", "route-map", { projectId });
56686
57332
  const durationMs = Date.now() - startTime;
@@ -56736,7 +57382,7 @@ var init_nexus3 = __esm({
56736
57382
  const startTime = Date.now();
56737
57383
  const routeSymbol = args.routeSymbol;
56738
57384
  const projectIdOverride = args["project-id"];
56739
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot46();
57385
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot47();
56740
57386
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
56741
57387
  const response = await dispatchRaw("query", "nexus", "shape-check", { routeSymbol, projectId });
56742
57388
  const durationMs = Date.now() - startTime;
@@ -57126,7 +57772,7 @@ var init_nexus3 = __esm({
57126
57772
  async run({ args }) {
57127
57773
  applyJsonFlag2(args.json);
57128
57774
  const startTime = Date.now();
57129
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot46();
57775
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot47();
57130
57776
  const projectIdOverride = args["project-id"];
57131
57777
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
57132
57778
  const response = await dispatchRaw("mutate", "nexus", "contracts-sync", {
@@ -57230,7 +57876,7 @@ var init_nexus3 = __esm({
57230
57876
  async run({ args }) {
57231
57877
  applyJsonFlag2(args.json);
57232
57878
  const startTime = Date.now();
57233
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot46();
57879
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot47();
57234
57880
  const projectId = Buffer.from(repoPath).toString("base64url").slice(0, 32);
57235
57881
  const response = await dispatchRaw("mutate", "nexus", "contracts-link-tasks", {
57236
57882
  projectId,
@@ -57311,7 +57957,7 @@ var init_nexus3 = __esm({
57311
57957
  const isIncremental = !!args.incremental;
57312
57958
  try {
57313
57959
  const result = await runNexusWiki({
57314
- projectRoot: getProjectRoot46(),
57960
+ projectRoot: getProjectRoot47(),
57315
57961
  outputDir,
57316
57962
  communityFilter,
57317
57963
  incremental: isIncremental
@@ -57661,7 +58307,7 @@ __export(orchestrate_exports, {
57661
58307
  });
57662
58308
  import { execFileSync as execFileSync3 } from "node:child_process";
57663
58309
  import { orchestration } from "@cleocode/core";
57664
- import { BUILD_CONFIG as BUILD_CONFIG2 } from "@cleocode/core/internal";
58310
+ import { BUILD_CONFIG as BUILD_CONFIG2, getProjectRoot as getProjectRoot48 } from "@cleocode/core/internal";
57665
58311
  function formatRollupTable(rollup) {
57666
58312
  const waves = "waves" in rollup ? rollup.waves : [rollup];
57667
58313
  const lines = [];
@@ -57696,7 +58342,7 @@ function formatRollupTable(rollup) {
57696
58342
  }
57697
58343
  return lines.join("\n");
57698
58344
  }
57699
- var rollupCommand, startCommand5, statusCommand11, analyzeCommand4, readyCommand, nextCommand2, wavesCommand2, planCommand, spawnCommand2, validateCommand6, contextCommand5, ivtrCommand, parallelCommand, tesseraListCommand, tesseraInstantiateCommand, tesseraCommand, unblockCommand, bootstrapCommand, classifyCommand, fanoutStatusCommand, handoffCommand, spawnExecuteCommand, fanoutCommand, pruneCommand, worktreeCompleteCommand, conduitStatusCommand, conduitPeekCommand, conduitStartCommand, conduitStopCommand, approveCommand, rejectCommand, pendingCommand, conduitSendCommand, orchestrateCommand;
58345
+ var rollupCommand, startCommand5, statusCommand11, dashboardCommand, analyzeCommand4, readyCommand, nextCommand2, wavesCommand2, planCommand, spawnCommand2, validateCommand6, contextCommand5, ivtrCommand, parallelCommand, tesseraListCommand, tesseraInstantiateCommand, tesseraCommand, unblockCommand, bootstrapCommand, classifyCommand, fanoutStatusCommand, handoffCommand, spawnExecuteCommand, fanoutCommand, pruneCommand, worktreeCompleteCommand, conduitStatusCommand, conduitPeekCommand, conduitStartCommand, conduitStopCommand, approveCommand, rejectCommand, pendingCommand, conduitSendCommand, orchestrateCommand;
57700
58346
  var init_orchestrate3 = __esm({
57701
58347
  "packages/cleo/src/cli/commands/orchestrate.ts"() {
57702
58348
  "use strict";
@@ -57791,6 +58437,28 @@ var init_orchestrate3 = __esm({
57791
58437
  );
57792
58438
  }
57793
58439
  });
58440
+ dashboardCommand = defineCommand({
58441
+ meta: {
58442
+ name: "dashboard",
58443
+ description: "Show queue depth, admin-merge rate, force-bypass rate, and active worktree count"
58444
+ },
58445
+ args: {
58446
+ window: {
58447
+ type: "string",
58448
+ description: "Audit rate window in hours (default: 24)"
58449
+ }
58450
+ },
58451
+ async run({ args }) {
58452
+ const rateWindowHours = args.window !== void 0 ? Number.parseFloat(String(args.window)) : void 0;
58453
+ const metrics = await orchestration.collectOrchestrateDashboard(getProjectRoot48(), {
58454
+ ...rateWindowHours !== void 0 && Number.isFinite(rateWindowHours) && rateWindowHours > 0 ? { rateWindowHours } : {}
58455
+ });
58456
+ cliOutput(metrics, {
58457
+ command: "orchestrate-dashboard",
58458
+ operation: "orchestrate.dashboard"
58459
+ });
58460
+ }
58461
+ });
57794
58462
  analyzeCommand4 = defineCommand({
57795
58463
  meta: { name: "analyze", description: "Analyze epic dependency structure" },
57796
58464
  args: {
@@ -58547,6 +59215,7 @@ var init_orchestrate3 = __esm({
58547
59215
  subCommands: {
58548
59216
  start: startCommand5,
58549
59217
  status: statusCommand11,
59218
+ dashboard: dashboardCommand,
58550
59219
  "roll-up": rollupCommand,
58551
59220
  analyze: analyzeCommand4,
58552
59221
  ready: readyCommand,
@@ -59771,7 +60440,7 @@ var refresh_memory_exports = {};
59771
60440
  __export(refresh_memory_exports, {
59772
60441
  refreshMemoryCommand: () => refreshMemoryCommand
59773
60442
  });
59774
- import { getProjectRoot as getProjectRoot47 } from "@cleocode/core";
60443
+ import { getProjectRoot as getProjectRoot49 } from "@cleocode/core";
59775
60444
  var refreshMemoryCommand;
59776
60445
  var init_refresh_memory = __esm({
59777
60446
  "packages/cleo/src/cli/commands/refresh-memory.ts"() {
@@ -59784,7 +60453,7 @@ var init_refresh_memory = __esm({
59784
60453
  description: "Regenerate .cleo/memory-bridge.md from brain.db"
59785
60454
  },
59786
60455
  async run() {
59787
- const projectDir = getProjectRoot47();
60456
+ const projectDir = getProjectRoot49();
59788
60457
  const { writeMemoryBridge } = await import("@cleocode/core/internal");
59789
60458
  const result = await writeMemoryBridge(projectDir);
59790
60459
  if (result.written) {
@@ -60032,7 +60701,7 @@ __export(release_exports, {
60032
60701
  releaseCommand: () => releaseCommand
60033
60702
  });
60034
60703
  import { release as release3 } from "@cleocode/core";
60035
- var listCommand19, showCommand10, cancelCommand2, rollbackCommand, rollbackFullCommand, prStatusCommand, channelCommand, planCommand3, openCommand2, reconcileCommand4, releaseCommand;
60704
+ var listCommand19, showCommand10, cancelCommand2, rollbackCommand, rollbackFullCommand, prStatusCommand, channelCommand, validateChangelogCommand, planCommand3, openCommand2, reconcileCommand4, releaseCommand;
60036
60705
  var init_release3 = __esm({
60037
60706
  "packages/cleo/src/cli/commands/release.ts"() {
60038
60707
  "use strict";
@@ -60181,6 +60850,36 @@ var init_release3 = __esm({
60181
60850
  await dispatchFromCli("query", "pipeline", "release.channel.show", {}, { command: "release" });
60182
60851
  }
60183
60852
  });
60853
+ validateChangelogCommand = defineCommand({
60854
+ meta: {
60855
+ name: "validate-changelog",
60856
+ description: "Validate that CHANGELOG.md contains the canonical `## [VERSION]` header (T9937)"
60857
+ },
60858
+ args: {
60859
+ version: {
60860
+ type: "positional",
60861
+ description: "Release version (accepts v2026.5.94 or 2026.5.94)",
60862
+ required: true
60863
+ },
60864
+ path: {
60865
+ type: "string",
60866
+ description: "Override the CHANGELOG file path (default: <projectRoot>/CHANGELOG.md)",
60867
+ required: false
60868
+ }
60869
+ },
60870
+ async run({ args }) {
60871
+ await dispatchFromCli(
60872
+ "query",
60873
+ "release",
60874
+ "validate-changelog",
60875
+ {
60876
+ version: args.version,
60877
+ ...typeof args.path === "string" && args.path.length > 0 ? { changelogPath: args.path } : {}
60878
+ },
60879
+ { command: "release" }
60880
+ );
60881
+ }
60882
+ });
60184
60883
  planCommand3 = defineCommand({
60185
60884
  meta: {
60186
60885
  name: "plan",
@@ -60221,9 +60920,17 @@ var init_release3 = __esm({
60221
60920
  "no-changelog": {
60222
60921
  type: "boolean",
60223
60922
  description: "Skip CHANGELOG.md auto-write (default: write/replace the ## [<version>] section). (T9838)"
60923
+ },
60924
+ "skip-readiness": {
60925
+ type: "boolean",
60926
+ description: "Skip the release-readiness preflight check (default: run check). Use only in emergency. (T10459)"
60224
60927
  }
60225
60928
  },
60226
60929
  async run({ args }) {
60930
+ if (args["skip-readiness"] !== true) {
60931
+ const { runSpawnReadinessHygieneCli: runSpawnReadinessHygieneCli2 } = await import("@cleocode/core/hygiene/validate-spawn-readiness.js");
60932
+ await runSpawnReadinessHygieneCli2();
60933
+ }
60227
60934
  await dispatchFromCli(
60228
60935
  "mutate",
60229
60936
  "release",
@@ -60344,7 +61051,9 @@ var init_release3 = __esm({
60344
61051
  cancel: cancelCommand2,
60345
61052
  "pr-status": prStatusCommand,
60346
61053
  channel: channelCommand,
60347
- "rollback-full": rollbackFullCommand
61054
+ "rollback-full": rollbackFullCommand,
61055
+ // T9937 — canonical CHANGELOG.md header validator (Saga T9862).
61056
+ "validate-changelog": validateChangelogCommand
60348
61057
  },
60349
61058
  async run({ cmd, rawArgs }) {
60350
61059
  const firstArg = rawArgs?.find((a) => !a.startsWith("-"));
@@ -61185,8 +61894,8 @@ import fs3 from "node:fs";
61185
61894
  import path5 from "node:path";
61186
61895
  import {
61187
61896
  CleoError as CleoError7,
61188
- getProjectRoot as getProjectRoot48,
61189
- getTaskAccessor as getTaskAccessor3,
61897
+ getProjectRoot as getProjectRoot50,
61898
+ getTaskAccessor as getTaskAccessor4,
61190
61899
  parseConflictReport,
61191
61900
  setAtPath
61192
61901
  } from "@cleocode/core";
@@ -61206,7 +61915,7 @@ var init_restore = __esm({
61206
61915
  description: "Apply manually-resolved conflicts from .cleo/restore-conflicts.md"
61207
61916
  },
61208
61917
  async run() {
61209
- const projectRoot = getProjectRoot48();
61918
+ const projectRoot = getProjectRoot50();
61210
61919
  const reportPath = path5.join(projectRoot, CLEO_DIR_NAME, RESTORE_CONFLICTS_MD);
61211
61920
  if (!fs3.existsSync(reportPath)) {
61212
61921
  humanLine("No pending restore conflicts. Nothing to finalize.");
@@ -61384,7 +62093,7 @@ var init_restore = __esm({
61384
62093
  if (!idPattern.test(taskId)) {
61385
62094
  throw new CleoError7(2 /* INVALID_INPUT */, `Invalid task ID: ${taskId}`);
61386
62095
  }
61387
- const accessor = await getTaskAccessor3();
62096
+ const accessor = await getTaskAccessor4();
61388
62097
  const activeTask = await accessor.loadSingleTask(taskId);
61389
62098
  if (activeTask) {
61390
62099
  if (activeTask.status === "cancelled") {
@@ -61572,7 +62281,7 @@ __export(revert_exports, {
61572
62281
  revertCommand: () => revertCommand
61573
62282
  });
61574
62283
  import { readFile as readFile5 } from "node:fs/promises";
61575
- import { join as join27 } from "node:path";
62284
+ import { join as join28 } from "node:path";
61576
62285
  import { cwd as processCwd2 } from "node:process";
61577
62286
  import { E_RECEIPT_NOT_FOUND } from "@cleocode/core/sentient/chain-walker.js";
61578
62287
  import { SENTIENT_STATE_FILE } from "@cleocode/core/sentient/daemon.js";
@@ -61625,7 +62334,7 @@ async function loadOwnerAttestation(attestationFilePath) {
61625
62334
  return obj;
61626
62335
  }
61627
62336
  async function loadOwnerPubkeys(projectRoot) {
61628
- const path6 = join27(projectRoot, OWNER_PUBKEYS_FILE);
62337
+ const path6 = join28(projectRoot, OWNER_PUBKEYS_FILE);
61629
62338
  try {
61630
62339
  const raw = await readFile5(path6, "utf-8");
61631
62340
  const parsed = JSON.parse(raw);
@@ -61709,7 +62418,7 @@ var init_revert = __esm({
61709
62418
  if (attestation && allowedPubkeys.size > 0 && !allowedPubkeys.has(attestation.ownerPubkey)) {
61710
62419
  emitFailure2(
61711
62420
  E_OWNER_ATTESTATION_REQUIRED,
61712
- `Attestation pubkey "${attestation.ownerPubkey}" is not in the owner allowlist at ${join27(projectRoot, OWNER_PUBKEYS_FILE)}`,
62421
+ `Attestation pubkey "${attestation.ownerPubkey}" is not in the owner allowlist at ${join28(projectRoot, OWNER_PUBKEYS_FILE)}`,
61713
62422
  jsonMode
61714
62423
  );
61715
62424
  }
@@ -61762,7 +62471,7 @@ ${lines}`
61762
62471
  identity,
61763
62472
  includeHuman
61764
62473
  });
61765
- const statePath = join27(projectRoot, SENTIENT_STATE_FILE);
62474
+ const statePath = join28(projectRoot, SENTIENT_STATE_FILE);
61766
62475
  const state = await readSentientState(statePath);
61767
62476
  emitSuccess(
61768
62477
  {
@@ -62296,7 +63005,7 @@ __export(self_update_exports, {
62296
63005
  });
62297
63006
  import { execFile } from "node:child_process";
62298
63007
  import { readFile as readFile6 } from "node:fs/promises";
62299
- import { join as join28 } from "node:path";
63008
+ import { join as join29 } from "node:path";
62300
63009
  import * as readline2 from "node:readline";
62301
63010
  import { promisify } from "node:util";
62302
63011
  import {
@@ -62311,7 +63020,7 @@ import {
62311
63020
  async function getCurrentVersion() {
62312
63021
  const cleoHome = getCleoHome4();
62313
63022
  try {
62314
- const content = await readFile6(join28(cleoHome, "VERSION"), "utf-8");
63023
+ const content = await readFile6(join29(cleoHome, "VERSION"), "utf-8");
62315
63024
  return (content.split("\n")[0] ?? "unknown").trim();
62316
63025
  } catch {
62317
63026
  return "unknown";
@@ -62365,7 +63074,7 @@ async function writeRuntimeVersionMetadata(mode, source, version) {
62365
63074
  ];
62366
63075
  await import("node:fs/promises").then(
62367
63076
  ({ writeFile: writeFile4, mkdir: mkdir5 }) => mkdir5(cleoHome, { recursive: true }).then(
62368
- () => writeFile4(join28(cleoHome, "VERSION"), `${lines.join("\n")}
63077
+ () => writeFile4(join29(cleoHome, "VERSION"), `${lines.join("\n")}
62369
63078
  `, "utf-8")
62370
63079
  )
62371
63080
  );
@@ -62403,11 +63112,11 @@ async function runPostUpdateDiagnostics(opts) {
62403
63112
  input: process.stdin,
62404
63113
  output: process.stdout
62405
63114
  });
62406
- shouldMigrate = await new Promise((resolve8) => {
63115
+ shouldMigrate = await new Promise((resolve9) => {
62407
63116
  rl.question(" Do you want to run the upgrade now? [Y/n] ", (answer) => {
62408
63117
  rl.close();
62409
63118
  const clean = answer.trim().toLowerCase();
62410
- resolve8(clean === "" || clean === "y" || clean === "yes");
63119
+ resolve9(clean === "" || clean === "y" || clean === "yes");
62411
63120
  });
62412
63121
  });
62413
63122
  }
@@ -62778,7 +63487,7 @@ __export(sentient_exports, {
62778
63487
  promptAcceptExecution: () => promptAcceptExecution,
62779
63488
  sentientCommand: () => sentientCommand
62780
63489
  });
62781
- import { join as join29 } from "node:path";
63490
+ import { join as join30 } from "node:path";
62782
63491
  import { cwd as processCwd3, stdin, stdout } from "node:process";
62783
63492
  import { createInterface as createInterface3 } from "node:readline/promises";
62784
63493
  import {
@@ -62867,7 +63576,7 @@ var init_sentient3 = __esm({
62867
63576
  return;
62868
63577
  }
62869
63578
  if (dryRun) {
62870
- const statePath2 = join29(projectRoot, SENTIENT_STATE_FILE2);
63579
+ const statePath2 = join30(projectRoot, SENTIENT_STATE_FILE2);
62871
63580
  const outcome = await safeRunTick({ projectRoot, statePath: statePath2, dryRun: true });
62872
63581
  emitSuccess2(
62873
63582
  { dryRun: true, outcome },
@@ -62983,7 +63692,7 @@ Logs: ${logPath}`
62983
63692
  const jsonMode = args.json === true;
62984
63693
  const dryRun = args["dry-run"] === true;
62985
63694
  try {
62986
- const statePath = join29(projectRoot, SENTIENT_STATE_FILE2);
63695
+ const statePath = join30(projectRoot, SENTIENT_STATE_FILE2);
62987
63696
  const outcome = await safeRunTick({ projectRoot, statePath, dryRun });
62988
63697
  emitSuccess2(
62989
63698
  { outcome, dryRun },
@@ -63075,7 +63784,7 @@ Logs: ${logPath}`
63075
63784
  return;
63076
63785
  }
63077
63786
  await db.update(tasks).set({ status: "pending", updatedAt: now }).where(eq2(tasks.id, id)).run();
63078
- const statePath = join29(projectRoot, SENTIENT_STATE_FILE2);
63787
+ const statePath = join30(projectRoot, SENTIENT_STATE_FILE2);
63079
63788
  const state = await readSentientState2(statePath);
63080
63789
  await patchSentientState(statePath, {
63081
63790
  tier2Stats: {
@@ -63171,7 +63880,7 @@ Logs: ${logPath}`
63171
63880
  return;
63172
63881
  }
63173
63882
  await db.update(tasks).set({ status: "cancelled", cancellationReason: reason, cancelledAt: now, updatedAt: now }).where(eq2(tasks.id, id)).run();
63174
- const statePath = join29(projectRoot, SENTIENT_STATE_FILE2);
63883
+ const statePath = join30(projectRoot, SENTIENT_STATE_FILE2);
63175
63884
  const state = await readSentientState2(statePath);
63176
63885
  await patchSentientState(statePath, {
63177
63886
  tier2Stats: {
@@ -63216,7 +63925,7 @@ Logs: ${logPath}`
63216
63925
  const projectRoot = resolveProjectRoot6(args.project);
63217
63926
  const jsonMode = args.json === true;
63218
63927
  try {
63219
- const statePath = join29(projectRoot, SENTIENT_STATE_FILE2);
63928
+ const statePath = join30(projectRoot, SENTIENT_STATE_FILE2);
63220
63929
  const outcome = await safeRunProposeTick({ projectRoot, statePath });
63221
63930
  emitSuccess2(
63222
63931
  { outcome },
@@ -63236,7 +63945,7 @@ Logs: ${logPath}`
63236
63945
  const projectRoot = resolveProjectRoot6(args.project);
63237
63946
  const jsonMode = args.json === true;
63238
63947
  try {
63239
- const statePath = join29(projectRoot, SENTIENT_STATE_FILE2);
63948
+ const statePath = join30(projectRoot, SENTIENT_STATE_FILE2);
63240
63949
  const updated = await patchSentientState(statePath, { tier2Enabled: true });
63241
63950
  emitSuccess2({ tier2Enabled: updated.tier2Enabled }, jsonMode, "Tier-2 proposals enabled");
63242
63951
  } catch (err) {
@@ -63255,7 +63964,7 @@ Logs: ${logPath}`
63255
63964
  const projectRoot = resolveProjectRoot6(args.project);
63256
63965
  const jsonMode = args.json === true;
63257
63966
  try {
63258
- const statePath = join29(projectRoot, SENTIENT_STATE_FILE2);
63967
+ const statePath = join30(projectRoot, SENTIENT_STATE_FILE2);
63259
63968
  const updated = await patchSentientState(statePath, { tier2Enabled: false });
63260
63969
  emitSuccess2({ tier2Enabled: updated.tier2Enabled }, jsonMode, "Tier-2 proposals disabled");
63261
63970
  } catch (err) {
@@ -63286,7 +63995,7 @@ Logs: ${logPath}`
63286
63995
  const projectRoot = resolveProjectRoot6(args.project);
63287
63996
  const jsonMode = args.json === true;
63288
63997
  try {
63289
- const statePath = join29(projectRoot, SENTIENT_STATE_FILE2);
63998
+ const statePath = join30(projectRoot, SENTIENT_STATE_FILE2);
63290
63999
  const state = await readSentientState2(statePath);
63291
64000
  emitSuccess2(
63292
64001
  {
@@ -63844,7 +64553,7 @@ var sequence_exports = {};
63844
64553
  __export(sequence_exports, {
63845
64554
  sequenceCommand: () => sequenceCommand
63846
64555
  });
63847
- import { getProjectRoot as getProjectRoot49 } from "@cleocode/core/internal";
64556
+ import { getProjectRoot as getProjectRoot51 } from "@cleocode/core/internal";
63848
64557
  var showCommand12, checkCommand6, repairCommand2, sequenceCommand;
63849
64558
  var init_sequence = __esm({
63850
64559
  "packages/cleo/src/cli/commands/sequence.ts"() {
@@ -63880,7 +64589,7 @@ var init_sequence = __esm({
63880
64589
  meta: { name: "repair", description: "Reset counter to max + 1 if behind" },
63881
64590
  async run() {
63882
64591
  const { repairSequence } = await import("@cleocode/core/internal");
63883
- const projectRoot = getProjectRoot49();
64592
+ const projectRoot = getProjectRoot51();
63884
64593
  const repair = await repairSequence(projectRoot);
63885
64594
  const result = {
63886
64595
  repaired: repair.repaired,
@@ -63934,7 +64643,7 @@ async function promptOwnerAuthPassword(sessionName) {
63934
64643
  terminal: true
63935
64644
  });
63936
64645
  process.stderr.write(`[cleo] Enter owner-auth password for session "${sessionName}": `);
63937
- const password = await new Promise((resolve8) => {
64646
+ const password = await new Promise((resolve9) => {
63938
64647
  if (process.stdin.setRawMode) {
63939
64648
  process.stdin.setRawMode(
63940
64649
  true
@@ -63952,10 +64661,10 @@ async function promptOwnerAuthPassword(sessionName) {
63952
64661
  );
63953
64662
  }
63954
64663
  process.stderr.write("\n");
63955
- resolve8(pw);
64664
+ resolve9(pw);
63956
64665
  } else if (ch === "") {
63957
64666
  process.stderr.write("\n[cleo] Cancelled.\n");
63958
- resolve8("");
64667
+ resolve9("");
63959
64668
  } else if (ch === "\x7F" || ch === "\b") {
63960
64669
  pw = pw.slice(0, -1);
63961
64670
  } else {
@@ -64335,8 +65044,8 @@ var init_session4 = __esm({
64335
65044
  "audit-scope": { type: "string", description: "Audit log scope (global|local)" }
64336
65045
  },
64337
65046
  async run({ args }) {
64338
- const { detectSessionDrift, getProjectRoot: getProjectRoot54 } = await import("@cleocode/core");
64339
- const projectRoot = await getProjectRoot54();
65047
+ const { detectSessionDrift, getProjectRoot: getProjectRoot56 } = await import("@cleocode/core");
65048
+ const projectRoot = await getProjectRoot56();
64340
65049
  const scope = args["audit-scope"] === "local" ? "local" : "global";
64341
65050
  const report = await detectSessionDrift({ projectRoot, auditScope: scope });
64342
65051
  cliOutput(report, { command: "session drift", operation: "session.drift" });
@@ -66990,14 +67699,14 @@ var init_telemetry2 = __esm({
66990
67699
 
66991
67700
  // packages/cleo/src/cli/commands/templates/lib.ts
66992
67701
  import { readFileSync as readFileSync15 } from "node:fs";
66993
- import { isAbsolute as isAbsolute3, resolve as resolve6 } from "node:path";
66994
- import { getProjectRoot as getProjectRoot50 } from "@cleocode/core";
67702
+ import { isAbsolute as isAbsolute3, resolve as resolve7 } from "node:path";
67703
+ import { getProjectRoot as getProjectRoot52 } from "@cleocode/core";
66995
67704
  import { resolveSourcePathAbsolute } from "@cleocode/core/templates/registry";
66996
67705
  function resolveProjectRoot7(raw) {
66997
67706
  if (typeof raw === "string" && raw.length > 0) {
66998
- return isAbsolute3(raw) ? raw : resolve6(process.cwd(), raw);
67707
+ return isAbsolute3(raw) ? raw : resolve7(process.cwd(), raw);
66999
67708
  }
67000
- return getProjectRoot50();
67709
+ return getProjectRoot52();
67001
67710
  }
67002
67711
  function readTemplateSource(entry) {
67003
67712
  const sourceAbsolute = resolveSourcePathAbsolute(entry);
@@ -67016,8 +67725,8 @@ var init_lib = __esm({
67016
67725
  });
67017
67726
 
67018
67727
  // packages/cleo/src/cli/commands/templates/diff.ts
67019
- import { existsSync as existsSync15, readFileSync as readFileSync16 } from "node:fs";
67020
- import { join as join30 } from "node:path";
67728
+ import { existsSync as existsSync16, readFileSync as readFileSync16 } from "node:fs";
67729
+ import { join as join31 } from "node:path";
67021
67730
  import { getTemplateById } from "@cleocode/core/templates/registry";
67022
67731
  function unifiedDiff(a, b) {
67023
67732
  const aLines = a.length === 0 ? [] : a.split("\n");
@@ -67087,7 +67796,7 @@ var init_diff = __esm({
67087
67796
  let rendered;
67088
67797
  try {
67089
67798
  projectRoot = resolveProjectRoot7(args["project"]);
67090
- installPath = join30(projectRoot, entry.installPath);
67799
+ installPath = join31(projectRoot, entry.installPath);
67091
67800
  const source = readTemplateSource(entry);
67092
67801
  rendered = applySubstitution(entry, source).rendered;
67093
67802
  } catch (err) {
@@ -67098,7 +67807,7 @@ var init_diff = __esm({
67098
67807
  process.exit(1 /* GENERAL_ERROR */);
67099
67808
  return;
67100
67809
  }
67101
- if (!existsSync15(installPath)) {
67810
+ if (!existsSync16(installPath)) {
67102
67811
  const missingResult = {
67103
67812
  id,
67104
67813
  installPath,
@@ -67137,8 +67846,8 @@ ${unifiedDiff("", rendered)}`
67137
67846
  });
67138
67847
 
67139
67848
  // packages/cleo/src/cli/commands/templates/install.ts
67140
- import { existsSync as existsSync16, mkdirSync as mkdirSync5, readFileSync as readFileSync17, writeFileSync as writeFileSync5 } from "node:fs";
67141
- import { dirname as dirname9, join as join31 } from "node:path";
67849
+ import { existsSync as existsSync17, mkdirSync as mkdirSync5, readFileSync as readFileSync17, writeFileSync as writeFileSync5 } from "node:fs";
67850
+ import { dirname as dirname9, join as join32 } from "node:path";
67142
67851
  import { getTemplateById as getTemplateById2 } from "@cleocode/core/templates/registry";
67143
67852
  var templatesInstallCommand;
67144
67853
  var init_install = __esm({
@@ -67192,7 +67901,7 @@ var init_install = __esm({
67192
67901
  let substituted;
67193
67902
  try {
67194
67903
  projectRoot = resolveProjectRoot7(args["project"]);
67195
- installPath = join31(projectRoot, entry.installPath);
67904
+ installPath = join32(projectRoot, entry.installPath);
67196
67905
  const source = readTemplateSource(entry);
67197
67906
  const sub = applySubstitution(entry, source);
67198
67907
  rendered = sub.rendered;
@@ -67205,7 +67914,7 @@ var init_install = __esm({
67205
67914
  process.exit(1 /* GENERAL_ERROR */);
67206
67915
  return;
67207
67916
  }
67208
- if (existsSync16(installPath)) {
67917
+ if (existsSync17(installPath)) {
67209
67918
  const current = readFileSync17(installPath, "utf8");
67210
67919
  if (current === rendered) {
67211
67920
  const noopResult = {
@@ -67354,8 +68063,8 @@ var init_show3 = __esm({
67354
68063
  });
67355
68064
 
67356
68065
  // packages/cleo/src/cli/commands/templates/upgrade.ts
67357
- import { existsSync as existsSync17, mkdirSync as mkdirSync6, readFileSync as readFileSync18, writeFileSync as writeFileSync6 } from "node:fs";
67358
- import { dirname as dirname10, join as join32 } from "node:path";
68066
+ import { existsSync as existsSync18, mkdirSync as mkdirSync6, readFileSync as readFileSync18, writeFileSync as writeFileSync6 } from "node:fs";
68067
+ import { dirname as dirname10, join as join33 } from "node:path";
67359
68068
  import { getTemplateById as getTemplateById4 } from "@cleocode/core/templates/registry";
67360
68069
  var templatesUpgradeCommand;
67361
68070
  var init_upgrade2 = __esm({
@@ -67417,7 +68126,7 @@ var init_upgrade2 = __esm({
67417
68126
  let rendered;
67418
68127
  try {
67419
68128
  projectRoot = resolveProjectRoot7(args["project"]);
67420
- installPath = join32(projectRoot, entry.installPath);
68129
+ installPath = join33(projectRoot, entry.installPath);
67421
68130
  const source = readTemplateSource(entry);
67422
68131
  rendered = applySubstitution(entry, source).rendered;
67423
68132
  } catch (err) {
@@ -67430,7 +68139,7 @@ var init_upgrade2 = __esm({
67430
68139
  }
67431
68140
  const previewOnly = args["diff"] === true;
67432
68141
  const accept = args["accept"] === true;
67433
- const current = existsSync17(installPath) ? readFileSync18(installPath, "utf8") : null;
68142
+ const current = existsSync18(installPath) ? readFileSync18(installPath, "utf8") : null;
67434
68143
  const diffBody = current === null ? "" : current === rendered ? "" : unifiedDiff(current, rendered);
67435
68144
  let outcome;
67436
68145
  let reason;
@@ -67781,7 +68490,7 @@ __export(token_exports, {
67781
68490
  tokenCommand: () => tokenCommand
67782
68491
  });
67783
68492
  import { readFileSync as readFileSync19 } from "node:fs";
67784
- import { getProjectRoot as getProjectRoot51, measureTokenExchange, recordTokenExchange as recordTokenExchange2 } from "@cleocode/core/internal";
68493
+ import { getProjectRoot as getProjectRoot53, measureTokenExchange, recordTokenExchange as recordTokenExchange2 } from "@cleocode/core/internal";
67785
68494
  function readPayload(args, textKey, fileKey) {
67786
68495
  const text = args[textKey];
67787
68496
  const file = args[fileKey];
@@ -67945,7 +68654,7 @@ var init_token = __esm({
67945
68654
  domain: args.domain,
67946
68655
  operation: args.operation
67947
68656
  };
67948
- const result = args.record ? await recordTokenExchange2(getProjectRoot51(), input2) : await measureTokenExchange(input2);
68657
+ const result = args.record ? await recordTokenExchange2(getProjectRoot53(), input2) : await measureTokenExchange(input2);
67949
68658
  cliOutput(result, {
67950
68659
  command: "token",
67951
68660
  operation: args.record ? "admin.token.record" : "token.estimate"
@@ -67980,8 +68689,8 @@ __export(transcript_exports, {
67980
68689
  transcriptCommand: () => transcriptCommand
67981
68690
  });
67982
68691
  import { homedir as homedir6 } from "node:os";
67983
- import { join as join33 } from "node:path";
67984
- import { getProjectRoot as getProjectRoot52 } from "@cleocode/core";
68692
+ import { join as join34 } from "node:path";
68693
+ import { getProjectRoot as getProjectRoot54 } from "@cleocode/core";
67985
68694
  import {
67986
68695
  parseDurationMs,
67987
68696
  pruneTranscripts,
@@ -68011,7 +68720,7 @@ var init_transcript = __esm({
68011
68720
  async run({ args }) {
68012
68721
  if (args.pending) {
68013
68722
  try {
68014
- const projectRoot = getProjectRoot52();
68723
+ const projectRoot = getProjectRoot54();
68015
68724
  const { scanPendingTranscripts } = await import("@cleocode/core/memory/transcript-scanner.js");
68016
68725
  const pending = await scanPendingTranscripts(projectRoot);
68017
68726
  cliOutput(
@@ -68034,7 +68743,7 @@ var init_transcript = __esm({
68034
68743
  }
68035
68744
  return;
68036
68745
  }
68037
- const projectsDir = args["projects-dir"] ?? join33(homedir6(), ".claude", "projects");
68746
+ const projectsDir = args["projects-dir"] ?? join34(homedir6(), ".claude", "projects");
68038
68747
  try {
68039
68748
  const result = await scanTranscripts(projectsDir);
68040
68749
  cliOutput(
@@ -68108,7 +68817,7 @@ var init_transcript = __esm({
68108
68817
  async run({ args }) {
68109
68818
  const tier = args.tier ?? "warm";
68110
68819
  const dryRun = args["dry-run"] ?? false;
68111
- const projectRoot = getProjectRoot52();
68820
+ const projectRoot = getProjectRoot54();
68112
68821
  try {
68113
68822
  const { extractTranscript } = await import("@cleocode/core/memory/transcript-extractor.js");
68114
68823
  const { findSessionTranscriptPath, listAllTranscripts } = await import("@cleocode/core/memory/transcript-scanner.js");
@@ -68220,7 +68929,7 @@ var init_transcript = __esm({
68220
68929
  const dryRun = args["dry-run"] ?? false;
68221
68930
  const olderThanHours = args["older-than-hours"] ? Number.parseInt(args["older-than-hours"], 10) : 24;
68222
68931
  const limit = args.limit ? Number.parseInt(args.limit, 10) : void 0;
68223
- const projectRoot = getProjectRoot52();
68932
+ const projectRoot = getProjectRoot54();
68224
68933
  try {
68225
68934
  const { extractTranscript } = await import("@cleocode/core/memory/transcript-extractor.js");
68226
68935
  const { listAllTranscripts } = await import("@cleocode/core/memory/transcript-scanner.js");
@@ -68340,7 +69049,7 @@ var init_transcript = __esm({
68340
69049
  process.exit(2);
68341
69050
  return;
68342
69051
  }
68343
- const projectsDir = args["projects-dir"] ?? join33(homedir6(), ".claude", "projects");
69052
+ const projectsDir = args["projects-dir"] ?? join34(homedir6(), ".claude", "projects");
68344
69053
  try {
68345
69054
  const pruneResult = await pruneTranscripts({
68346
69055
  olderThanMs,
@@ -68872,7 +69581,7 @@ var upgrade_exports = {};
68872
69581
  __export(upgrade_exports, {
68873
69582
  upgradeCommand: () => upgradeCommand
68874
69583
  });
68875
- import { resolve as resolve7 } from "node:path";
69584
+ import { resolve as resolve8 } from "node:path";
68876
69585
  import { CleoError as CleoError10, diagnoseUpgrade, runUpgrade as runUpgrade2, upgradeWorkflows as upgradeWorkflows2 } from "@cleocode/core/internal";
68877
69586
  var workflowsSubcommand, upgradeCommand;
68878
69587
  var init_upgrade3 = __esm({
@@ -68912,7 +69621,7 @@ var init_upgrade3 = __esm({
68912
69621
  const dryRun = args["dry-run"] === true || args.check === true;
68913
69622
  const force = args.force === true && !dryRun;
68914
69623
  const result = await upgradeWorkflows2({
68915
- projectRoot: resolve7(process.cwd()),
69624
+ projectRoot: resolve8(process.cwd()),
68916
69625
  templatesDir: getWorkflowTemplatesDir2(),
68917
69626
  dryRun,
68918
69627
  force
@@ -69173,15 +69882,15 @@ __export(web_exports, {
69173
69882
  });
69174
69883
  import { execFileSync as execFileSync4, spawn as spawn3 } from "node:child_process";
69175
69884
  import { mkdir as mkdir4, open, readFile as readFile7, rm, stat as stat2, writeFile as writeFile3 } from "node:fs/promises";
69176
- import { join as join34 } from "node:path";
69885
+ import { join as join35 } from "node:path";
69177
69886
  import { CleoError as CleoError11, formatError as formatError5, getCleoHome as getCleoHome5 } from "@cleocode/core";
69178
69887
  function getWebPaths() {
69179
69888
  const cleoHome = getCleoHome5();
69180
69889
  return {
69181
- pidFile: join34(cleoHome, "web-server.pid"),
69182
- configFile: join34(cleoHome, "web-server.json"),
69183
- logDir: join34(cleoHome, "logs"),
69184
- logFile: join34(cleoHome, "logs", "web-server.log")
69890
+ pidFile: join35(cleoHome, "web-server.pid"),
69891
+ configFile: join35(cleoHome, "web-server.json"),
69892
+ logDir: join35(cleoHome, "logs"),
69893
+ logFile: join35(cleoHome, "logs", "web-server.log")
69185
69894
  };
69186
69895
  }
69187
69896
  function isProcessRunning(pid) {
@@ -69220,7 +69929,7 @@ async function startWebServer(port, host) {
69220
69929
  throw new CleoError11(1 /* GENERAL_ERROR */, `Server already running (PID: ${status.pid})`);
69221
69930
  }
69222
69931
  const projectRoot = process.env["CLEO_ROOT"] ?? process.cwd();
69223
- const studioDir = process.env["CLEO_STUDIO_DIR"] ?? join34(projectRoot, "packages", "studio", "build");
69932
+ const studioDir = process.env["CLEO_STUDIO_DIR"] ?? join35(projectRoot, "packages", "studio", "build");
69224
69933
  await mkdir4(logDir, { recursive: true });
69225
69934
  await writeFile3(
69226
69935
  configFile,
@@ -69230,7 +69939,7 @@ async function startWebServer(port, host) {
69230
69939
  startedAt: (/* @__PURE__ */ new Date()).toISOString()
69231
69940
  })
69232
69941
  );
69233
- const webIndexPath = join34(studioDir, "index.js");
69942
+ const webIndexPath = join35(studioDir, "index.js");
69234
69943
  try {
69235
69944
  await stat2(webIndexPath);
69236
69945
  } catch {
@@ -69278,7 +69987,7 @@ Logs: ${logFile}`
69278
69987
  }
69279
69988
  } catch {
69280
69989
  }
69281
- await new Promise((resolve8) => setTimeout(resolve8, 500));
69990
+ await new Promise((resolve9) => setTimeout(resolve9, 500));
69282
69991
  }
69283
69992
  if (!started) {
69284
69993
  try {
@@ -69355,7 +70064,7 @@ var init_web = __esm({
69355
70064
  }
69356
70065
  for (let i = 0; i < 60; i++) {
69357
70066
  if (!isProcessRunning(status.pid)) break;
69358
- await new Promise((resolve8) => setTimeout(resolve8, 500));
70067
+ await new Promise((resolve9) => setTimeout(resolve9, 500));
69359
70068
  }
69360
70069
  if (isProcessRunning(status.pid)) {
69361
70070
  try {
@@ -69407,7 +70116,7 @@ var init_web = __esm({
69407
70116
  }
69408
70117
  for (let i = 0; i < 60; i++) {
69409
70118
  if (!isProcessRunning(status.pid)) break;
69410
- await new Promise((resolve8) => setTimeout(resolve8, 500));
70119
+ await new Promise((resolve9) => setTimeout(resolve9, 500));
69411
70120
  }
69412
70121
  if (isProcessRunning(status.pid)) {
69413
70122
  try {
@@ -69503,14 +70212,14 @@ __export(worktree_exports, {
69503
70212
  worktreeCommand: () => worktreeCommand
69504
70213
  });
69505
70214
  import readline4 from "node:readline";
69506
- import { getProjectRoot as getProjectRoot53, listWorktrees as listWorktrees2 } from "@cleocode/core/internal";
70215
+ import { getProjectRoot as getProjectRoot55, listWorktrees as listWorktrees2 } from "@cleocode/core/internal";
69507
70216
  async function promptYesNo2(question) {
69508
- return new Promise((resolve8) => {
70217
+ return new Promise((resolve9) => {
69509
70218
  const rl = readline4.createInterface({ input: process.stdin, output: process.stdout });
69510
70219
  rl.question(`${question} [y/N]: `, (answer) => {
69511
70220
  rl.close();
69512
70221
  const trimmed = answer.trim().toLowerCase();
69513
- resolve8(trimmed === "y" || trimmed === "yes");
70222
+ resolve9(trimmed === "y" || trimmed === "yes");
69514
70223
  });
69515
70224
  });
69516
70225
  }
@@ -69608,7 +70317,7 @@ var init_worktree3 = __esm({
69608
70317
  const staleDays = staleDaysRaw !== void 0 ? Number.parseInt(staleDaysRaw, 10) : void 0;
69609
70318
  const idleDaysRaw = typeof args["idle-days"] === "string" ? args["idle-days"] : void 0;
69610
70319
  const idleDays = idleDaysRaw !== void 0 ? Number.parseInt(idleDaysRaw, 10) : void 0;
69611
- const projectRoot = getProjectRoot53();
70320
+ const projectRoot = getProjectRoot55();
69612
70321
  const listResult = await listWorktrees2({
69613
70322
  projectRoot,
69614
70323
  ...staleDays !== void 0 && !Number.isNaN(staleDays) ? { staleDays } : {}
@@ -69787,6 +70496,11 @@ var init_worktree3 = __esm({
69787
70496
  actor: {
69788
70497
  type: "string",
69789
70498
  description: "Override actor name written to the audit log."
70499
+ },
70500
+ recover: {
70501
+ type: "boolean",
70502
+ description: "After adopting, recover a partial ETIMEDOUT worktree by running pnpm install and clearing stale git locks.",
70503
+ default: false
69790
70504
  }
69791
70505
  },
69792
70506
  async run({ args }) {
@@ -69808,7 +70522,8 @@ var init_worktree3 = __esm({
69808
70522
  worktreePath: rawPath,
69809
70523
  ...source !== void 0 ? { source } : {},
69810
70524
  ...rawTaskId !== void 0 ? { taskId: rawTaskId } : {},
69811
- ...rawActor !== void 0 ? { actor: rawActor } : {}
70525
+ ...rawActor !== void 0 ? { actor: rawActor } : {},
70526
+ recover: args["recover"] === true
69812
70527
  },
69813
70528
  { command: "worktree-adopt", operation: "worktree.adopt" }
69814
70529
  );
@@ -69844,7 +70559,7 @@ init_dist();
69844
70559
  init_field_context();
69845
70560
  init_format_context();
69846
70561
  import { readFileSync as readFileSync20 } from "node:fs";
69847
- import { dirname as dirname11, join as join36 } from "node:path";
70562
+ import { dirname as dirname11, join as join37 } from "node:path";
69848
70563
  import { fileURLToPath as fileURLToPath7 } from "node:url";
69849
70564
 
69850
70565
  // packages/cleo/src/cli/generated/command-manifest.ts
@@ -70161,6 +70876,12 @@ var COMMAND_MANIFEST = [
70161
70876
  description: "Probe every registered project (nexus.db) for DB + config health",
70162
70877
  load: async () => (await Promise.resolve().then(() => (init_doctor_projects(), doctor_projects_exports))).doctorProjectsCommand
70163
70878
  },
70879
+ {
70880
+ exportName: "doctorReleaseReadinessCommand",
70881
+ name: "release-readiness",
70882
+ description: "Pre-flight release readiness check \u2014 lint matrix + changelog + changeset + npm OIDC + tag-trigger sanity (T10458)",
70883
+ load: async () => (await Promise.resolve().then(() => (init_doctor_release_readiness(), doctor_release_readiness_exports))).doctorReleaseReadinessCommand
70884
+ },
70164
70885
  {
70165
70886
  exportName: "doctorCommand",
70166
70887
  name: "doctor",
@@ -70245,6 +70966,12 @@ var COMMAND_MANIFEST = [
70245
70966
  description: "Completion timeline and productivity analytics",
70246
70967
  load: async () => (await Promise.resolve().then(() => (init_history(), history_exports))).historyCommand
70247
70968
  },
70969
+ {
70970
+ exportName: "hygieneCommand",
70971
+ name: "hygiene",
70972
+ description: "Run spawn-readiness hygiene checks",
70973
+ load: async () => (await Promise.resolve().then(() => (init_hygiene(), hygiene_exports))).hygieneCommand
70974
+ },
70248
70975
  {
70249
70976
  exportName: "importTasksCommand",
70250
70977
  name: "import-tasks",
@@ -70290,7 +71017,7 @@ var COMMAND_MANIFEST = [
70290
71017
  {
70291
71018
  exportName: "labelsCommand",
70292
71019
  name: "labels",
70293
- description: "List all labels with counts or show tasks with specific label",
71020
+ description: "List all labels (no args), or show tasks for a label (cleo labels <name>)",
70294
71021
  load: async () => (await Promise.resolve().then(() => (init_labels(), labels_exports))).labelsCommand
70295
71022
  },
70296
71023
  {
@@ -70858,14 +71585,14 @@ function lazyCommand(meta, loader2) {
70858
71585
  init_did_you_mean();
70859
71586
 
70860
71587
  // packages/cleo/src/cli/lib/first-run-detection.ts
70861
- import { existsSync as existsSync18 } from "node:fs";
70862
- import { join as join35 } from "node:path";
71588
+ import { existsSync as existsSync19 } from "node:fs";
71589
+ import { join as join36 } from "node:path";
70863
71590
  async function detectFirstRun() {
70864
71591
  const envKey = process.env["ANTHROPIC_API_KEY"];
70865
71592
  if (typeof envKey === "string" && envKey.length > 0) return false;
70866
71593
  const { getCleoPlatformPaths } = await import("@cleocode/paths");
70867
- const configPath = join35(getCleoPlatformPaths().config, "config.json");
70868
- if (existsSync18(configPath)) return false;
71594
+ const configPath = join36(getCleoPlatformPaths().config, "config.json");
71595
+ if (existsSync19(configPath)) return false;
70869
71596
  try {
70870
71597
  const { getCredentialPool } = await import("@cleocode/core/llm/credential-pool.js");
70871
71598
  const pool = getCredentialPool();
@@ -70876,7 +71603,7 @@ async function detectFirstRun() {
70876
71603
  return true;
70877
71604
  }
70878
71605
  function waitForEnterOrTimeout(timeoutMs) {
70879
- return new Promise((resolve8) => {
71606
+ return new Promise((resolve9) => {
70880
71607
  let resolved = false;
70881
71608
  const finish = () => {
70882
71609
  if (resolved) return;
@@ -70888,7 +71615,7 @@ function waitForEnterOrTimeout(timeoutMs) {
70888
71615
  process.stdin.pause();
70889
71616
  } catch {
70890
71617
  }
70891
- resolve8();
71618
+ resolve9();
70892
71619
  };
70893
71620
  const onData = (chunk) => {
70894
71621
  const s = typeof chunk === "string" ? chunk : chunk.toString("utf8");
@@ -70984,7 +71711,7 @@ Or via NodeSource: https://github.com/nodesource/distributions
70984
71711
  }
70985
71712
  }
70986
71713
  function getPackageVersion() {
70987
- const pkgPath = join36(dirname11(fileURLToPath7(import.meta.url)), "../../package.json");
71714
+ const pkgPath = join37(dirname11(fileURLToPath7(import.meta.url)), "../../package.json");
70988
71715
  const pkg = JSON.parse(readFileSync20(pkgPath, "utf-8"));
70989
71716
  return pkg.version;
70990
71717
  }
@@ -71160,7 +71887,7 @@ async function runStartupMaintenance() {
71160
71887
  detectAndRemoveStrayProjectNexus,
71161
71888
  getGlobalSalt,
71162
71889
  getLogger: getLogger21,
71163
- getProjectRoot: getProjectRoot54,
71890
+ getProjectRoot: getProjectRoot56,
71164
71891
  isCleanupMarkerSet,
71165
71892
  migrateSignaldockToConduit,
71166
71893
  needsSignaldockToConduitMigration,
@@ -71169,7 +71896,7 @@ async function runStartupMaintenance() {
71169
71896
  } = await import("@cleocode/core/internal");
71170
71897
  let projectRootForCleanup = "";
71171
71898
  try {
71172
- projectRootForCleanup = getProjectRoot54();
71899
+ projectRootForCleanup = getProjectRoot56();
71173
71900
  } catch {
71174
71901
  }
71175
71902
  if (!isCleanupMarkerSet(CLI_VERSION, projectRootForCleanup)) {
@@ -71189,7 +71916,7 @@ async function runStartupMaintenance() {
71189
71916
  const isInitInvocation = process.argv.slice(2).some((a) => a === "init");
71190
71917
  if (!isInitInvocation) {
71191
71918
  try {
71192
- const _projectRootForMigration = getProjectRoot54();
71919
+ const _projectRootForMigration = getProjectRoot56();
71193
71920
  if (needsSignaldockToConduitMigration(_projectRootForMigration)) {
71194
71921
  const migrationResult = migrateSignaldockToConduit(_projectRootForMigration);
71195
71922
  if (migrationResult.status === "failed") {