@cleocode/cleo 2026.5.78 → 2026.5.79

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
@@ -2573,6 +2573,192 @@ var init_peer = __esm({
2573
2573
  }
2574
2574
  });
2575
2575
 
2576
+ // packages/contracts/src/release/plan.ts
2577
+ import { z as z4 } from "zod";
2578
+ var RELEASE_CHANNEL, RELEASE_SCHEME, RELEASE_KIND, RELEASE_STATUS, GATE_STATUS, GATE_NAME, PLATFORM_TUPLE, PUBLISHER, TASK_KIND, IMPACT, RESOLVED_SOURCE, ReleaseChannelSchema, ReleaseSchemeSchema, ReleaseKindSchema, ReleaseStatusSchema, GateStatusSchema, GateNameSchema, PlatformTupleSchema, PublisherSchema, TaskKindSchema, ImpactSchema, ResolvedSourceSchema, Iso8601, NonEmptyString, ReleasePlanTaskSchema, ReleaseGateSchema, ReleasePlatformMatrixEntrySchema, ReleasePreflightSummarySchema, ReleasePlanChangelogSchema, ReleasePlanMetaSchema, ReleasePlanSchema;
2579
+ var init_plan = __esm({
2580
+ "packages/contracts/src/release/plan.ts"() {
2581
+ "use strict";
2582
+ RELEASE_CHANNEL = ["latest", "beta", "alpha", "rc"];
2583
+ RELEASE_SCHEME = ["calver", "semver", "calver-suffix"];
2584
+ RELEASE_KIND = ["regular", "hotfix", "prerelease"];
2585
+ RELEASE_STATUS = [
2586
+ "planned",
2587
+ "pr-opened",
2588
+ "pr-merged",
2589
+ "published",
2590
+ "reconciled",
2591
+ "rolled_back",
2592
+ "failed",
2593
+ "cancelled"
2594
+ ];
2595
+ GATE_STATUS = ["passed", "failed", "skipped", "unresolved"];
2596
+ GATE_NAME = ["test", "build", "lint", "typecheck", "audit", "security-scan"];
2597
+ PLATFORM_TUPLE = [
2598
+ "linux-x64",
2599
+ "linux-arm64",
2600
+ "macos-x64",
2601
+ "macos-arm64",
2602
+ "windows-x64",
2603
+ "any"
2604
+ ];
2605
+ PUBLISHER = ["npm", "cargo", "docker", "pypi", "github-release", "binary"];
2606
+ TASK_KIND = [
2607
+ "feat",
2608
+ "fix",
2609
+ "chore",
2610
+ "docs",
2611
+ "refactor",
2612
+ "test",
2613
+ "perf",
2614
+ "revert",
2615
+ "breaking",
2616
+ "hotfix"
2617
+ ];
2618
+ IMPACT = ["major", "minor", "patch"];
2619
+ RESOLVED_SOURCE = ["project-context", "language-default", "legacy-alias"];
2620
+ ReleaseChannelSchema = z4.enum(RELEASE_CHANNEL);
2621
+ ReleaseSchemeSchema = z4.enum(RELEASE_SCHEME);
2622
+ ReleaseKindSchema = z4.enum(RELEASE_KIND);
2623
+ ReleaseStatusSchema = z4.enum(RELEASE_STATUS);
2624
+ GateStatusSchema = z4.enum(GATE_STATUS);
2625
+ GateNameSchema = z4.enum(GATE_NAME);
2626
+ PlatformTupleSchema = z4.enum(PLATFORM_TUPLE);
2627
+ PublisherSchema = z4.enum(PUBLISHER);
2628
+ TaskKindSchema = z4.enum(TASK_KIND);
2629
+ ImpactSchema = z4.enum(IMPACT);
2630
+ ResolvedSourceSchema = z4.enum(RESOLVED_SOURCE);
2631
+ Iso8601 = z4.iso.datetime({ offset: true });
2632
+ NonEmptyString = z4.string().min(1);
2633
+ ReleasePlanTaskSchema = z4.object({
2634
+ /** Task ID (e.g. "T10001"). Format intentionally loose so historical IDs validate. */
2635
+ id: NonEmptyString,
2636
+ /** Conventional-commit-aligned task classification. */
2637
+ kind: TaskKindSchema,
2638
+ /** SemVer impact classification. */
2639
+ impact: ImpactSchema,
2640
+ /** Human-readable changelog line for this task. */
2641
+ userFacingSummary: z4.string(),
2642
+ /**
2643
+ * ADR-051 evidence atoms attesting the task's gate results. Format is
2644
+ * `kind:value` (e.g. `commit:abc123`, `test-run:vitest.json`). The contract
2645
+ * accepts empty arrays so legacy plans validate; `cleo release plan`
2646
+ * enforces non-empty via R-301.
2647
+ */
2648
+ evidenceAtoms: z4.array(NonEmptyString),
2649
+ /** IVTR phase at plan time — informational only per R-316. */
2650
+ ivtrPhaseAtPlan: z4.string().optional(),
2651
+ /** Epic this task rolls up to, locked at plan time per R-303. */
2652
+ epicAncestor: NonEmptyString
2653
+ });
2654
+ ReleaseGateSchema = z4.object({
2655
+ /** Canonical gate name. */
2656
+ name: GateNameSchema,
2657
+ /** ADR-051 atom string identifying the resolved tool (e.g. `tool:test`). */
2658
+ atom: NonEmptyString,
2659
+ /** Gate execution status at plan time. */
2660
+ status: GateStatusSchema,
2661
+ /** ISO-8601 timestamp the gate was last verified. */
2662
+ lastVerifiedAt: Iso8601,
2663
+ /** Resolved shell command (e.g. `pnpm run test`). Optional for unresolved gates. */
2664
+ resolvedCommand: z4.string().optional(),
2665
+ /** Provenance of the resolved command. Optional for unresolved gates. */
2666
+ resolvedSource: ResolvedSourceSchema.optional()
2667
+ });
2668
+ ReleasePlatformMatrixEntrySchema = z4.object({
2669
+ /** Target platform tuple. */
2670
+ platform: PlatformTupleSchema,
2671
+ /** Distribution backend. */
2672
+ publisher: PublisherSchema,
2673
+ /** Package identifier on the target backend (e.g. `@cleocode/cleo`). */
2674
+ package: NonEmptyString,
2675
+ /** Whether to run the GHA smoke job for this matrix entry. */
2676
+ smoke: z4.boolean().default(true).optional()
2677
+ });
2678
+ ReleasePreflightSummarySchema = z4.object({
2679
+ /** True if esbuild externals are out of sync with package.json. */
2680
+ esbuildExternalsDrift: z4.boolean(),
2681
+ /** True if `pnpm-lock.yaml` diverges from the workspace manifest. */
2682
+ lockfileDrift: z4.boolean(),
2683
+ /** True if all epic children are in terminal lifecycle states. */
2684
+ epicCompletenessClean: z4.boolean(),
2685
+ /** True if no task appears in multiple in-flight release plans. */
2686
+ doubleListingClean: z4.boolean(),
2687
+ /** Non-fatal preflight warnings (e.g. unresolved tools per R-024). */
2688
+ preflightWarnings: z4.array(z4.string()).default([]).optional()
2689
+ });
2690
+ ReleasePlanChangelogSchema = z4.object({
2691
+ /** `kind=feat` tasks. */
2692
+ features: z4.array(NonEmptyString).default([]),
2693
+ /** `kind=fix` or `kind=hotfix` tasks. */
2694
+ fixes: z4.array(NonEmptyString).default([]),
2695
+ /** `kind=chore`, `docs`, `refactor`, `test`, `perf` tasks. */
2696
+ chores: z4.array(NonEmptyString).default([]),
2697
+ /** `kind=breaking` or `kind=revert` tasks. */
2698
+ breaking: z4.array(NonEmptyString).default([])
2699
+ });
2700
+ ReleasePlanMetaSchema = z4.object({
2701
+ /** True if this is the project's first ever release. */
2702
+ firstEverRelease: z4.boolean().optional(),
2703
+ /** Canonical tool names that could not be resolved at plan time. */
2704
+ unresolvedTools: z4.array(z4.string()).optional(),
2705
+ /** Project archetype detected at plan time. */
2706
+ archetype: z4.string().optional()
2707
+ }).catchall(z4.unknown());
2708
+ ReleasePlanSchema = z4.object({
2709
+ /** Schema URL for this plan version. */
2710
+ $schema: z4.string().optional(),
2711
+ /** Requested version string (e.g. "v2026.6.0"). Includes the leading `v`. */
2712
+ version: NonEmptyString,
2713
+ /** Resolved version string after suffix application (e.g. "v2026.6.0.2"). */
2714
+ resolvedVersion: NonEmptyString,
2715
+ /** True if a `calver-suffix` was applied to disambiguate a same-day hotfix. */
2716
+ suffixApplied: z4.boolean(),
2717
+ /** Versioning scheme governing `version` / `resolvedVersion`. */
2718
+ scheme: ReleaseSchemeSchema,
2719
+ /** npm dist-tag channel for this release. */
2720
+ channel: ReleaseChannelSchema,
2721
+ /** Epic ID this release ships. */
2722
+ epicId: NonEmptyString,
2723
+ /** Release-kind classification. */
2724
+ releaseKind: ReleaseKindSchema,
2725
+ /** ISO-8601 timestamp the plan was written. */
2726
+ createdAt: Iso8601,
2727
+ /** Identifier of the actor that wrote the plan (agent name or operator). */
2728
+ createdBy: NonEmptyString,
2729
+ /**
2730
+ * Version of the previous release on the same channel. MUST be `null` only
2731
+ * for first-ever releases (R-300, enforced at the verb layer).
2732
+ */
2733
+ previousVersion: z4.string().nullable(),
2734
+ /** Git tag of the previous release (typically `previousVersion` prefixed). */
2735
+ previousTag: z4.string().nullable(),
2736
+ /** ISO-8601 timestamp the previous release was published. */
2737
+ previousShippedAt: Iso8601.nullable(),
2738
+ /** Tasks rolled into this release. */
2739
+ tasks: z4.array(ReleasePlanTaskSchema),
2740
+ /** Bucketed changelog. */
2741
+ changelog: ReleasePlanChangelogSchema,
2742
+ /** Per-gate verification status. */
2743
+ gates: z4.array(ReleaseGateSchema),
2744
+ /** Platform / publisher matrix. */
2745
+ platformMatrix: z4.array(ReleasePlatformMatrixEntrySchema),
2746
+ /** Preflight summary from `cleo release plan`. */
2747
+ preflightSummary: ReleasePreflightSummarySchema,
2748
+ /** URL of the GHA workflow run (populated by `release-prepare.yml`). */
2749
+ workflowRunUrl: z4.string().nullable(),
2750
+ /** URL of the bump PR (populated by `cleo release open`). */
2751
+ prUrl: z4.string().nullable(),
2752
+ /** Merge commit SHA on `main` (populated by `release-publish.yml`). */
2753
+ mergeCommitSha: z4.string().nullable(),
2754
+ /** Current FSM state per R-302. */
2755
+ status: ReleaseStatusSchema,
2756
+ /** Informational / forward-compat metadata. */
2757
+ meta: ReleasePlanMetaSchema.optional()
2758
+ });
2759
+ }
2760
+ });
2761
+
2576
2762
  // packages/contracts/src/session.ts
2577
2763
  var init_session2 = __esm({
2578
2764
  "packages/contracts/src/session.ts"() {
@@ -2581,52 +2767,52 @@ var init_session2 = __esm({
2581
2767
  });
2582
2768
 
2583
2769
  // packages/contracts/src/session-journal.ts
2584
- import { z as z4 } from "zod";
2770
+ import { z as z5 } from "zod";
2585
2771
  var SESSION_JOURNAL_SCHEMA_VERSION, sessionJournalDoctorSummarySchema, sessionJournalDebriefSummarySchema, sessionJournalEntrySchema;
2586
2772
  var init_session_journal = __esm({
2587
2773
  "packages/contracts/src/session-journal.ts"() {
2588
2774
  "use strict";
2589
2775
  SESSION_JOURNAL_SCHEMA_VERSION = "1.0";
2590
- sessionJournalDoctorSummarySchema = z4.object({
2776
+ sessionJournalDoctorSummarySchema = z5.object({
2591
2777
  /** `true` when zero noise patterns were detected. */
2592
- isClean: z4.boolean(),
2778
+ isClean: z5.boolean(),
2593
2779
  /** Total number of noise findings across all patterns. */
2594
- findingsCount: z4.number().int().nonnegative(),
2780
+ findingsCount: z5.number().int().nonnegative(),
2595
2781
  /** Pattern names that were detected (empty when isClean). */
2596
- patterns: z4.array(z4.string()),
2782
+ patterns: z5.array(z5.string()),
2597
2783
  /** Total brain entries scanned. `0` = empty or unavailable. */
2598
- totalScanned: z4.number().int().nonnegative()
2784
+ totalScanned: z5.number().int().nonnegative()
2599
2785
  });
2600
- sessionJournalDebriefSummarySchema = z4.object({
2786
+ sessionJournalDebriefSummarySchema = z5.object({
2601
2787
  /** First 200 characters of the session end note (if provided). */
2602
- noteExcerpt: z4.string().max(200).optional(),
2788
+ noteExcerpt: z5.string().max(200).optional(),
2603
2789
  /** Number of tasks completed during the session. */
2604
- tasksCompletedCount: z4.number().int().nonnegative(),
2790
+ tasksCompletedCount: z5.number().int().nonnegative(),
2605
2791
  /** Up to 5 task IDs (not titles) that were the focus of the session. */
2606
- tasksFocused: z4.array(z4.string()).max(5).optional()
2792
+ tasksFocused: z5.array(z5.string()).max(5).optional()
2607
2793
  });
2608
- sessionJournalEntrySchema = z4.object({
2794
+ sessionJournalEntrySchema = z5.object({
2609
2795
  // Identity
2610
2796
  /** Schema version for forward-compatibility. Always `'1.0'` in this release. */
2611
- schemaVersion: z4.literal(SESSION_JOURNAL_SCHEMA_VERSION),
2797
+ schemaVersion: z5.literal(SESSION_JOURNAL_SCHEMA_VERSION),
2612
2798
  /** ISO 8601 timestamp when the entry was written. */
2613
- timestamp: z4.string(),
2799
+ timestamp: z5.string(),
2614
2800
  /** CLEO session ID (e.g. `ses_20260424055456_ede571`). */
2615
- sessionId: z4.string(),
2801
+ sessionId: z5.string(),
2616
2802
  /** Event type that triggered this journal entry. */
2617
- eventType: z4.enum(["session_start", "session_end", "observation", "decision", "error"]),
2803
+ eventType: z5.enum(["session_start", "session_end", "observation", "decision", "error"]),
2618
2804
  // Session metadata (set on session_start / session_end)
2619
2805
  /** Agent identifier (e.g. `cleo-prime`, `claude-code`). */
2620
- agentIdentifier: z4.string().optional(),
2806
+ agentIdentifier: z5.string().optional(),
2621
2807
  /** Provider adapter ID active for this session. */
2622
- providerId: z4.string().optional(),
2808
+ providerId: z5.string().optional(),
2623
2809
  /** Session scope string (e.g. `'global'` or `'epic:T1263'`). */
2624
- scope: z4.string().optional(),
2810
+ scope: z5.string().optional(),
2625
2811
  // Session-end fields
2626
2812
  /** Duration of the session in seconds (session_end only). */
2627
- duration: z4.number().int().nonnegative().optional(),
2813
+ duration: z5.number().int().nonnegative().optional(),
2628
2814
  /** Task IDs (not titles) completed during the session. */
2629
- tasksCompleted: z4.array(z4.string()).optional(),
2815
+ tasksCompleted: z5.array(z5.string()).optional(),
2630
2816
  // Doctor summary (T1262 absorbed)
2631
2817
  /** Compact result of `scanBrainNoise` run at session-end. */
2632
2818
  doctorSummary: sessionJournalDoctorSummarySchema.optional(),
@@ -2635,7 +2821,7 @@ var init_session_journal = __esm({
2635
2821
  debriefSummary: sessionJournalDebriefSummarySchema.optional(),
2636
2822
  // Optional hash chain
2637
2823
  /** SHA-256 hex of the previous entry's raw JSON string (for integrity chain). */
2638
- prevEntryHash: z4.string().optional()
2824
+ prevEntryHash: z5.string().optional()
2639
2825
  });
2640
2826
  }
2641
2827
  });
@@ -2681,52 +2867,52 @@ var init_task = __esm({
2681
2867
  });
2682
2868
 
2683
2869
  // packages/contracts/src/task-evidence.ts
2684
- import { z as z5 } from "zod";
2870
+ import { z as z6 } from "zod";
2685
2871
  var fileEvidenceSchema, logEvidenceSchema, screenshotEvidenceSchema, testOutputEvidenceSchema, commandOutputEvidenceSchema, taskEvidenceSchema;
2686
2872
  var init_task_evidence = __esm({
2687
2873
  "packages/contracts/src/task-evidence.ts"() {
2688
2874
  "use strict";
2689
- fileEvidenceSchema = z5.object({
2690
- kind: z5.literal("file"),
2691
- sha256: z5.string().length(64),
2692
- timestamp: z5.string().datetime(),
2693
- path: z5.string().min(1),
2694
- mime: z5.string().optional(),
2695
- description: z5.string().optional()
2696
- });
2697
- logEvidenceSchema = z5.object({
2698
- kind: z5.literal("log"),
2699
- sha256: z5.string().length(64),
2700
- timestamp: z5.string().datetime(),
2701
- source: z5.string().min(1),
2702
- description: z5.string().optional()
2703
- });
2704
- screenshotEvidenceSchema = z5.object({
2705
- kind: z5.literal("screenshot"),
2706
- sha256: z5.string().length(64),
2707
- timestamp: z5.string().datetime(),
2708
- mime: z5.enum(["image/png", "image/jpeg", "image/webp"]).optional(),
2709
- description: z5.string().optional()
2710
- });
2711
- testOutputEvidenceSchema = z5.object({
2712
- kind: z5.literal("test-output"),
2713
- sha256: z5.string().length(64),
2714
- timestamp: z5.string().datetime(),
2715
- passed: z5.number().int().nonnegative(),
2716
- failed: z5.number().int().nonnegative(),
2717
- skipped: z5.number().int().nonnegative(),
2718
- exitCode: z5.number().int(),
2719
- description: z5.string().optional()
2720
- });
2721
- commandOutputEvidenceSchema = z5.object({
2722
- kind: z5.literal("command-output"),
2723
- sha256: z5.string().length(64),
2724
- timestamp: z5.string().datetime(),
2725
- cmd: z5.string().min(1),
2726
- exitCode: z5.number().int(),
2727
- description: z5.string().optional()
2728
- });
2729
- taskEvidenceSchema = z5.discriminatedUnion("kind", [
2875
+ fileEvidenceSchema = z6.object({
2876
+ kind: z6.literal("file"),
2877
+ sha256: z6.string().length(64),
2878
+ timestamp: z6.string().datetime(),
2879
+ path: z6.string().min(1),
2880
+ mime: z6.string().optional(),
2881
+ description: z6.string().optional()
2882
+ });
2883
+ logEvidenceSchema = z6.object({
2884
+ kind: z6.literal("log"),
2885
+ sha256: z6.string().length(64),
2886
+ timestamp: z6.string().datetime(),
2887
+ source: z6.string().min(1),
2888
+ description: z6.string().optional()
2889
+ });
2890
+ screenshotEvidenceSchema = z6.object({
2891
+ kind: z6.literal("screenshot"),
2892
+ sha256: z6.string().length(64),
2893
+ timestamp: z6.string().datetime(),
2894
+ mime: z6.enum(["image/png", "image/jpeg", "image/webp"]).optional(),
2895
+ description: z6.string().optional()
2896
+ });
2897
+ testOutputEvidenceSchema = z6.object({
2898
+ kind: z6.literal("test-output"),
2899
+ sha256: z6.string().length(64),
2900
+ timestamp: z6.string().datetime(),
2901
+ passed: z6.number().int().nonnegative(),
2902
+ failed: z6.number().int().nonnegative(),
2903
+ skipped: z6.number().int().nonnegative(),
2904
+ exitCode: z6.number().int(),
2905
+ description: z6.string().optional()
2906
+ });
2907
+ commandOutputEvidenceSchema = z6.object({
2908
+ kind: z6.literal("command-output"),
2909
+ sha256: z6.string().length(64),
2910
+ timestamp: z6.string().datetime(),
2911
+ cmd: z6.string().min(1),
2912
+ exitCode: z6.number().int(),
2913
+ description: z6.string().optional()
2914
+ });
2915
+ taskEvidenceSchema = z6.discriminatedUnion("kind", [
2730
2916
  fileEvidenceSchema,
2731
2917
  logEvidenceSchema,
2732
2918
  screenshotEvidenceSchema,
@@ -2737,12 +2923,12 @@ var init_task_evidence = __esm({
2737
2923
  });
2738
2924
 
2739
2925
  // packages/contracts/src/tasks/archive.ts
2740
- import { z as z6 } from "zod";
2926
+ import { z as z7 } from "zod";
2741
2927
  var ArchiveReason, ARCHIVE_REASON_VALUES;
2742
2928
  var init_archive = __esm({
2743
2929
  "packages/contracts/src/tasks/archive.ts"() {
2744
2930
  "use strict";
2745
- ArchiveReason = z6.enum([
2931
+ ArchiveReason = z7.enum([
2746
2932
  "verified",
2747
2933
  "reconciled",
2748
2934
  "superseded",
@@ -2773,6 +2959,7 @@ var init_src2 = __esm({
2773
2959
  init_nexus_scope_map();
2774
2960
  init_params();
2775
2961
  init_peer();
2962
+ init_plan();
2776
2963
  init_session2();
2777
2964
  init_session_journal();
2778
2965
  init_status_registry();
@@ -8907,32 +9094,10 @@ var init_registry = __esm({
8907
9094
  requiredParams: [],
8908
9095
  params: []
8909
9096
  },
8910
- {
8911
- gateway: "mutate",
8912
- domain: "pipeline",
8913
- operation: "release.ship",
8914
- description: "Ship a release: validate gates \u2192 write CHANGELOG \u2192 git commit/tag/push \u2192 record provenance; absorbs prepare/changelog/commit/tag/push/gates.run via step param",
8915
- tier: 1,
8916
- idempotent: false,
8917
- sessionRequired: false,
8918
- requiredParams: ["version", "epicId"],
8919
- params: [
8920
- {
8921
- name: "version",
8922
- type: "string",
8923
- required: true,
8924
- description: "version parameter",
8925
- cli: { positional: true }
8926
- },
8927
- {
8928
- name: "epicId",
8929
- type: "string",
8930
- required: true,
8931
- description: "epicId parameter",
8932
- cli: { positional: true }
8933
- }
8934
- ]
8935
- },
9097
+ // pipeline.release.ship removed in T9540 (Phase 6 of T9499) — the legacy
9098
+ // `releaseShip` monolith was deleted. `cleo release ship` is still a
9099
+ // deprecated CLI alias (R-420) but now forwards to `release.plan` +
9100
+ // `release.open` (handled by the release domain), not the pipeline domain.
8936
9101
  {
8937
9102
  gateway: "mutate",
8938
9103
  domain: "pipeline",
@@ -11808,9 +11973,9 @@ var init_registry = __esm({
11808
11973
  gateway: "mutate",
11809
11974
  domain: "orchestrate",
11810
11975
  operation: "worktree.complete",
11811
- description: "orchestrate.worktree.complete (mutate) \u2014 merge (--no-ff) a task worktree branch into the project default branch (preserves agent commit SHAs per ADR-062) and clean up the worktree",
11976
+ description: "orchestrate.worktree.complete (mutate) \u2014 merge (--no-ff) a task worktree branch into the project default branch (preserves agent commit SHAs per ADR-062) and clean up the worktree. T9548: idempotent (re-run on completed worktree = no-op).",
11812
11977
  tier: 2,
11813
- idempotent: false,
11978
+ idempotent: true,
11814
11979
  sessionRequired: false,
11815
11980
  requiredParams: ["taskId"],
11816
11981
  params: [
@@ -11819,6 +11984,12 @@ var init_registry = __esm({
11819
11984
  type: "string",
11820
11985
  required: true,
11821
11986
  description: "Task ID whose worktree should be merged and cleaned up"
11987
+ },
11988
+ {
11989
+ name: "resolve",
11990
+ type: "string",
11991
+ required: false,
11992
+ description: 'T9548 conflict-recovery mode: "auto" (default \u2014 attempt git merge --no-ff) or "manual" (skip merge, mark worktree as manually-handled in audit log)'
11822
11993
  }
11823
11994
  ]
11824
11995
  },
@@ -12134,14 +12305,21 @@ var init_registry = __esm({
12134
12305
  }
12135
12306
  ]
12136
12307
  },
12137
- // release mutate: start (T1597 / ADR-063 canonical step 1)
12308
+ // release.start / release.verify / release.publish removed in T9540
12309
+ // (Phase 6 of T9499) — backing functions in
12310
+ // `packages/core/src/release/pipeline.ts` (the legacy 4-step pipeline)
12311
+ // were deleted. The canonical replacement surface is the SPEC-T9345
12312
+ // 4-verb pipeline registered below: `release.plan`, `release.open`,
12313
+ // `release.reconcile`, plus `cleo verify <task> --gate X --evidence …`
12314
+ // for per-task gate verification (R-422 / ADR-051).
12315
+ // release mutate: reconcile (T9526 / SPEC-T9345 §4.4 — v2 reconcile verb)
12138
12316
  {
12139
12317
  gateway: "mutate",
12140
12318
  domain: "release",
12141
- operation: "start",
12142
- description: "release.start (mutate) \u2014 Step 1 of 4: validate version, capture branch, persist release handle (T1597 / ADR-063)",
12319
+ operation: "reconcile",
12320
+ description: "release.reconcile (mutate) \u2014 v2 reconcile verb: backfill the 11 provenance tables from git log + gh api. Single SQLite TX, UPSERT-everywhere, idempotent (T9526 / SPEC-T9345 \xA74.4).",
12143
12321
  tier: 1,
12144
- idempotent: false,
12322
+ idempotent: true,
12145
12323
  sessionRequired: false,
12146
12324
  requiredParams: ["version"],
12147
12325
  params: [
@@ -12149,70 +12327,90 @@ var init_registry = __esm({
12149
12327
  name: "version",
12150
12328
  type: "string",
12151
12329
  required: true,
12152
- description: "Version to release (e.g. 2026.5.4)",
12153
- cli: { positional: true }
12330
+ description: "Version string whose tag has landed on main (e.g. v2026.6.0)"
12154
12331
  },
12155
12332
  {
12156
- name: "epicId",
12157
- type: "string",
12333
+ name: "fromWorkflow",
12334
+ type: "boolean",
12158
12335
  required: false,
12159
- description: "Epic ID this release ships"
12336
+ description: "Indicates invocation from release-publish.yml (affects logging only)"
12160
12337
  },
12161
12338
  {
12162
- name: "branch",
12163
- type: "string",
12339
+ name: "rollback",
12340
+ type: "boolean",
12164
12341
  required: false,
12165
- description: "Override detected branch"
12342
+ description: "Reconcile a rollback rather than a publish (deferred to T9528)"
12166
12343
  }
12167
12344
  ]
12168
12345
  },
12169
- // release query: verify (T1597 / ADR-063 canonical step 2)
12170
- {
12171
- gateway: "query",
12172
- domain: "release",
12173
- operation: "verify",
12174
- description: "release.verify (query) \u2014 Step 2 of 4: run gates + audit child tasks of the active release epic (T1597 / ADR-063)",
12175
- tier: 1,
12176
- idempotent: true,
12177
- sessionRequired: false,
12178
- requiredParams: [],
12179
- params: []
12180
- },
12181
- // release mutate: publish (T1597 / ADR-063 canonical step 3)
12346
+ // ---------------------------------------------------------------------------
12347
+ // Provenance domain — `cleo provenance` CLI surface (T9528 · Phase 2 of T9493)
12348
+ // ---------------------------------------------------------------------------
12349
+ // provenance mutate: backfill (T9528 / SPEC-T9345 §8.3)
12182
12350
  {
12183
12351
  gateway: "mutate",
12184
- domain: "release",
12185
- operation: "publish",
12186
- description: "release.publish (mutate) \u2014 Step 3 of 4: invoke project-context publish.command to publish the release artifact (T1597 / ADR-063)",
12352
+ domain: "provenance",
12353
+ operation: "backfill",
12354
+ description: "provenance.backfill (mutate) \u2014 walk historical git tags from --since forward and populate the 11 provenance tables. UPSERT-everywhere, idempotent, restartable via .cleo/release/backfill-state.json (T9528 / SPEC-T9345 \xA78.3).",
12187
12355
  tier: 1,
12188
- idempotent: false,
12356
+ idempotent: true,
12189
12357
  sessionRequired: false,
12190
- requiredParams: [],
12358
+ requiredParams: ["since"],
12191
12359
  params: [
12360
+ {
12361
+ name: "since",
12362
+ type: "string",
12363
+ required: true,
12364
+ description: "Lower-bound version (exclusive). Empty string = walk every reachable tag from the beginning of history."
12365
+ },
12366
+ {
12367
+ name: "forceOverwrite",
12368
+ type: "boolean",
12369
+ required: false,
12370
+ description: "UPDATE existing rows on conflict (audit-logged). Default: UPSERT only."
12371
+ },
12192
12372
  {
12193
12373
  name: "dryRun",
12194
12374
  type: "boolean",
12195
12375
  required: false,
12196
- description: "Print command without executing"
12376
+ description: "Enumerate the tag set and return the plan without writing to the DB"
12377
+ },
12378
+ {
12379
+ name: "resetCheckpoint",
12380
+ type: "boolean",
12381
+ required: false,
12382
+ description: "Clear .cleo/release/backfill-state.json before starting (do NOT resume)"
12197
12383
  }
12198
12384
  ]
12199
12385
  },
12200
- // release mutate: reconcile (T1597 / ADR-063 canonical step 4)
12386
+ // provenance query: verify (T9529 / SPEC-T9345 §4.6)
12201
12387
  {
12202
- gateway: "mutate",
12203
- domain: "release",
12204
- operation: "reconcile",
12205
- description: "release.reconcile (mutate) \u2014 Step 4 of 4: run post-release invariants, auto-complete tasks for the active release (T1597 / ADR-063)",
12388
+ gateway: "query",
12389
+ domain: "provenance",
12390
+ operation: "verify",
12391
+ description: "provenance.verify (query) \u2014 READ-ONLY audit of the 11 provenance tables for a release. Checks FK integrity (release_commits, task_commits, pr_commits, pr_tasks, release_changes, release_artifacts), orphan rows, and ADR-051 evidence-atom staleness. Exit code 0 on pass, non-zero on any fail (T9529 / SPEC-T9345 \xA74.6).",
12206
12392
  tier: 1,
12207
- idempotent: false,
12393
+ idempotent: true,
12208
12394
  sessionRequired: false,
12209
12395
  requiredParams: [],
12210
12396
  params: [
12211
12397
  {
12212
- name: "dryRun",
12398
+ name: "version",
12399
+ type: "string",
12400
+ required: false,
12401
+ description: "Release version to verify (e.g. v2026.6.0). Required unless --all is set."
12402
+ },
12403
+ {
12404
+ name: "all",
12213
12405
  type: "boolean",
12214
12406
  required: false,
12215
- description: "Preview without mutations"
12407
+ description: "Verify the most-recent N releases instead of a single version"
12408
+ },
12409
+ {
12410
+ name: "limit",
12411
+ type: "number",
12412
+ required: false,
12413
+ description: "How many releases to verify in --all mode (default 5)"
12216
12414
  }
12217
12415
  ]
12218
12416
  },
@@ -12448,6 +12646,59 @@ var init_registry = __esm({
12448
12646
  description: "Optional credential label to pin this role to a specific store entry"
12449
12647
  }
12450
12648
  ]
12649
+ },
12650
+ // ---------------------------------------------------------------------------
12651
+ // Upgrade domain — `cleo upgrade workflows` (T9536 · Phase 4 of T9497)
12652
+ // ---------------------------------------------------------------------------
12653
+ // upgrade query: workflows — read-only drift detection.
12654
+ {
12655
+ gateway: "query",
12656
+ domain: "upgrade",
12657
+ operation: "workflows",
12658
+ description: "upgrade.workflows (query) \u2014 re-render the four release-pipeline workflow templates and report drift against .github/workflows/release-*.yml. Read-only (forces dryRun). Honours .workflow-overrides.yml for operator-declared customizations (T9536).",
12659
+ tier: 2,
12660
+ idempotent: true,
12661
+ sessionRequired: false,
12662
+ requiredParams: [],
12663
+ params: [
12664
+ {
12665
+ name: "includeRendered",
12666
+ type: "boolean",
12667
+ required: false,
12668
+ description: "Include the freshly rendered YAML in the response (for diff display)"
12669
+ }
12670
+ ]
12671
+ },
12672
+ // upgrade mutate: workflows — re-render + optional re-write with --force.
12673
+ {
12674
+ gateway: "mutate",
12675
+ domain: "upgrade",
12676
+ operation: "workflows",
12677
+ description: "upgrade.workflows (mutate) \u2014 re-render the four release-pipeline workflow templates; with force=true, overwrite drifted files and audit-log to .cleo/audit/upgrade-workflows.jsonl. .workflow-overrides.yml entries are preserved (operator-declared customization). hasDrift flag in the response drives the --check exit-code contract (T9536).",
12678
+ tier: 2,
12679
+ idempotent: true,
12680
+ sessionRequired: false,
12681
+ requiredParams: [],
12682
+ params: [
12683
+ {
12684
+ name: "force",
12685
+ type: "boolean",
12686
+ required: false,
12687
+ description: "Overwrite drifted files (excluding .workflow-overrides.yml keys)"
12688
+ },
12689
+ {
12690
+ name: "dryRun",
12691
+ type: "boolean",
12692
+ required: false,
12693
+ description: "Print the per-template diff without writing"
12694
+ },
12695
+ {
12696
+ name: "includeRendered",
12697
+ type: "boolean",
12698
+ required: false,
12699
+ description: "Include the freshly rendered YAML in the response (for diff display)"
12700
+ }
12701
+ ]
12451
12702
  }
12452
12703
  ];
12453
12704
  counts = getCounts();
@@ -12581,8 +12832,8 @@ var init_dispatcher = __esm({
12581
12832
  projectRoot
12582
12833
  });
12583
12834
  }).catch((err) => {
12584
- const log5 = getLogger("dialectic-hook");
12585
- log5.warn({ err }, "dialectic-evaluator failed");
12835
+ const log8 = getLogger("dialectic-hook");
12836
+ log8.warn({ err }, "dialectic-evaluator failed");
12586
12837
  });
12587
12838
  });
12588
12839
  }
@@ -12723,8 +12974,6 @@ __export(engine_exports, {
12723
12974
  lifecycleReset: () => lifecycleReset,
12724
12975
  lifecycleSkip: () => lifecycleSkip,
12725
12976
  lifecycleStatus: () => lifecycleStatus,
12726
- loadActiveReleaseHandle: () => loadActiveReleaseHandle,
12727
- makeAdr061GateRunner: () => makeAdr061GateRunner,
12728
12977
  mapCodebase: () => mapCodebase,
12729
12978
  memoryBrainStats: () => memoryBrainStats,
12730
12979
  memoryContradictions: () => memoryContradictions,
@@ -12802,18 +13051,16 @@ __export(engine_exports, {
12802
13051
  releaseGatesRun: () => releaseGatesRun,
12803
13052
  releaseIvtrAutoSuggest: () => releaseIvtrAutoSuggest,
12804
13053
  releaseList: () => releaseList,
13054
+ releaseOpen: () => releaseOpen,
13055
+ releasePlan: () => releasePlan,
12805
13056
  releasePrStatus: () => releasePrStatus,
12806
13057
  releasePrepare: () => releasePrepare,
12807
- releasePublish: () => releasePublish,
12808
13058
  releasePush: () => releasePush,
12809
- releaseReconcile: () => releaseReconcile,
13059
+ releaseReconcileV2: () => releaseReconcileV2,
12810
13060
  releaseRollback: () => releaseRollback,
12811
13061
  releaseRollbackFull: () => releaseRollbackFull,
12812
- releaseShip: () => releaseShip,
12813
13062
  releaseShow: () => releaseShow,
12814
- releaseStart: () => releaseStart,
12815
13063
  releaseTag: () => releaseTag,
12816
- releaseVerify: () => releaseVerify,
12817
13064
  sessionArchive: () => sessionArchive,
12818
13065
  sessionBriefing: () => sessionBriefing,
12819
13066
  sessionChainShow: () => sessionChainShow,
@@ -12954,8 +13201,6 @@ import {
12954
13201
  lifecycleReset,
12955
13202
  lifecycleSkip,
12956
13203
  lifecycleStatus,
12957
- loadActiveReleaseHandle,
12958
- makeAdr061GateRunner,
12959
13204
  mapCodebase,
12960
13205
  memoryBrainStats,
12961
13206
  memoryContradictions,
@@ -13032,18 +13277,16 @@ import {
13032
13277
  releaseGatesRun,
13033
13278
  releaseIvtrAutoSuggest,
13034
13279
  releaseList,
13280
+ releaseOpen,
13281
+ releasePlan,
13035
13282
  releasePrepare,
13036
13283
  releasePrStatus,
13037
- releasePublish,
13038
13284
  releasePush,
13039
- releaseReconcile,
13285
+ releaseReconcileV2,
13040
13286
  releaseRollback,
13041
13287
  releaseRollbackFull,
13042
- releaseShip,
13043
13288
  releaseShow,
13044
- releaseStart,
13045
13289
  releaseTag,
13046
- releaseVerify,
13047
13290
  sessionArchive,
13048
13291
  sessionBriefing,
13049
13292
  sessionChainShow,
@@ -24594,8 +24837,8 @@ async function loadPlaybookByName(name) {
24594
24837
  return null;
24595
24838
  }
24596
24839
  try {
24597
- const { getProjectRoot: getProjectRoot34 } = await import("@cleocode/core/internal");
24598
- const projectRoot = __playbookRuntimeOverrides.projectRoot ?? getProjectRoot34();
24840
+ const { getProjectRoot: getProjectRoot38 } = await import("@cleocode/core/internal");
24841
+ const projectRoot = __playbookRuntimeOverrides.projectRoot ?? getProjectRoot38();
24599
24842
  const resolved = resolvePlaybook(name, {
24600
24843
  projectRoot,
24601
24844
  globalPlaybooksDir: __playbookRuntimeOverrides.globalPlaybooksDir,
@@ -24639,8 +24882,8 @@ async function acquireDb() {
24639
24882
  async function buildDefaultDispatcher() {
24640
24883
  if (__playbookRuntimeOverrides.dispatcher) return __playbookRuntimeOverrides.dispatcher;
24641
24884
  const { orchestrateSpawnExecute: orchestrateSpawnExecute2 } = await Promise.resolve().then(() => (init_engine(), engine_exports));
24642
- const { getProjectRoot: getProjectRoot34 } = await import("@cleocode/core/internal");
24643
- const projectRoot = getProjectRoot34();
24885
+ const { getProjectRoot: getProjectRoot38 } = await import("@cleocode/core/internal");
24886
+ const projectRoot = getProjectRoot38();
24644
24887
  return {
24645
24888
  async dispatch(input2) {
24646
24889
  try {
@@ -24830,8 +25073,8 @@ var init_playbook2 = __esm({
24830
25073
  projectRoot = __playbookRuntimeOverrides.projectRoot;
24831
25074
  } else {
24832
25075
  try {
24833
- const { getProjectRoot: getProjectRoot34 } = await import("@cleocode/core/internal");
24834
- projectRoot = getProjectRoot34();
25076
+ const { getProjectRoot: getProjectRoot38 } = await import("@cleocode/core/internal");
25077
+ projectRoot = getProjectRoot38();
24835
25078
  } catch {
24836
25079
  projectRoot = void 0;
24837
25080
  }
@@ -24895,14 +25138,14 @@ var init_playbook2 = __esm({
24895
25138
  const dispatcher = await buildDefaultDispatcher();
24896
25139
  let result;
24897
25140
  try {
24898
- const { getProjectRoot: getProjectRoot34 } = await import("@cleocode/core/internal");
25141
+ const { getProjectRoot: getProjectRoot38 } = await import("@cleocode/core/internal");
24899
25142
  const opts = {
24900
25143
  db,
24901
25144
  playbook: parsed.definition,
24902
25145
  playbookHash: parsed.sourceHash,
24903
25146
  initialContext,
24904
25147
  dispatcher,
24905
- projectRoot: getProjectRoot34()
25148
+ projectRoot: getProjectRoot38()
24906
25149
  };
24907
25150
  if (__playbookRuntimeOverrides.approvalSecret !== void 0) {
24908
25151
  opts.approvalSecret = __playbookRuntimeOverrides.approvalSecret;
@@ -25238,7 +25481,7 @@ async function orchestratePivotOp(params) {
25238
25481
  }
25239
25482
  }
25240
25483
  async function orchestrateWorktreeCompleteOp(params) {
25241
- return handleWorktreeComplete(params.taskId, getProjectRoot9());
25484
+ return handleWorktreeComplete(params.taskId, getProjectRoot9(), params.resolve);
25242
25485
  }
25243
25486
  async function orchestrateWorktreeCleanupOp(params) {
25244
25487
  return handleWorktreeCleanup(getProjectRoot9(), params.taskIds);
@@ -25485,16 +25728,23 @@ async function orchestrateAnalyzeParallelSafety(taskIds, projectRoot) {
25485
25728
  };
25486
25729
  }
25487
25730
  }
25488
- async function handleWorktreeComplete(taskId, projectRoot) {
25731
+ async function handleWorktreeComplete(taskId, projectRoot, resolve8) {
25489
25732
  try {
25490
- const { completeAgentWorktreeViaMerge } = await import("@cleocode/core/internal");
25491
- const result = completeAgentWorktreeViaMerge(taskId, projectRoot);
25492
- if (!result.merged && result.error) {
25733
+ const { completeWorktreeForTask } = await import("@cleocode/core/internal");
25734
+ const result = completeWorktreeForTask(taskId, projectRoot, {
25735
+ resolve: resolve8 ?? "auto"
25736
+ });
25737
+ if (result.outcome === "conflict") {
25493
25738
  return {
25494
25739
  success: false,
25495
25740
  error: {
25496
25741
  code: "E_WORKTREE_COMPLETE_FAILED",
25497
- message: result.error
25742
+ message: result.reason,
25743
+ details: {
25744
+ taskId: result.taskId,
25745
+ integration: result.integration,
25746
+ recovery: result.recovery
25747
+ }
25498
25748
  }
25499
25749
  };
25500
25750
  }
@@ -26149,7 +26399,12 @@ var init_orchestrate2 = __esm({
26149
26399
  "taskId is required",
26150
26400
  startTime
26151
26401
  );
26152
- const p = { taskId: params.taskId };
26402
+ const rawResolve = params.resolve;
26403
+ const resolve8 = rawResolve === "manual" ? "manual" : rawResolve === "auto" ? "auto" : void 0;
26404
+ const p = {
26405
+ taskId: params.taskId,
26406
+ ...resolve8 !== void 0 ? { resolve: resolve8 } : {}
26407
+ };
26153
26408
  return wrapResult(
26154
26409
  await coreOps2["worktree.complete"](p),
26155
26410
  "mutate",
@@ -26483,19 +26738,6 @@ async function releaseChannelShowOp(_params) {
26483
26738
  async function releaseChangelogSinceOp(params) {
26484
26739
  return releaseChangelogSince(params.sinceTag, getProjectRoot10());
26485
26740
  }
26486
- async function releaseShipOp(params) {
26487
- return releaseShip(
26488
- {
26489
- version: params.version,
26490
- epicId: params.epicId,
26491
- remote: params.remote,
26492
- dryRun: params.dryRun,
26493
- bump: params.bump,
26494
- force: params.force
26495
- },
26496
- getProjectRoot10()
26497
- );
26498
- }
26499
26741
  async function releasePrStatusOp(params) {
26500
26742
  return releasePrStatus(params.version, getProjectRoot10());
26501
26743
  }
@@ -26655,7 +26897,6 @@ var init_pipeline3 = __esm({
26655
26897
  "release.show": releaseShowOp,
26656
26898
  "release.channel.show": releaseChannelShowOp,
26657
26899
  "release.changelog.since": releaseChangelogSinceOp,
26658
- "release.ship": releaseShipOp,
26659
26900
  "release.pr-status": releasePrStatusOp,
26660
26901
  "release.cancel": releaseCancelOp,
26661
26902
  "release.rollback": releaseRollbackOp,
@@ -26802,13 +27043,12 @@ var init_pipeline3 = __esm({
26802
27043
  },
26803
27044
  // -------------------------------------------------------------------------
26804
27045
  // Release mutations
27046
+ //
27047
+ // T9540 removed `release.ship` from the pipeline domain — the
27048
+ // `cleo release ship` CLI alias now forwards to `release.plan` +
27049
+ // `release.open` (handled by the release domain), not the deleted
27050
+ // `releaseShip` monolith.
26805
27051
  // -------------------------------------------------------------------------
26806
- "release.ship": async (params) => {
26807
- if (!params.version || !params.epicId) {
26808
- return lafsError("E_INVALID_INPUT", "version and epicId are required", "release.ship");
26809
- }
26810
- return wrapCoreResult(await coreOps3["release.ship"](params), "release.ship");
26811
- },
26812
27052
  // release.pr-status — T9095 query: poll CI checks for an in-progress release PR
26813
27053
  "release.pr-status": async (params) => {
26814
27054
  if (!params.version) {
@@ -27028,7 +27268,6 @@ var init_pipeline3 = __esm({
27028
27268
  "stage.reset",
27029
27269
  "stage.gate.pass",
27030
27270
  "stage.gate.fail",
27031
- "release.ship",
27032
27271
  "release.cancel",
27033
27272
  "release.rollback",
27034
27273
  "release.rollback.full",
@@ -27102,7 +27341,6 @@ var init_pipeline3 = __esm({
27102
27341
  "stage.reset",
27103
27342
  "stage.gate.pass",
27104
27343
  "stage.gate.fail",
27105
- "release.ship",
27106
27344
  "release.cancel",
27107
27345
  "release.rollback",
27108
27346
  "release.rollback.full",
@@ -27122,22 +27360,144 @@ var init_pipeline3 = __esm({
27122
27360
  }
27123
27361
  });
27124
27362
 
27363
+ // packages/cleo/src/dispatch/domains/provenance.ts
27364
+ import {
27365
+ getLogger as getLogger11,
27366
+ getProjectRoot as getProjectRoot11,
27367
+ provenanceBackfill,
27368
+ verifyProvenance
27369
+ } from "@cleocode/core/internal";
27370
+ var log2, ProvenanceHandler;
27371
+ var init_provenance = __esm({
27372
+ "packages/cleo/src/dispatch/domains/provenance.ts"() {
27373
+ "use strict";
27374
+ init_base();
27375
+ log2 = getLogger11("domain:provenance");
27376
+ ProvenanceHandler = class {
27377
+ // -----------------------------------------------------------------------
27378
+ // Query
27379
+ // -----------------------------------------------------------------------
27380
+ /**
27381
+ * Provenance query operations. Currently only `verify` is implemented.
27382
+ *
27383
+ * @param operation - The provenance query op name (`verify`).
27384
+ * @param params - The dispatch params object: `version`, `all`, `limit`.
27385
+ */
27386
+ async query(operation, params) {
27387
+ const startTime = Date.now();
27388
+ try {
27389
+ switch (operation) {
27390
+ // ------------------------------------------------------------------
27391
+ // provenance.verify — T9529 / SPEC-T9345 §4.6
27392
+ // ------------------------------------------------------------------
27393
+ case "verify": {
27394
+ const version = typeof params?.["version"] === "string" ? params["version"] : void 0;
27395
+ const all = typeof params?.["all"] === "boolean" ? params["all"] : false;
27396
+ const limit = typeof params?.["limit"] === "number" ? params["limit"] : void 0;
27397
+ if (!version && !all) {
27398
+ return errorResult(
27399
+ "query",
27400
+ "provenance",
27401
+ operation,
27402
+ "E_INVALID_INPUT",
27403
+ "verify requires either <version> or --all",
27404
+ startTime
27405
+ );
27406
+ }
27407
+ const result = await verifyProvenance({
27408
+ ...version ? { version } : {},
27409
+ all,
27410
+ ...limit !== void 0 ? { limit } : {},
27411
+ projectRoot: getProjectRoot11()
27412
+ });
27413
+ return wrapResult(result, "query", "provenance", operation, startTime);
27414
+ }
27415
+ default:
27416
+ return unsupportedOp("query", "provenance", operation, startTime);
27417
+ }
27418
+ } catch (err) {
27419
+ log2.error({ err, operation }, "ProvenanceHandler query error");
27420
+ return handleErrorResult("query", "provenance", operation, err, startTime);
27421
+ }
27422
+ }
27423
+ // -----------------------------------------------------------------------
27424
+ // Mutate
27425
+ // -----------------------------------------------------------------------
27426
+ /**
27427
+ * Provenance mutate operations. Currently only `backfill` is implemented.
27428
+ *
27429
+ * @param operation - The provenance mutate op name (`backfill`).
27430
+ * @param params - The dispatch params object: `since`, `forceOverwrite`,
27431
+ * `dryRun`, `resetCheckpoint`.
27432
+ */
27433
+ async mutate(operation, params) {
27434
+ const startTime = Date.now();
27435
+ try {
27436
+ switch (operation) {
27437
+ // ------------------------------------------------------------------
27438
+ // provenance.backfill — T9528 / SPEC-T9345 §8.3
27439
+ // ------------------------------------------------------------------
27440
+ case "backfill": {
27441
+ const since = typeof params?.["since"] === "string" ? params["since"] : void 0;
27442
+ if (since === void 0) {
27443
+ return errorResult(
27444
+ "mutate",
27445
+ "provenance",
27446
+ operation,
27447
+ "E_INVALID_INPUT",
27448
+ 'since is required (use --since "" to walk every reachable tag)',
27449
+ startTime
27450
+ );
27451
+ }
27452
+ const forceOverwrite = typeof params?.["forceOverwrite"] === "boolean" ? params["forceOverwrite"] : false;
27453
+ const dryRun = typeof params?.["dryRun"] === "boolean" ? params["dryRun"] : false;
27454
+ const resetCheckpoint = typeof params?.["resetCheckpoint"] === "boolean" ? params["resetCheckpoint"] : false;
27455
+ const result = await provenanceBackfill({
27456
+ since,
27457
+ projectRoot: getProjectRoot11(),
27458
+ forceOverwrite,
27459
+ dryRun,
27460
+ resetCheckpoint
27461
+ });
27462
+ return wrapResult(result, "mutate", "provenance", operation, startTime);
27463
+ }
27464
+ default:
27465
+ return unsupportedOp("mutate", "provenance", operation, startTime);
27466
+ }
27467
+ } catch (err) {
27468
+ log2.error({ err, operation }, "ProvenanceHandler mutate error");
27469
+ return handleErrorResult("mutate", "provenance", operation, err, startTime);
27470
+ }
27471
+ }
27472
+ // -----------------------------------------------------------------------
27473
+ // getSupportedOperations
27474
+ // -----------------------------------------------------------------------
27475
+ /** Return declared operations for introspection and registry validation. */
27476
+ getSupportedOperations() {
27477
+ return {
27478
+ query: ["verify"],
27479
+ mutate: ["backfill"]
27480
+ };
27481
+ }
27482
+ };
27483
+ }
27484
+ });
27485
+
27125
27486
  // packages/cleo/src/dispatch/domains/release.ts
27126
- import { getLogger as getLogger11, getProjectRoot as getProjectRoot11 } from "@cleocode/core/internal";
27487
+ import { getLogger as getLogger12, getProjectRoot as getProjectRoot12 } from "@cleocode/core/internal";
27127
27488
  async function releaseGateOp(params) {
27128
- return releaseGateCheck(params.epicId, params.force ?? false, getProjectRoot11());
27489
+ return releaseGateCheck(params.epicId, params.force ?? false, getProjectRoot12());
27129
27490
  }
27130
27491
  async function releaseIvtrSuggestOp(params) {
27131
- return releaseIvtrAutoSuggest(params.taskId, getProjectRoot11());
27492
+ return releaseIvtrAutoSuggest(params.taskId, getProjectRoot12());
27132
27493
  }
27133
- var log2, coreOps4, ReleaseHandler;
27494
+ var log3, coreOps4, ReleaseHandler;
27134
27495
  var init_release2 = __esm({
27135
27496
  "packages/cleo/src/dispatch/domains/release.ts"() {
27136
27497
  "use strict";
27137
27498
  init_engine();
27138
27499
  init_base();
27139
- init_meta2();
27140
- log2 = getLogger11("domain:release");
27500
+ log3 = getLogger12("domain:release");
27141
27501
  coreOps4 = {
27142
27502
  gate: releaseGateOp,
27143
27503
  "ivtr-suggest": releaseIvtrSuggestOp
@@ -27152,7 +27512,10 @@ var init_release2 = __esm({
27152
27512
  * Supported operations:
27153
27513
  * - `gate` — check IVTR phase state for all tasks in a release epic
27154
27514
  * - `ivtr-suggest` — check if all epic tasks are released and suggest `release ship`
27155
- * - `verify` — Step 2 of 4: run gates + audit child tasks (T1597 / ADR-063)
27515
+ *
27516
+ * The legacy `verify` query (run gates + audit child tasks) was removed
27517
+ * in T9540 — use `cleo verify <task> --gate X --evidence …` per
27518
+ * SPEC-T9345 §12 R-422 / ADR-051.
27156
27519
  */
27157
27520
  async query(operation, params) {
27158
27521
  const startTime = Date.now();
@@ -27195,24 +27558,11 @@ var init_release2 = __esm({
27195
27558
  startTime
27196
27559
  );
27197
27560
  }
27198
- // release.verify — Step 2 of 4: run gates + audit child tasks (T1597 / ADR-063)
27199
- case "verify": {
27200
- const projectRoot = getProjectRoot11();
27201
- const handle = loadActiveReleaseHandle(projectRoot);
27202
- const result = await releaseVerify(handle, {
27203
- runGate: makeAdr061GateRunner(projectRoot)
27204
- });
27205
- return {
27206
- success: true,
27207
- data: result,
27208
- meta: dispatchMeta("query", "release", operation, startTime)
27209
- };
27210
- }
27211
27561
  default:
27212
27562
  return unsupportedOp("query", "release", operation, startTime);
27213
27563
  }
27214
27564
  } catch (err) {
27215
- log2.error({ err, operation }, "ReleaseHandler query error");
27565
+ log3.error({ err, operation }, "ReleaseHandler query error");
27216
27566
  return handleErrorResult("query", "release", operation, err, startTime);
27217
27567
  }
27218
27568
  }
@@ -27229,9 +27579,14 @@ var init_release2 = __esm({
27229
27579
  * Supported operations:
27230
27580
  * - `gate` — same IVTR gate check as query.gate (no DB writes)
27231
27581
  * - `ivtr-suggest` — same auto-suggest as query.ivtr-suggest (no DB writes)
27232
- * - `start` Step 1 of 4: validate version, capture branch, persist handle
27233
- * - `publish` Step 3 of 4: invoke project-context publish.command
27234
- * - `reconcile` — Step 4 of 4: run post-release invariants, auto-complete tasks
27582
+ * - `plan` SPEC-T9345 §4.2 (T9525): build canonical Release Plan envelope
27583
+ * - `open` SPEC-T9345 §4.3 (T9530): dispatch release-prepare workflow
27584
+ * - `reconcile` — SPEC-T9345 §4.4 (T9526 v2): backfill 11 provenance tables
27585
+ *
27586
+ * The legacy `start` / `publish` mutations (and the legacy v1
27587
+ * `reconcile`) were removed in T9540 — their backing functions in
27588
+ * `packages/core/src/release/pipeline.ts` were deleted as part of
27589
+ * Phase 6 of T9499.
27235
27590
  */
27236
27591
  async mutate(operation, params) {
27237
27592
  const startTime = Date.now();
@@ -27274,10 +27629,11 @@ var init_release2 = __esm({
27274
27629
  startTime
27275
27630
  );
27276
27631
  }
27277
- // release.startStep 1 of 4 (T1597 / ADR-063)
27278
- case "start": {
27632
+ // release.planSPEC-T9345 §4.2 (T9525): build canonical Release Plan envelope
27633
+ case "plan": {
27279
27634
  const version = typeof params?.version === "string" ? params.version : void 0;
27280
- if (!version)
27635
+ const epicId = typeof params?.epicId === "string" ? params.epicId : void 0;
27636
+ if (!version) {
27281
27637
  return errorResult(
27282
27638
  "mutate",
27283
27639
  "release",
@@ -27286,45 +27642,74 @@ var init_release2 = __esm({
27286
27642
  "version is required",
27287
27643
  startTime
27288
27644
  );
27289
- const result = await releaseStart(version, {
27290
- epicId: typeof params?.epicId === "string" ? params.epicId : void 0,
27291
- branch: typeof params?.branch === "string" ? params.branch : void 0
27292
- });
27293
- return {
27294
- success: true,
27295
- data: result,
27296
- meta: dispatchMeta("mutate", "release", operation, startTime)
27645
+ }
27646
+ if (!epicId) {
27647
+ return errorResult(
27648
+ "mutate",
27649
+ "release",
27650
+ operation,
27651
+ "E_INVALID_INPUT",
27652
+ "epicId is required",
27653
+ startTime
27654
+ );
27655
+ }
27656
+ const typed = {
27657
+ version,
27658
+ epicId,
27659
+ scheme: typeof params?.scheme === "string" ? params.scheme : void 0,
27660
+ channel: typeof params?.channel === "string" ? params.channel : void 0,
27661
+ hotfix: typeof params?.hotfix === "boolean" ? params.hotfix : false,
27662
+ dryRun: typeof params?.dryRun === "boolean" ? params.dryRun : false,
27663
+ projectRoot: getProjectRoot12()
27297
27664
  };
27665
+ return wrapResult(await releasePlan(typed), "mutate", "release", operation, startTime);
27298
27666
  }
27299
- // release.publishStep 3 of 4 (T1597 / ADR-063)
27300
- case "publish": {
27301
- const handle = loadActiveReleaseHandle(getProjectRoot11());
27302
- const result = await releasePublish(handle, {
27303
- dryRun: typeof params?.dryRun === "boolean" ? params.dryRun : false
27304
- });
27305
- return {
27306
- success: true,
27307
- data: result,
27308
- meta: dispatchMeta("mutate", "release", operation, startTime)
27667
+ // release.openSPEC-T9345 §4.3 (T9530): dispatch release-prepare workflow
27668
+ case "open": {
27669
+ const version = typeof params?.version === "string" ? params.version : void 0;
27670
+ if (!version) {
27671
+ return errorResult(
27672
+ "mutate",
27673
+ "release",
27674
+ operation,
27675
+ "E_INVALID_INPUT",
27676
+ "version is required",
27677
+ startTime
27678
+ );
27679
+ }
27680
+ const typed = {
27681
+ version,
27682
+ workflow: typeof params?.workflow === "string" ? params.workflow : void 0,
27683
+ watch: typeof params?.watch === "boolean" ? params.watch : false,
27684
+ commitPlan: typeof params?.commitPlan === "boolean" ? params.commitPlan : false,
27685
+ projectRoot: getProjectRoot12()
27309
27686
  };
27687
+ return wrapResult(await releaseOpen(typed), "mutate", "release", operation, startTime);
27310
27688
  }
27311
- // release.reconcile — Step 4 of 4 (T1597 / ADR-063)
27689
+ // release.reconcile — v2 reconcile verb (T9526 / SPEC-T9345 §4.4)
27312
27690
  case "reconcile": {
27313
- const handle = loadActiveReleaseHandle(getProjectRoot11());
27314
- const result = await releaseReconcile(handle, {
27315
- dryRun: typeof params?.dryRun === "boolean" ? params.dryRun : false
27691
+ const version = typeof params?.version === "string" ? params.version : void 0;
27692
+ if (!version)
27693
+ return errorResult(
27694
+ "mutate",
27695
+ "release",
27696
+ operation,
27697
+ "E_INVALID_INPUT",
27698
+ "version is required",
27699
+ startTime
27700
+ );
27701
+ const result = await releaseReconcileV2(version, {
27702
+ projectRoot: getProjectRoot12(),
27703
+ fromWorkflow: typeof params?.fromWorkflow === "boolean" ? params.fromWorkflow : false,
27704
+ rollback: typeof params?.rollback === "boolean" ? params.rollback : false
27316
27705
  });
27317
- return {
27318
- success: true,
27319
- data: result,
27320
- meta: dispatchMeta("mutate", "release", operation, startTime)
27321
- };
27706
+ return wrapResult(result, "mutate", "release", operation, startTime);
27322
27707
  }
27323
27708
  default:
27324
27709
  return unsupportedOp("mutate", "release", operation, startTime);
27325
27710
  }
27326
27711
  } catch (err) {
27327
- log2.error({ err, operation }, "ReleaseHandler mutate error");
27712
+ log3.error({ err, operation }, "ReleaseHandler mutate error");
27328
27713
  return handleErrorResult("mutate", "release", operation, err, startTime);
27329
27714
  }
27330
27715
  }
@@ -27334,8 +27719,8 @@ var init_release2 = __esm({
27334
27719
  /** Return declared operations for introspection and registry validation. */
27335
27720
  getSupportedOperations() {
27336
27721
  return {
27337
- query: ["gate", "ivtr-suggest", "verify"],
27338
- mutate: ["gate", "ivtr-suggest", "start", "publish", "reconcile"]
27722
+ query: ["gate", "ivtr-suggest"],
27723
+ mutate: ["gate", "ivtr-suggest", "reconcile", "plan", "open"]
27339
27724
  };
27340
27725
  }
27341
27726
  };
@@ -27343,7 +27728,7 @@ var init_release2 = __esm({
27343
27728
  });
27344
27729
 
27345
27730
  // packages/cleo/src/dispatch/domains/sentient.ts
27346
- import { getProjectRoot as getProjectRoot12 } from "@cleocode/core";
27731
+ import { getProjectRoot as getProjectRoot13 } from "@cleocode/core";
27347
27732
  import {
27348
27733
  sentientAllowlistAdd,
27349
27734
  sentientAllowlistList,
@@ -27363,16 +27748,16 @@ var init_sentient2 = __esm({
27363
27748
  init_typed();
27364
27749
  init_base();
27365
27750
  coreOps5 = {
27366
- "propose.list": (params) => sentientProposeList(getProjectRoot12(), params),
27367
- "propose.diff": (params) => sentientProposeDiff(getProjectRoot12(), params),
27368
- "allowlist.list": (params) => sentientAllowlistList(getProjectRoot12(), params),
27369
- "propose.accept": (params) => sentientProposeAccept(getProjectRoot12(), params),
27370
- "propose.reject": (params) => sentientProposeReject(getProjectRoot12(), params),
27371
- "propose.run": (params) => sentientProposeRun(getProjectRoot12(), params),
27372
- "propose.enable": (params) => sentientProposeEnable(getProjectRoot12(), params),
27373
- "propose.disable": (params) => sentientProposeDisable(getProjectRoot12(), params),
27374
- "allowlist.add": (params) => sentientAllowlistAdd(getProjectRoot12(), params),
27375
- "allowlist.remove": (params) => sentientAllowlistRemove(getProjectRoot12(), params)
27751
+ "propose.list": (params) => sentientProposeList(getProjectRoot13(), params),
27752
+ "propose.diff": (params) => sentientProposeDiff(getProjectRoot13(), params),
27753
+ "allowlist.list": (params) => sentientAllowlistList(getProjectRoot13(), params),
27754
+ "propose.accept": (params) => sentientProposeAccept(getProjectRoot13(), params),
27755
+ "propose.reject": (params) => sentientProposeReject(getProjectRoot13(), params),
27756
+ "propose.run": (params) => sentientProposeRun(getProjectRoot13(), params),
27757
+ "propose.enable": (params) => sentientProposeEnable(getProjectRoot13(), params),
27758
+ "propose.disable": (params) => sentientProposeDisable(getProjectRoot13(), params),
27759
+ "allowlist.add": (params) => sentientAllowlistAdd(getProjectRoot13(), params),
27760
+ "allowlist.remove": (params) => sentientAllowlistRemove(getProjectRoot13(), params)
27376
27761
  };
27377
27762
  _sentientTypedHandler = defineTypedHandler("sentient", {
27378
27763
  // -------------------------------------------------------------------------
@@ -27602,28 +27987,28 @@ var init_session_context = __esm({
27602
27987
  });
27603
27988
 
27604
27989
  // packages/cleo/src/dispatch/domains/session.ts
27605
- import { getDb, getLogger as getLogger12, getProjectRoot as getProjectRoot13, sessions } from "@cleocode/core/internal";
27990
+ import { getDb, getLogger as getLogger13, getProjectRoot as getProjectRoot14, sessions } from "@cleocode/core/internal";
27606
27991
  import { eq } from "drizzle-orm";
27607
27992
  async function sessionStatusOp() {
27608
- return sessionStatus(getProjectRoot13());
27993
+ return sessionStatus(getProjectRoot14());
27609
27994
  }
27610
27995
  async function sessionListOp(params) {
27611
- return sessionList(getProjectRoot13(), params);
27996
+ return sessionList(getProjectRoot14(), params);
27612
27997
  }
27613
27998
  async function sessionShowOp(params) {
27614
27999
  if (params.include === "debrief") {
27615
- return sessionDebriefShow(getProjectRoot13(), params.sessionId);
28000
+ return sessionDebriefShow(getProjectRoot14(), params.sessionId);
27616
28001
  }
27617
- return sessionShow(getProjectRoot13(), params.sessionId);
28002
+ return sessionShow(getProjectRoot14(), params.sessionId);
27618
28003
  }
27619
28004
  async function sessionFindOp(params) {
27620
- return sessionFind(getProjectRoot13(), params);
28005
+ return sessionFind(getProjectRoot14(), params);
27621
28006
  }
27622
28007
  async function sessionDecisionLogOp(params) {
27623
- return sessionDecisionLog(getProjectRoot13(), params);
28008
+ return sessionDecisionLog(getProjectRoot14(), params);
27624
28009
  }
27625
28010
  async function sessionContextDriftOp(params) {
27626
- return sessionContextDrift(getProjectRoot13(), params);
28011
+ return sessionContextDrift(getProjectRoot14(), params);
27627
28012
  }
27628
28013
  async function sessionHandoffShowOp(params) {
27629
28014
  let scopeFilter;
@@ -27634,33 +28019,33 @@ async function sessionHandoffShowOp(params) {
27634
28019
  scopeFilter = { type: "epic", epicId: params.scope.replace("epic:", "") };
27635
28020
  }
27636
28021
  }
27637
- return sessionHandoff(getProjectRoot13(), scopeFilter);
28022
+ return sessionHandoff(getProjectRoot14(), scopeFilter);
27638
28023
  }
27639
28024
  async function sessionBriefingShowOp(params) {
27640
- return sessionBriefing(getProjectRoot13(), params);
28025
+ return sessionBriefing(getProjectRoot14(), params);
27641
28026
  }
27642
28027
  async function sessionStartOp(params) {
27643
- return sessionStart(getProjectRoot13(), params);
28028
+ return sessionStart(getProjectRoot14(), params);
27644
28029
  }
27645
28030
  async function sessionEndOp(params) {
27646
- return sessionEnd(getProjectRoot13(), params.note, {
28031
+ return sessionEnd(getProjectRoot14(), params.note, {
27647
28032
  sessionSummary: params.sessionSummary
27648
28033
  });
27649
28034
  }
27650
28035
  async function sessionResumeOp(params) {
27651
- return sessionResume(getProjectRoot13(), params.sessionId);
28036
+ return sessionResume(getProjectRoot14(), params.sessionId);
27652
28037
  }
27653
28038
  async function sessionSuspendOp(params) {
27654
- return sessionSuspend(getProjectRoot13(), params.sessionId, params.reason);
28039
+ return sessionSuspend(getProjectRoot14(), params.sessionId, params.reason);
27655
28040
  }
27656
28041
  async function sessionGcOp(params) {
27657
- return sessionGc(getProjectRoot13(), params.maxAgeDays);
28042
+ return sessionGc(getProjectRoot14(), params.maxAgeDays);
27658
28043
  }
27659
28044
  async function sessionRecordDecisionOp(params) {
27660
- return sessionRecordDecision(getProjectRoot13(), params);
28045
+ return sessionRecordDecision(getProjectRoot14(), params);
27661
28046
  }
27662
28047
  async function sessionRecordAssumptionOp(params) {
27663
- return sessionRecordAssumption(getProjectRoot13(), params);
28048
+ return sessionRecordAssumption(getProjectRoot14(), params);
27664
28049
  }
27665
28050
  async function storeSessionOwnerAuthToken(projectRoot, sessionId, token) {
27666
28051
  const db = await getDb(projectRoot);
@@ -27749,7 +28134,7 @@ var init_session3 = __esm({
27749
28134
  // SSoT-EXEMPT: storeOwnerAuthToken (DB side-effect requiring post-create sessionId),
27750
28135
  // bindSession (process-scoped context, requires scope-string parsing) — ADR-058
27751
28136
  start: async (params) => {
27752
- const projectRoot = getProjectRoot13();
28137
+ const projectRoot = getProjectRoot14();
27753
28138
  if (!params.scope) {
27754
28139
  return lafsError("E_INVALID_INPUT", "scope is required", "start");
27755
28140
  }
@@ -27770,7 +28155,7 @@ var init_session3 = __esm({
27770
28155
  try {
27771
28156
  await storeSessionOwnerAuthToken(projectRoot, sessionId, params.ownerAuthToken);
27772
28157
  } catch (err) {
27773
- getLogger12("domain:session").warn(
28158
+ getLogger13("domain:session").warn(
27774
28159
  { sessionId, err },
27775
28160
  "Failed to store owner_auth_token \u2014 override auth will not be available"
27776
28161
  );
@@ -27788,7 +28173,7 @@ var init_session3 = __esm({
27788
28173
  gradeMode: params.grade ?? false
27789
28174
  });
27790
28175
  } catch {
27791
- getLogger12("domain:session").warn(
28176
+ getLogger13("domain:session").warn(
27792
28177
  { sessionId },
27793
28178
  "Session context already bound, skipping bindSession"
27794
28179
  );
@@ -27798,7 +28183,7 @@ var init_session3 = __esm({
27798
28183
  // SSoT-EXEMPT: orchestrated post-op pipeline — sessionComputeDebrief, persistSessionMemory,
27799
28184
  // unbindSession (process-context teardown), refreshMemoryBridge — ADR-058
27800
28185
  end: async (params) => {
27801
- const projectRoot = getProjectRoot13();
28186
+ const projectRoot = getProjectRoot14();
27802
28187
  const endResult = await coreOps6.end(params);
27803
28188
  if (!endResult.success) {
27804
28189
  return lafsError(
@@ -27924,7 +28309,7 @@ var init_session3 = __esm({
27924
28309
  );
27925
28310
  return wrapResult(envelopeToEngineResult(envelope), "query", "session", operation, startTime);
27926
28311
  } catch (error) {
27927
- getLogger12("domain:session").error(
28312
+ getLogger13("domain:session").error(
27928
28313
  { gateway: "query", domain: "session", operation, err: error },
27929
28314
  error instanceof Error ? error.message : String(error)
27930
28315
  );
@@ -27959,7 +28344,7 @@ var init_session3 = __esm({
27959
28344
  startTime
27960
28345
  );
27961
28346
  } catch (error) {
27962
- getLogger12("domain:session").error(
28347
+ getLogger13("domain:session").error(
27963
28348
  { gateway: "mutate", domain: "session", operation, err: error },
27964
28349
  error instanceof Error ? error.message : String(error)
27965
28350
  );
@@ -27990,7 +28375,7 @@ var init_session3 = __esm({
27990
28375
  });
27991
28376
 
27992
28377
  // packages/cleo/src/dispatch/domains/sticky.ts
27993
- import { getLogger as getLogger13, getProjectRoot as getProjectRoot14 } from "@cleocode/core";
28378
+ import { getLogger as getLogger14, getProjectRoot as getProjectRoot15 } from "@cleocode/core";
27994
28379
  import {
27995
28380
  stickyAdd,
27996
28381
  stickyArchive,
@@ -28004,7 +28389,7 @@ import {
28004
28389
  } from "@cleocode/core/internal";
28005
28390
  async function stickyListOp(params) {
28006
28391
  return stickyListFiltered(
28007
- getProjectRoot14(),
28392
+ getProjectRoot15(),
28008
28393
  {
28009
28394
  status: params.status,
28010
28395
  color: params.color,
@@ -28016,10 +28401,10 @@ async function stickyListOp(params) {
28016
28401
  );
28017
28402
  }
28018
28403
  async function stickyShowOp(params) {
28019
- return stickyShow(getProjectRoot14(), params.stickyId);
28404
+ return stickyShow(getProjectRoot15(), params.stickyId);
28020
28405
  }
28021
28406
  async function stickyAddOp(params) {
28022
- return stickyAdd(getProjectRoot14(), {
28407
+ return stickyAdd(getProjectRoot15(), {
28023
28408
  content: params.content,
28024
28409
  tags: params.tags,
28025
28410
  color: params.color,
@@ -28027,24 +28412,24 @@ async function stickyAddOp(params) {
28027
28412
  });
28028
28413
  }
28029
28414
  async function stickyArchiveOp(params) {
28030
- return stickyArchive(getProjectRoot14(), params.stickyId);
28415
+ return stickyArchive(getProjectRoot15(), params.stickyId);
28031
28416
  }
28032
28417
  async function stickyPurgeOp(params) {
28033
- return stickyPurge(getProjectRoot14(), params.stickyId);
28418
+ return stickyPurge(getProjectRoot15(), params.stickyId);
28034
28419
  }
28035
28420
  async function stickyConvertTaskOp(params) {
28036
- const result = await stickyConvertToTask(getProjectRoot14(), params.stickyId, params.title);
28421
+ const result = await stickyConvertToTask(getProjectRoot15(), params.stickyId, params.title);
28037
28422
  if (!result.success) return { taskId: void 0 };
28038
28423
  return { taskId: result.data.taskId };
28039
28424
  }
28040
28425
  async function stickyConvertMemoryOp(params) {
28041
- const result = await stickyConvertToMemory(getProjectRoot14(), params.stickyId, params.memoryType);
28426
+ const result = await stickyConvertToMemory(getProjectRoot15(), params.stickyId, params.memoryType);
28042
28427
  if (!result.success) return { memoryId: void 0 };
28043
28428
  return { memoryId: result.data.memoryId };
28044
28429
  }
28045
28430
  async function stickyConvertSessionNoteOp(params) {
28046
28431
  const result = await stickyConvertToSessionNote(
28047
- getProjectRoot14(),
28432
+ getProjectRoot15(),
28048
28433
  params.stickyId,
28049
28434
  params.sessionId
28050
28435
  );
@@ -28052,7 +28437,7 @@ async function stickyConvertSessionNoteOp(params) {
28052
28437
  return { sessionId: result.data.sessionId };
28053
28438
  }
28054
28439
  async function stickyConvertTaskNoteOp(params) {
28055
- const result = await stickyConvertToTaskNote(getProjectRoot14(), params.stickyId, params.taskId);
28440
+ const result = await stickyConvertToTaskNote(getProjectRoot15(), params.stickyId, params.taskId);
28056
28441
  if (!result.success) return { taskId: void 0 };
28057
28442
  return { taskId: result.data.taskId };
28058
28443
  }
@@ -28075,14 +28460,14 @@ function envelopeToDispatch(envelope, gateway, operation, startTime) {
28075
28460
  }
28076
28461
  };
28077
28462
  }
28078
- var log3, stickyCoreOps, _stickyTypedHandler, QUERY_OPS9, MUTATE_OPS9, CONVERT_TARGET_TO_KEY, StickyHandler;
28463
+ var log4, stickyCoreOps, _stickyTypedHandler, QUERY_OPS9, MUTATE_OPS9, CONVERT_TARGET_TO_KEY, StickyHandler;
28079
28464
  var init_sticky2 = __esm({
28080
28465
  "packages/cleo/src/dispatch/domains/sticky.ts"() {
28081
28466
  "use strict";
28082
28467
  init_typed();
28083
28468
  init_base();
28084
28469
  init_meta2();
28085
- log3 = getLogger13("domain:sticky");
28470
+ log4 = getLogger14("domain:sticky");
28086
28471
  stickyCoreOps = {
28087
28472
  list: stickyListOp,
28088
28473
  show: stickyShowOp,
@@ -28175,7 +28560,7 @@ var init_sticky2 = __esm({
28175
28560
  );
28176
28561
  return envelopeToDispatch(envelope, "query", operation, startTime);
28177
28562
  } catch (error) {
28178
- log3.error({ gateway: "query", domain: "sticky", operation, err: error }, String(error));
28563
+ log4.error({ gateway: "query", domain: "sticky", operation, err: error }, String(error));
28179
28564
  return handleErrorResult("query", "sticky", operation, error, startTime);
28180
28565
  }
28181
28566
  }
@@ -28208,7 +28593,7 @@ var init_sticky2 = __esm({
28208
28593
  );
28209
28594
  return envelopeToDispatch(envelope, "mutate", operation, startTime);
28210
28595
  } catch (error) {
28211
- log3.error({ gateway: "mutate", domain: "sticky", operation, err: error }, String(error));
28596
+ log4.error({ gateway: "mutate", domain: "sticky", operation, err: error }, String(error));
28212
28597
  return handleErrorResult("mutate", "sticky", operation, error, startTime);
28213
28598
  }
28214
28599
  }
@@ -28223,9 +28608,9 @@ var init_sticky2 = __esm({
28223
28608
  });
28224
28609
 
28225
28610
  // packages/cleo/src/dispatch/domains/tasks.ts
28226
- import { getLogger as getLogger14, getProjectRoot as getProjectRoot15 } from "@cleocode/core";
28611
+ import { getLogger as getLogger15, getProjectRoot as getProjectRoot16 } from "@cleocode/core";
28227
28612
  async function sagaCreate(params) {
28228
- const projectRoot = getProjectRoot15();
28613
+ const projectRoot = getProjectRoot16();
28229
28614
  const title = typeof params.title === "string" ? params.title : "";
28230
28615
  const description = typeof params.description === "string" ? params.description : void 0;
28231
28616
  const acceptance = Array.isArray(params.acceptance) ? params.acceptance : void 0;
@@ -28241,7 +28626,7 @@ async function sagaCreate(params) {
28241
28626
  );
28242
28627
  }
28243
28628
  async function sagaAdd(params) {
28244
- const projectRoot = getProjectRoot15();
28629
+ const projectRoot = getProjectRoot16();
28245
28630
  const sagaId = typeof params.sagaId === "string" ? params.sagaId : "";
28246
28631
  const epicId = typeof params.epicId === "string" ? params.epicId : "";
28247
28632
  if (!sagaId || !epicId) {
@@ -28279,7 +28664,7 @@ async function sagaAdd(params) {
28279
28664
  return lafsSuccess({ sagaId, epicId, added: relResult.data?.added ?? true }, "saga.add");
28280
28665
  }
28281
28666
  async function sagaList() {
28282
- const projectRoot = getProjectRoot15();
28667
+ const projectRoot = getProjectRoot16();
28283
28668
  const result = await taskList(projectRoot, { type: "epic", label: "saga" });
28284
28669
  if (!result.success) {
28285
28670
  return lafsError("E_GENERAL", result.error?.message ?? "Failed to list Sagas", "saga.list");
@@ -28292,7 +28677,7 @@ async function sagaList() {
28292
28677
  return lafsSuccess({ sagas: topLevel, total: topLevel.length }, "saga.list");
28293
28678
  }
28294
28679
  async function sagaMembers(params) {
28295
- const projectRoot = getProjectRoot15();
28680
+ const projectRoot = getProjectRoot16();
28296
28681
  const sagaId = typeof params.sagaId === "string" ? params.sagaId : "";
28297
28682
  if (!sagaId) {
28298
28683
  return lafsError("E_INVALID_INPUT", "sagaId is required", "saga.members");
@@ -28317,7 +28702,7 @@ async function sagaMembers(params) {
28317
28702
  );
28318
28703
  }
28319
28704
  async function sagaRollup(params) {
28320
- const projectRoot = getProjectRoot15();
28705
+ const projectRoot = getProjectRoot16();
28321
28706
  const sagaId = typeof params.sagaId === "string" ? params.sagaId : "";
28322
28707
  if (!sagaId) {
28323
28708
  return lafsError("E_INVALID_INPUT", "sagaId is required", "saga.rollup");
@@ -28369,7 +28754,7 @@ var init_tasks3 = __esm({
28369
28754
  // Query ops
28370
28755
  // -------------------------------------------------------------------------
28371
28756
  show: async (params) => {
28372
- const projectRoot = getProjectRoot15();
28757
+ const projectRoot = getProjectRoot16();
28373
28758
  if (params.ivtrHistory) {
28374
28759
  return wrapCoreResult(await taskShowIvtrHistory(projectRoot, params.taskId), "show");
28375
28760
  }
@@ -28379,7 +28764,7 @@ var init_tasks3 = __esm({
28379
28764
  return wrapCoreResult(await taskShow(projectRoot, params.taskId), "show");
28380
28765
  },
28381
28766
  list: async (params) => {
28382
- const projectRoot = getProjectRoot15();
28767
+ const projectRoot = getProjectRoot16();
28383
28768
  const result = await taskList(projectRoot, {
28384
28769
  parent: params.parent,
28385
28770
  status: params.status,
@@ -28405,7 +28790,7 @@ var init_tasks3 = __esm({
28405
28790
  return lafsSuccess(result.data, "list");
28406
28791
  },
28407
28792
  find: async (params) => {
28408
- const projectRoot = getProjectRoot15();
28793
+ const projectRoot = getProjectRoot16();
28409
28794
  return wrapCoreResult(
28410
28795
  await taskFind(projectRoot, params.query, params.limit, {
28411
28796
  id: params.id,
@@ -28422,15 +28807,15 @@ var init_tasks3 = __esm({
28422
28807
  );
28423
28808
  },
28424
28809
  tree: async (params) => {
28425
- const projectRoot = getProjectRoot15();
28810
+ const projectRoot = getProjectRoot16();
28426
28811
  return wrapCoreResult(await taskTree(projectRoot, params.taskId, params.withBlockers), "tree");
28427
28812
  },
28428
28813
  blockers: async (params) => {
28429
- const projectRoot = getProjectRoot15();
28814
+ const projectRoot = getProjectRoot16();
28430
28815
  return wrapCoreResult(await taskBlockers(projectRoot, params), "blockers");
28431
28816
  },
28432
28817
  depends: async (params) => {
28433
- const projectRoot = getProjectRoot15();
28818
+ const projectRoot = getProjectRoot16();
28434
28819
  if (params.action === "overview") {
28435
28820
  return wrapCoreResult(await taskDepsOverview(projectRoot), "depends");
28436
28821
  }
@@ -28450,14 +28835,14 @@ var init_tasks3 = __esm({
28450
28835
  );
28451
28836
  },
28452
28837
  "deps.validate": async (params) => {
28453
- const projectRoot = getProjectRoot15();
28838
+ const projectRoot = getProjectRoot16();
28454
28839
  return wrapCoreResult(
28455
28840
  await taskDepsValidate(projectRoot, params.epicId, params.scope),
28456
28841
  "deps.validate"
28457
28842
  );
28458
28843
  },
28459
28844
  "deps.tree": async (params) => {
28460
- const projectRoot = getProjectRoot15();
28845
+ const projectRoot = getProjectRoot16();
28461
28846
  if (!params.epicId) {
28462
28847
  return lafsError("E_INVALID_INPUT", "epicId is required for deps.tree", "deps.tree");
28463
28848
  }
@@ -28467,29 +28852,29 @@ var init_tasks3 = __esm({
28467
28852
  );
28468
28853
  },
28469
28854
  analyze: async (params) => {
28470
- const projectRoot = getProjectRoot15();
28855
+ const projectRoot = getProjectRoot16();
28471
28856
  return wrapCoreResult(
28472
28857
  await taskAnalyze(projectRoot, params.taskId, { tierLimit: params.tierLimit }),
28473
28858
  "analyze"
28474
28859
  );
28475
28860
  },
28476
28861
  impact: async (params) => {
28477
- const projectRoot = getProjectRoot15();
28862
+ const projectRoot = getProjectRoot16();
28478
28863
  return wrapCoreResult(
28479
28864
  await taskImpact(projectRoot, params.change, params.matchLimit),
28480
28865
  "impact"
28481
28866
  );
28482
28867
  },
28483
28868
  next: async (params) => {
28484
- const projectRoot = getProjectRoot15();
28869
+ const projectRoot = getProjectRoot16();
28485
28870
  return wrapCoreResult(await taskNext(projectRoot, params), "next");
28486
28871
  },
28487
28872
  plan: async (_params) => {
28488
- const projectRoot = getProjectRoot15();
28873
+ const projectRoot = getProjectRoot16();
28489
28874
  return wrapCoreResult(await taskPlan(projectRoot), "plan");
28490
28875
  },
28491
28876
  relates: async (params) => {
28492
- const projectRoot = getProjectRoot15();
28877
+ const projectRoot = getProjectRoot16();
28493
28878
  if (params.mode) {
28494
28879
  return wrapCoreResult(
28495
28880
  await taskRelatesFind(projectRoot, params.taskId, {
@@ -28502,36 +28887,36 @@ var init_tasks3 = __esm({
28502
28887
  return wrapCoreResult(await taskRelates(projectRoot, params.taskId), "relates");
28503
28888
  },
28504
28889
  "complexity.estimate": async (params) => {
28505
- const projectRoot = getProjectRoot15();
28890
+ const projectRoot = getProjectRoot16();
28506
28891
  return wrapCoreResult(
28507
28892
  await taskComplexityEstimate(projectRoot, { taskId: params.taskId }),
28508
28893
  "complexity.estimate"
28509
28894
  );
28510
28895
  },
28511
28896
  history: async (params) => {
28512
- const projectRoot = getProjectRoot15();
28897
+ const projectRoot = getProjectRoot16();
28513
28898
  if (params.taskId) {
28514
28899
  return wrapCoreResult(await taskHistory(projectRoot, params.taskId, params.limit), "history");
28515
28900
  }
28516
28901
  return wrapCoreResult(await taskWorkHistory(projectRoot), "history");
28517
28902
  },
28518
28903
  current: async (_params) => {
28519
- const projectRoot = getProjectRoot15();
28904
+ const projectRoot = getProjectRoot16();
28520
28905
  return wrapCoreResult(await taskCurrentGet(projectRoot), "current");
28521
28906
  },
28522
28907
  "label.list": async (_params) => {
28523
- const projectRoot = getProjectRoot15();
28908
+ const projectRoot = getProjectRoot16();
28524
28909
  return wrapCoreResult(await taskLabelList(projectRoot), "label.list");
28525
28910
  },
28526
28911
  "sync.links": async (params) => {
28527
- const projectRoot = getProjectRoot15();
28912
+ const projectRoot = getProjectRoot16();
28528
28913
  return wrapCoreResult(await taskSyncLinks(projectRoot, params), "sync.links");
28529
28914
  },
28530
28915
  // -------------------------------------------------------------------------
28531
28916
  // Mutate ops
28532
28917
  // -------------------------------------------------------------------------
28533
28918
  add: async (params) => {
28534
- const projectRoot = getProjectRoot15();
28919
+ const projectRoot = getProjectRoot16();
28535
28920
  return wrapCoreResult(
28536
28921
  await addTaskWithSessionScope(projectRoot, {
28537
28922
  title: params.title,
@@ -28559,7 +28944,7 @@ var init_tasks3 = __esm({
28559
28944
  );
28560
28945
  },
28561
28946
  update: async (params) => {
28562
- const projectRoot = getProjectRoot15();
28947
+ const projectRoot = getProjectRoot16();
28563
28948
  return wrapCoreResult(
28564
28949
  await taskUpdate(projectRoot, params.taskId, {
28565
28950
  title: params.title,
@@ -28602,7 +28987,7 @@ var init_tasks3 = __esm({
28602
28987
  );
28603
28988
  },
28604
28989
  complete: async (params) => {
28605
- const projectRoot = getProjectRoot15();
28990
+ const projectRoot = getProjectRoot16();
28606
28991
  if (params.force !== void 0) {
28607
28992
  return lafsError(
28608
28993
  "E_FLAG_REMOVED",
@@ -28625,15 +29010,15 @@ var init_tasks3 = __esm({
28625
29010
  return wrapCoreResult(result, "complete");
28626
29011
  },
28627
29012
  cancel: async (params) => {
28628
- const projectRoot = getProjectRoot15();
29013
+ const projectRoot = getProjectRoot16();
28629
29014
  return wrapCoreResult(await taskCancel(projectRoot, params.taskId, params.reason), "cancel");
28630
29015
  },
28631
29016
  delete: async (params) => {
28632
- const projectRoot = getProjectRoot15();
29017
+ const projectRoot = getProjectRoot16();
28633
29018
  return wrapCoreResult(await taskDelete(projectRoot, params.taskId, params.force), "delete");
28634
29019
  },
28635
29020
  archive: async (params) => {
28636
- const projectRoot = getProjectRoot15();
29021
+ const projectRoot = getProjectRoot16();
28637
29022
  return wrapCoreResult(
28638
29023
  await taskArchive(projectRoot, params.taskId, params.before, {
28639
29024
  taskIds: params.taskIds,
@@ -28644,7 +29029,7 @@ var init_tasks3 = __esm({
28644
29029
  );
28645
29030
  },
28646
29031
  restore: async (params) => {
28647
- const projectRoot = getProjectRoot15();
29032
+ const projectRoot = getProjectRoot16();
28648
29033
  if (params.from === "done") {
28649
29034
  return wrapCoreResult(
28650
29035
  await taskReopen(projectRoot, params.taskId, {
@@ -28672,21 +29057,21 @@ var init_tasks3 = __esm({
28672
29057
  );
28673
29058
  },
28674
29059
  reparent: async (params) => {
28675
- const projectRoot = getProjectRoot15();
29060
+ const projectRoot = getProjectRoot16();
28676
29061
  return wrapCoreResult(
28677
29062
  await taskReparent(projectRoot, params.taskId, params.newParentId ?? null),
28678
29063
  "reparent"
28679
29064
  );
28680
29065
  },
28681
29066
  reorder: async (params) => {
28682
- const projectRoot = getProjectRoot15();
29067
+ const projectRoot = getProjectRoot16();
28683
29068
  return wrapCoreResult(
28684
29069
  await taskReorder(projectRoot, params.taskId, params.position),
28685
29070
  "reorder"
28686
29071
  );
28687
29072
  },
28688
29073
  "relates.add": async (params) => {
28689
- const projectRoot = getProjectRoot15();
29074
+ const projectRoot = getProjectRoot16();
28690
29075
  const relatedId = params.relatedId ?? params.targetId;
28691
29076
  if (!relatedId) {
28692
29077
  return lafsError("E_INVALID_INPUT", "relatedId (or targetId) is required", "relates.add");
@@ -28697,7 +29082,7 @@ var init_tasks3 = __esm({
28697
29082
  );
28698
29083
  },
28699
29084
  "relates.remove": async (params) => {
28700
- const projectRoot = getProjectRoot15();
29085
+ const projectRoot = getProjectRoot16();
28701
29086
  if (!params.relatedId) {
28702
29087
  return lafsError("E_INVALID_INPUT", "relatedId is required", "relates.remove");
28703
29088
  }
@@ -28707,15 +29092,15 @@ var init_tasks3 = __esm({
28707
29092
  );
28708
29093
  },
28709
29094
  start: async (params) => {
28710
- const projectRoot = getProjectRoot15();
29095
+ const projectRoot = getProjectRoot16();
28711
29096
  return wrapCoreResult(await taskStart(projectRoot, params.taskId), "start");
28712
29097
  },
28713
29098
  stop: async (_params) => {
28714
- const projectRoot = getProjectRoot15();
29099
+ const projectRoot = getProjectRoot16();
28715
29100
  return wrapCoreResult(await taskStop(projectRoot), "stop");
28716
29101
  },
28717
29102
  "sync.reconcile": async (params) => {
28718
- const projectRoot = getProjectRoot15();
29103
+ const projectRoot = getProjectRoot16();
28719
29104
  return wrapCoreResult(
28720
29105
  await taskSyncReconcile(projectRoot, {
28721
29106
  providerId: params.providerId,
@@ -28729,18 +29114,18 @@ var init_tasks3 = __esm({
28729
29114
  );
28730
29115
  },
28731
29116
  "sync.links.remove": async (params) => {
28732
- const projectRoot = getProjectRoot15();
29117
+ const projectRoot = getProjectRoot16();
28733
29118
  return wrapCoreResult(
28734
29119
  await taskSyncLinksRemove(projectRoot, params.providerId),
28735
29120
  "sync.links.remove"
28736
29121
  );
28737
29122
  },
28738
29123
  claim: async (params) => {
28739
- const projectRoot = getProjectRoot15();
29124
+ const projectRoot = getProjectRoot16();
28740
29125
  return wrapCoreResult(await taskClaim(projectRoot, params.taskId, params.agentId), "claim");
28741
29126
  },
28742
29127
  unclaim: async (params) => {
28743
- const projectRoot = getProjectRoot15();
29128
+ const projectRoot = getProjectRoot16();
28744
29129
  return wrapCoreResult(await taskUnclaim(projectRoot, params.taskId), "unclaim");
28745
29130
  }
28746
29131
  });
@@ -28829,7 +29214,7 @@ var init_tasks3 = __esm({
28829
29214
  return wrapResult(envelopeToEngineResult(envelope), "query", "tasks", operation, startTime);
28830
29215
  }
28831
29216
  } catch (error) {
28832
- getLogger14("domain:tasks").error(
29217
+ getLogger15("domain:tasks").error(
28833
29218
  { gateway: "query", domain: "tasks", operation, err: error },
28834
29219
  error instanceof Error ? error.message : String(error)
28835
29220
  );
@@ -28843,7 +29228,7 @@ var init_tasks3 = __esm({
28843
29228
  );
28844
29229
  return wrapResult(envelopeToEngineResult(envelope), "query", "tasks", operation, startTime);
28845
29230
  } catch (error) {
28846
- getLogger14("domain:tasks").error(
29231
+ getLogger15("domain:tasks").error(
28847
29232
  { gateway: "query", domain: "tasks", operation, err: error },
28848
29233
  error instanceof Error ? error.message : String(error)
28849
29234
  );
@@ -28886,7 +29271,7 @@ var init_tasks3 = __esm({
28886
29271
  );
28887
29272
  }
28888
29273
  } catch (error) {
28889
- getLogger14("domain:tasks").error(
29274
+ getLogger15("domain:tasks").error(
28890
29275
  { gateway: "mutate", domain: "tasks", operation, err: error },
28891
29276
  error instanceof Error ? error.message : String(error)
28892
29277
  );
@@ -28900,7 +29285,7 @@ var init_tasks3 = __esm({
28900
29285
  );
28901
29286
  return wrapResult(envelopeToEngineResult(envelope), "mutate", "tasks", operation, startTime);
28902
29287
  } catch (error) {
28903
- getLogger14("domain:tasks").error(
29288
+ getLogger15("domain:tasks").error(
28904
29289
  { gateway: "mutate", domain: "tasks", operation, err: error },
28905
29290
  error instanceof Error ? error.message : String(error)
28906
29291
  );
@@ -28966,7 +29351,7 @@ var init_tasks3 = __esm({
28966
29351
  });
28967
29352
 
28968
29353
  // packages/cleo/src/dispatch/domains/tools.ts
28969
- import { getLogger as getLogger15, getProjectRoot as getProjectRoot16 } from "@cleocode/core";
29354
+ import { getLogger as getLogger16, getProjectRoot as getProjectRoot17 } from "@cleocode/core";
28970
29355
  import {
28971
29356
  codeOutline,
28972
29357
  codeParse,
@@ -29011,7 +29396,7 @@ var init_tools = __esm({
29011
29396
  init_routing();
29012
29397
  ToolsHandler = class {
29013
29398
  get projectRoot() {
29014
- return getProjectRoot16();
29399
+ return getProjectRoot17();
29015
29400
  }
29016
29401
  // -----------------------------------------------------------------------
29017
29402
  // DomainHandler interface
@@ -29524,13 +29909,295 @@ var init_tools = __esm({
29524
29909
  // -----------------------------------------------------------------------
29525
29910
  handleError(gateway, domain, operation, error, startTime) {
29526
29911
  const message = error instanceof Error ? error.message : String(error);
29527
- getLogger15("domain:tools").error({ gateway, domain, operation, err: error }, message);
29912
+ getLogger16("domain:tools").error({ gateway, domain, operation, err: error }, message);
29528
29913
  return handleErrorResult(gateway, domain, operation, error, startTime);
29529
29914
  }
29530
29915
  };
29531
29916
  }
29532
29917
  });
29533
29918
 
29919
+ // packages/cleo/src/dispatch/domains/upgrade.ts
29920
+ import { dirname as dirname3, resolve as resolve3 } from "node:path";
29921
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
29922
+ import { getLogger as getLogger17, getProjectRoot as getProjectRoot18 } from "@cleocode/core";
29923
+ import { upgradeWorkflows } from "@cleocode/core/internal";
29924
+ function resolveTemplatesDir() {
29925
+ const here = dirname3(fileURLToPath2(import.meta.url));
29926
+ return resolve3(here, "..", "..", "..", "templates", "workflows");
29927
+ }
29928
+ function toDispatchData(result) {
29929
+ return {
29930
+ outcomes: result.outcomes.map((o) => ({
29931
+ template: o.template,
29932
+ targetPath: o.targetPath,
29933
+ status: o.status,
29934
+ overrideDeclared: o.overrideDeclared
29935
+ })),
29936
+ resolvedTools: result.resolvedTools,
29937
+ hasDrift: result.hasDrift
29938
+ };
29939
+ }
29940
+ var log5, UpgradeHandler;
29941
+ var init_upgrade = __esm({
29942
+ "packages/cleo/src/dispatch/domains/upgrade.ts"() {
29943
+ "use strict";
29944
+ init_base();
29945
+ init_meta2();
29946
+ log5 = getLogger17("domain:upgrade");
29947
+ UpgradeHandler = class {
29948
+ /**
29949
+ * Handle read-only upgrade queries.
29950
+ *
29951
+ * Supported operations:
29952
+ * - `workflows` — drift detection only; never writes to disk.
29953
+ * Effectively forces `dryRun=true` at the query gateway.
29954
+ */
29955
+ async query(operation, params) {
29956
+ const startTime = Date.now();
29957
+ try {
29958
+ switch (operation) {
29959
+ case "workflows": {
29960
+ const includeRendered = params?.["includeRendered"] === true;
29961
+ const result = await upgradeWorkflows({
29962
+ projectRoot: getProjectRoot18(),
29963
+ templatesDir: resolveTemplatesDir(),
29964
+ dryRun: true
29965
+ });
29966
+ const data = toDispatchData(result);
29967
+ return {
29968
+ meta: dispatchMeta("query", "upgrade", operation, startTime),
29969
+ success: true,
29970
+ data: includeRendered ? {
29971
+ ...data,
29972
+ rendered: result.outcomes.map((o) => ({
29973
+ template: o.template,
29974
+ rendered: o.rendered
29975
+ }))
29976
+ } : data
29977
+ };
29978
+ }
29979
+ default:
29980
+ return unsupportedOp("query", "upgrade", operation, startTime);
29981
+ }
29982
+ } catch (err) {
29983
+ log5.error({ err, operation }, "UpgradeHandler query error");
29984
+ return handleErrorResult("query", "upgrade", operation, err, startTime);
29985
+ }
29986
+ }
29987
+ /**
29988
+ * Handle upgrade mutations.
29989
+ *
29990
+ * Supported operations:
29991
+ * - `workflows` — re-render + (optionally) re-write drifted files.
29992
+ * Params: `{ force?, dryRun? }`. Returns the per-template
29993
+ * outcomes plus the `hasDrift` flag the CLI uses to drive
29994
+ * the `--check` exit-code contract.
29995
+ */
29996
+ async mutate(operation, params) {
29997
+ const startTime = Date.now();
29998
+ try {
29999
+ switch (operation) {
30000
+ case "workflows": {
30001
+ const force = params?.["force"] === true;
30002
+ const dryRun = params?.["dryRun"] === true;
30003
+ const includeRendered = params?.["includeRendered"] === true;
30004
+ const result = await upgradeWorkflows({
30005
+ projectRoot: getProjectRoot18(),
30006
+ templatesDir: resolveTemplatesDir(),
30007
+ force,
30008
+ dryRun
30009
+ });
30010
+ const data = toDispatchData(result);
30011
+ return {
30012
+ meta: dispatchMeta("mutate", "upgrade", operation, startTime),
30013
+ success: true,
30014
+ data: includeRendered ? {
30015
+ ...data,
30016
+ rendered: result.outcomes.map((o) => ({
30017
+ template: o.template,
30018
+ rendered: o.rendered
30019
+ }))
30020
+ } : data
30021
+ };
30022
+ }
30023
+ default:
30024
+ return unsupportedOp("mutate", "upgrade", operation, startTime);
30025
+ }
30026
+ } catch (err) {
30027
+ log5.error({ err, operation }, "UpgradeHandler mutate error");
30028
+ return handleErrorResult("mutate", "upgrade", operation, err, startTime);
30029
+ }
30030
+ }
30031
+ /** Declared operations for introspection and validation. */
30032
+ getSupportedOperations() {
30033
+ return {
30034
+ query: ["workflows"],
30035
+ mutate: ["workflows"]
30036
+ };
30037
+ }
30038
+ };
30039
+ }
30040
+ });
30041
+
30042
+ // packages/cleo/src/dispatch/domains/worktree.ts
30043
+ import {
30044
+ forceUnlockWorktree,
30045
+ getLogger as getLogger18,
30046
+ getProjectRoot as getProjectRoot19,
30047
+ listWorktrees,
30048
+ pruneOrphanedWorktreesByStatus
30049
+ } from "@cleocode/core/internal";
30050
+ function coerceStatusFilter(value) {
30051
+ if (value === void 0 || value === null) return void 0;
30052
+ const raw = Array.isArray(value) ? value.filter((v) => typeof v === "string") : typeof value === "string" ? value.split(",").map((s) => s.trim()) : [];
30053
+ const out = raw.filter(
30054
+ (s) => ALL_CATEGORIES.includes(s)
30055
+ );
30056
+ return out.length > 0 ? out : void 0;
30057
+ }
30058
+ function coerceStringList(value) {
30059
+ if (value === void 0 || value === null) return void 0;
30060
+ if (Array.isArray(value)) {
30061
+ const out = value.filter((v) => typeof v === "string");
30062
+ return out.length > 0 ? out : void 0;
30063
+ }
30064
+ if (typeof value === "string") {
30065
+ const parts = value.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
30066
+ return parts.length > 0 ? parts : void 0;
30067
+ }
30068
+ return void 0;
30069
+ }
30070
+ var log6, ALL_CATEGORIES, WorktreeHandler;
30071
+ var init_worktree2 = __esm({
30072
+ "packages/cleo/src/dispatch/domains/worktree.ts"() {
30073
+ "use strict";
30074
+ init_base();
30075
+ log6 = getLogger18("domain:worktree");
30076
+ ALL_CATEGORIES = [
30077
+ "active",
30078
+ "stale",
30079
+ "merged",
30080
+ "orphan",
30081
+ "locked"
30082
+ ];
30083
+ WorktreeHandler = class {
30084
+ /**
30085
+ * Handle read-only worktree queries.
30086
+ *
30087
+ * Supported operations:
30088
+ * - `list` — return a structured listing of every worktree with status
30089
+ * classification. Params: `{ statusFilter?, staleDays? }`.
30090
+ */
30091
+ async query(operation, params) {
30092
+ const startTime = Date.now();
30093
+ try {
30094
+ switch (operation) {
30095
+ case "list": {
30096
+ const opts = {
30097
+ projectRoot: getProjectRoot19(),
30098
+ statusFilter: coerceStatusFilter(params?.["statusFilter"]),
30099
+ staleDays: typeof params?.["staleDays"] === "number" ? params["staleDays"] : void 0
30100
+ };
30101
+ const result = await listWorktrees(opts);
30102
+ return wrapResult(
30103
+ result,
30104
+ "query",
30105
+ "worktree",
30106
+ operation,
30107
+ startTime
30108
+ );
30109
+ }
30110
+ default:
30111
+ return unsupportedOp("query", "worktree", operation, startTime);
30112
+ }
30113
+ } catch (err) {
30114
+ log6.error({ err, operation }, "WorktreeHandler query error");
30115
+ return handleErrorResult("query", "worktree", operation, err, startTime);
30116
+ }
30117
+ }
30118
+ /**
30119
+ * Handle worktree mutations.
30120
+ *
30121
+ * Supported operations:
30122
+ * - `prune` — remove orphan/merged worktrees. Params:
30123
+ * `{ dryRun?, staleDays?, paths?, actor? }`. Returns a
30124
+ * {@link PruneOrphanedWorktreesResult} envelope.
30125
+ * - `forceUnlock` — clear wedge state for a single worktree. Params:
30126
+ * `{ taskId, actor? }`. Returns a {@link ForceUnlockWorktreeResult}.
30127
+ *
30128
+ * @task T9547
30129
+ */
30130
+ async mutate(operation, params) {
30131
+ const startTime = Date.now();
30132
+ try {
30133
+ switch (operation) {
30134
+ case "prune": {
30135
+ const opts = {
30136
+ projectRoot: getProjectRoot19(),
30137
+ dryRun: params?.["dryRun"] === true,
30138
+ ...typeof params?.["staleDays"] === "number" ? { staleDays: params["staleDays"] } : {},
30139
+ ...coerceStringList(params?.["paths"]) !== void 0 ? { paths: coerceStringList(params?.["paths"]) } : {},
30140
+ ...typeof params?.["actor"] === "string" && params["actor"].length > 0 ? { actor: params["actor"] } : {}
30141
+ };
30142
+ const result = await pruneOrphanedWorktreesByStatus(opts);
30143
+ return wrapResult(
30144
+ result,
30145
+ "mutate",
30146
+ "worktree",
30147
+ operation,
30148
+ startTime
30149
+ );
30150
+ }
30151
+ case "forceUnlock": {
30152
+ const taskId = params?.["taskId"];
30153
+ if (typeof taskId !== "string" || taskId.length === 0) {
30154
+ return errorResult(
30155
+ "mutate",
30156
+ "worktree",
30157
+ operation,
30158
+ "E_VALIDATION",
30159
+ "Missing required param: taskId (pass --task-id T####).",
30160
+ startTime
30161
+ );
30162
+ }
30163
+ const opts = {
30164
+ projectRoot: getProjectRoot19(),
30165
+ taskId,
30166
+ ...typeof params?.["actor"] === "string" && params["actor"].length > 0 ? { actor: params["actor"] } : {}
30167
+ };
30168
+ const result = await forceUnlockWorktree(opts);
30169
+ return wrapResult(
30170
+ result,
30171
+ "mutate",
30172
+ "worktree",
30173
+ operation,
30174
+ startTime
30175
+ );
30176
+ }
30177
+ default:
30178
+ return unsupportedOp("mutate", "worktree", operation, startTime);
30179
+ }
30180
+ } catch (err) {
30181
+ log6.error({ err, operation }, "WorktreeHandler mutate error");
30182
+ return handleErrorResult("mutate", "worktree", operation, err, startTime);
30183
+ }
30184
+ }
30185
+ /**
30186
+ * Declare the operations this domain supports — feeds dispatch introspection
30187
+ * and the `cleo --help` rendering pipeline.
30188
+ *
30189
+ * @returns Query/mutate operation lists.
30190
+ */
30191
+ getSupportedOperations() {
30192
+ return {
30193
+ query: ["list"],
30194
+ mutate: ["prune", "forceUnlock"]
30195
+ };
30196
+ }
30197
+ };
30198
+ }
30199
+ });
30200
+
29534
30201
  // packages/cleo/src/dispatch/domains/index.ts
29535
30202
  function createDomainHandlers() {
29536
30203
  const handlers = /* @__PURE__ */ new Map();
@@ -29551,7 +30218,10 @@ function createDomainHandlers() {
29551
30218
  handlers.set("conduit", new ConduitHandler());
29552
30219
  handlers.set("sentient", new SentientHandler());
29553
30220
  handlers.set("release", new ReleaseHandler());
30221
+ handlers.set("provenance", new ProvenanceHandler());
29554
30222
  handlers.set("llm", new LlmHandler());
30223
+ handlers.set("worktree", new WorktreeHandler());
30224
+ handlers.set("upgrade", new UpgradeHandler());
29555
30225
  return handlers;
29556
30226
  }
29557
30227
  var init_domains = __esm({
@@ -29569,12 +30239,15 @@ var init_domains = __esm({
29569
30239
  init_orchestrate2();
29570
30240
  init_pipeline3();
29571
30241
  init_playbook2();
30242
+ init_provenance();
29572
30243
  init_release2();
29573
30244
  init_sentient2();
29574
30245
  init_session3();
29575
30246
  init_sticky2();
29576
30247
  init_tasks3();
29577
30248
  init_tools();
30249
+ init_upgrade();
30250
+ init_worktree2();
29578
30251
  }
29579
30252
  });
29580
30253
 
@@ -29814,7 +30487,7 @@ var init_config = __esm({
29814
30487
  });
29815
30488
 
29816
30489
  // packages/cleo/src/dispatch/middleware/audit.ts
29817
- import { getLogger as getLogger16, getProjectInfoSync } from "@cleocode/core/internal";
30490
+ import { getLogger as getLogger19, getProjectInfoSync } from "@cleocode/core/internal";
29818
30491
  import { queryAudit } from "@cleocode/core/internal";
29819
30492
  function resolveProjectHash() {
29820
30493
  if (cachedProjectHash !== void 0) return cachedProjectHash;
@@ -29868,7 +30541,7 @@ async function writeToSqlite(entry, requestId) {
29868
30541
  };
29869
30542
  const parsed = AuditLogInsertSchema.safeParse(payload);
29870
30543
  if (!parsed.success) {
29871
- log4.warn(
30544
+ log7.warn(
29872
30545
  { issues: parsed.error.issues },
29873
30546
  "Audit payload failed Zod validation; skipping insert"
29874
30547
  );
@@ -29877,7 +30550,7 @@ async function writeToSqlite(entry, requestId) {
29877
30550
  const db = await getDb3(process.cwd());
29878
30551
  await db.insert(auditLog).values(parsed.data).run();
29879
30552
  } catch (err) {
29880
- log4.warn({ err }, "Failed to write audit entry to SQLite");
30553
+ log7.warn({ err }, "Failed to write audit entry to SQLite");
29881
30554
  }
29882
30555
  }
29883
30556
  function createAudit() {
@@ -29908,7 +30581,7 @@ function createAudit() {
29908
30581
  },
29909
30582
  error: response.error?.message
29910
30583
  };
29911
- log4.info(
30584
+ log7.info(
29912
30585
  {
29913
30586
  domain: entry.domain,
29914
30587
  operation: entry.operation,
@@ -29925,18 +30598,18 @@ function createAudit() {
29925
30598
  await writeToSqlite(entry, req.requestId);
29926
30599
  } else {
29927
30600
  writeToSqlite(entry, req.requestId).catch((err) => {
29928
- log4.error({ err }, "Failed to persist audit entry to SQLite");
30601
+ log7.error({ err }, "Failed to persist audit entry to SQLite");
29929
30602
  });
29930
30603
  }
29931
30604
  return response;
29932
30605
  };
29933
30606
  }
29934
- var log4, cachedProjectHash;
30607
+ var log7, cachedProjectHash;
29935
30608
  var init_audit = __esm({
29936
30609
  "packages/cleo/src/dispatch/middleware/audit.ts"() {
29937
30610
  "use strict";
29938
30611
  init_config();
29939
- log4 = getLogger16("audit");
30612
+ log7 = getLogger19("audit");
29940
30613
  }
29941
30614
  });
29942
30615
 
@@ -30011,11 +30684,11 @@ var init_security = __esm({
30011
30684
  });
30012
30685
 
30013
30686
  // packages/cleo/src/dispatch/middleware/sanitizer.ts
30014
- function createSanitizer(getProjectRoot34) {
30687
+ function createSanitizer(getProjectRoot38) {
30015
30688
  return async (req, next) => {
30016
30689
  if (req.params) {
30017
30690
  try {
30018
- const root = getProjectRoot34 ? getProjectRoot34() : void 0;
30691
+ const root = getProjectRoot38 ? getProjectRoot38() : void 0;
30019
30692
  req.params = sanitizeParams(req.params, root, {
30020
30693
  domain: req.domain,
30021
30694
  operation: req.operation
@@ -30137,10 +30810,10 @@ __export(cli_exports, {
30137
30810
  import { randomUUID as randomUUID5 } from "node:crypto";
30138
30811
  import { existsSync as existsSync4 } from "node:fs";
30139
30812
  import { createRequire } from "node:module";
30140
- import { dirname as dirname3, join as join6 } from "node:path";
30141
- import { fileURLToPath as fileURLToPath2 } from "node:url";
30813
+ import { dirname as dirname4, join as join6 } from "node:path";
30814
+ import { fileURLToPath as fileURLToPath3 } from "node:url";
30142
30815
  import { catalog, registerSkillLibraryFromPath } from "@cleocode/caamp";
30143
- import { autoRecordDispatchTokenUsage, getProjectRoot as getProjectRoot17, hooks } from "@cleocode/core/internal";
30816
+ import { autoRecordDispatchTokenUsage, getProjectRoot as getProjectRoot20, hooks } from "@cleocode/core/internal";
30144
30817
  function ensureCaampLibrary() {
30145
30818
  if (catalog.isCatalogAvailable()) return;
30146
30819
  try {
@@ -30148,15 +30821,15 @@ function ensureCaampLibrary() {
30148
30821
  try {
30149
30822
  const req = createRequire(import.meta.url);
30150
30823
  const skillsPkgJson = req.resolve("@cleocode/skills/package.json");
30151
- const candidate = dirname3(skillsPkgJson);
30824
+ const candidate = dirname4(skillsPkgJson);
30152
30825
  if (existsSync4(join6(candidate, "skills.json"))) {
30153
30826
  skillsRoot = candidate;
30154
30827
  }
30155
30828
  } catch {
30156
30829
  }
30157
30830
  if (!skillsRoot) {
30158
- const thisFile = fileURLToPath2(import.meta.url);
30159
- const packageRoot = join6(dirname3(thisFile), "..", "..", "..", "..", "..");
30831
+ const thisFile = fileURLToPath3(import.meta.url);
30832
+ const packageRoot = join6(dirname4(thisFile), "..", "..", "..", "..", "..");
30160
30833
  const candidate = join6(packageRoot, "packages", "skills");
30161
30834
  if (existsSync4(join6(candidate, "skills.json"))) {
30162
30835
  skillsRoot = candidate;
@@ -30191,7 +30864,7 @@ function createCliDispatcher() {
30191
30864
  middlewares: [
30192
30865
  createSessionResolver(lookupCliSession),
30193
30866
  // T4959: session identity first
30194
- createSanitizer(() => getProjectRoot17()),
30867
+ createSanitizer(() => getProjectRoot20()),
30195
30868
  createFieldFilter(),
30196
30869
  createAudit(),
30197
30870
  // T4959: CLI now gets audit trail
@@ -30205,7 +30878,7 @@ function resetCliDispatcher() {
30205
30878
  }
30206
30879
  async function dispatchFromCli(gateway, domain, operation, params, outputOpts) {
30207
30880
  const dispatcher = getCliDispatcher();
30208
- const projectRoot = getProjectRoot17();
30881
+ const projectRoot = getProjectRoot20();
30209
30882
  const dispatchStart = Date.now();
30210
30883
  hooks.dispatch("PromptSubmit", projectRoot, {
30211
30884
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
@@ -30250,7 +30923,7 @@ async function dispatchFromCli(gateway, domain, operation, params, outputOpts) {
30250
30923
  operation,
30251
30924
  sessionId: response.meta.sessionId,
30252
30925
  requestId: response.meta.requestId,
30253
- cwd: getProjectRoot17()
30926
+ cwd: getProjectRoot20()
30254
30927
  });
30255
30928
  const opts = {
30256
30929
  command: outputOpts?.command ?? operation,
@@ -30312,7 +30985,7 @@ function handleRawError(response, _opts) {
30312
30985
  }
30313
30986
  async function dispatchRaw(gateway, domain, operation, params) {
30314
30987
  const dispatcher = getCliDispatcher();
30315
- const projectRoot = getProjectRoot17();
30988
+ const projectRoot = getProjectRoot20();
30316
30989
  const dispatchStart = Date.now();
30317
30990
  hooks.dispatch("PromptSubmit", projectRoot, {
30318
30991
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
@@ -30707,7 +31380,7 @@ __export(add_exports, {
30707
31380
  });
30708
31381
  import {
30709
31382
  appendSignedSeverityAttestation,
30710
- getProjectRoot as getProjectRoot18,
31383
+ getProjectRoot as getProjectRoot21,
30711
31384
  inferTaskAddParams
30712
31385
  } from "@cleocode/core";
30713
31386
  var addCommand;
@@ -30935,7 +31608,7 @@ var init_add = __esm({
30935
31608
  return;
30936
31609
  }
30937
31610
  if (args["depends-waiver"] !== void 0) params["dependsWaiver"] = args["depends-waiver"];
30938
- const inferred = await inferTaskAddParams(getProjectRoot18(), {
31611
+ const inferred = await inferTaskAddParams(getProjectRoot21(), {
30939
31612
  title: args.title,
30940
31613
  description: args.description ?? args.desc,
30941
31614
  filesInfer: args["files-infer"],
@@ -33568,9 +34241,9 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
33568
34241
  let tempDir = null;
33569
34242
  try {
33570
34243
  const { existsSync: existsSync16, mkdirSync: mkdirSync7, statSync, readdirSync: readdirSync4, copyFileSync } = await import("node:fs");
33571
- const { join: join28, basename, resolve: resolve5, extname } = await import("node:path");
34244
+ const { join: join28, basename, resolve: resolve8, extname } = await import("node:path");
33572
34245
  const { tmpdir: tmpdir2 } = await import("node:os");
33573
- const resolvedPath = resolve5(args.path);
34246
+ const resolvedPath = resolve8(args.path);
33574
34247
  if (!existsSync16(resolvedPath)) {
33575
34248
  cliOutput(
33576
34249
  {
@@ -33787,9 +34460,9 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
33787
34460
  async run({ args }) {
33788
34461
  try {
33789
34462
  const { existsSync: existsSync16, statSync } = await import("node:fs");
33790
- const { resolve: resolve5, basename, dirname: dirname9 } = await import("node:path");
34463
+ const { resolve: resolve8, basename, dirname: dirname11 } = await import("node:path");
33791
34464
  const { execFileSync: execFileSync5 } = await import("node:child_process");
33792
- const resolvedDir = resolve5(args.dir);
34465
+ const resolvedDir = resolve8(args.dir);
33793
34466
  if (!existsSync16(resolvedDir) || !statSync(resolvedDir).isDirectory()) {
33794
34467
  cliOutput(
33795
34468
  {
@@ -33822,8 +34495,8 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
33822
34495
  }
33823
34496
  const agentName = basename(resolvedDir);
33824
34497
  const archiveName = `${agentName}.cantz`;
33825
- const archivePath = resolve5(archiveName);
33826
- const parentDir = dirname9(resolvedDir);
34498
+ const archivePath = resolve8(archiveName);
34499
+ const parentDir = dirname11(resolvedDir);
33827
34500
  try {
33828
34501
  execFileSync5("zip", ["-r", archivePath, agentName], {
33829
34502
  cwd: parentDir,
@@ -34134,8 +34807,8 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
34134
34807
  async run({ args }) {
34135
34808
  try {
34136
34809
  const { existsSync: existsSync16, readFileSync: readFileSync18, mkdirSync: mkdirSync7 } = await import("node:fs");
34137
- const { resolve: resolve5, join: join28 } = await import("node:path");
34138
- const specPath = resolve5(args.spec);
34810
+ const { resolve: resolve8, join: join28 } = await import("node:path");
34811
+ const specPath = resolve8(args.spec);
34139
34812
  if (!existsSync16(specPath)) {
34140
34813
  cliError(`spec file not found: ${specPath}`, 4, { name: "E_NOT_FOUND" });
34141
34814
  process.exitCode = 4;
@@ -34143,7 +34816,7 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
34143
34816
  }
34144
34817
  const specContent = readFileSync18(specPath, "utf-8");
34145
34818
  const projectRoot = process.cwd();
34146
- const outputDir = args["output-dir"] ? resolve5(args["output-dir"]) : join28(projectRoot, ".cleo", "cant", "agents");
34819
+ const outputDir = args["output-dir"] ? resolve8(args["output-dir"]) : join28(projectRoot, ".cleo", "cant", "agents");
34147
34820
  mkdirSync7(outputDir, { recursive: true });
34148
34821
  if (args["dry-run"]) {
34149
34822
  cliOutput(
@@ -34541,7 +35214,7 @@ var audit_exports = {};
34541
35214
  __export(audit_exports, {
34542
35215
  auditCommand: () => auditCommand
34543
35216
  });
34544
- import { getProjectRoot as getProjectRoot19, reconstructLineage } from "@cleocode/core/internal";
35217
+ import { getProjectRoot as getProjectRoot22, reconstructLineage } from "@cleocode/core/internal";
34545
35218
  var reconstructCommand, auditCommand;
34546
35219
  var init_audit2 = __esm({
34547
35220
  "packages/cleo/src/cli/commands/audit.ts"() {
@@ -34585,7 +35258,7 @@ var init_audit2 = __esm({
34585
35258
  repoRoot = args["repo-root"];
34586
35259
  } else {
34587
35260
  try {
34588
- repoRoot = getProjectRoot19(process.cwd()) ?? process.cwd();
35261
+ repoRoot = getProjectRoot22(process.cwd()) ?? process.cwd();
34589
35262
  } catch {
34590
35263
  repoRoot = process.cwd();
34591
35264
  }
@@ -34740,8 +35413,8 @@ function detectAuthType(provider, token) {
34740
35413
  async function promptYesNo(question) {
34741
35414
  const rl = createInterface({ input: process.stdin, output: process.stderr });
34742
35415
  try {
34743
- const answer = await new Promise((resolve5) => {
34744
- rl.question(question, (a) => resolve5(a));
35416
+ const answer = await new Promise((resolve8) => {
35417
+ rl.question(question, (a) => resolve8(a));
34745
35418
  });
34746
35419
  const clean = answer.trim().toLowerCase();
34747
35420
  return clean === "y" || clean === "yes";
@@ -35053,7 +35726,7 @@ var backfill_exports = {};
35053
35726
  __export(backfill_exports, {
35054
35727
  backfillCommand: () => backfillCommand
35055
35728
  });
35056
- import { backfillTasks, getProjectRoot as getProjectRoot20, populateEmbeddings } from "@cleocode/core/internal";
35729
+ import { backfillTasks, getProjectRoot as getProjectRoot23, populateEmbeddings } from "@cleocode/core/internal";
35057
35730
  var backfillCommand;
35058
35731
  var init_backfill = __esm({
35059
35732
  "packages/cleo/src/cli/commands/backfill.ts"() {
@@ -35087,7 +35760,7 @@ var init_backfill = __esm({
35087
35760
  }
35088
35761
  },
35089
35762
  async run({ args }) {
35090
- const root = getProjectRoot20();
35763
+ const root = getProjectRoot23();
35091
35764
  if (args.embeddings) {
35092
35765
  try {
35093
35766
  let lastLine = "";
@@ -35466,12 +36139,12 @@ async function promptPassphrase() {
35466
36139
  "Cannot prompt for passphrase: stdin is not a TTY. Set the CLEO_BACKUP_PASSPHRASE environment variable for non-interactive use."
35467
36140
  );
35468
36141
  }
35469
- return new Promise((resolve5) => {
36142
+ return new Promise((resolve8) => {
35470
36143
  process.stdout.write("Passphrase: ");
35471
36144
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
35472
36145
  rl.question("", (answer) => {
35473
36146
  rl.close();
35474
- resolve5(answer.trim());
36147
+ resolve8(answer.trim());
35475
36148
  });
35476
36149
  });
35477
36150
  }
@@ -35604,9 +36277,9 @@ var init_backup = __esm({
35604
36277
  },
35605
36278
  async run({ args }) {
35606
36279
  const scope = args.scope;
35607
- const { packBundle, getProjectRoot: getProjectRoot34 } = await import("@cleocode/core/internal");
36280
+ const { packBundle, getProjectRoot: getProjectRoot38 } = await import("@cleocode/core/internal");
35608
36281
  const includesProject = scope === "project" || scope === "all";
35609
- const projectRoot = includesProject ? getProjectRoot34() : void 0;
36282
+ const projectRoot = includesProject ? getProjectRoot38() : void 0;
35610
36283
  let passphrase;
35611
36284
  if (args.encrypt === true) {
35612
36285
  passphrase = process.env["CLEO_BACKUP_PASSPHRASE"];
@@ -35907,7 +36580,7 @@ import {
35907
36580
  exportBrainAsJson,
35908
36581
  getMemoryQualityReport,
35909
36582
  getPlasticityStats,
35910
- getProjectRoot as getProjectRoot21,
36583
+ getProjectRoot as getProjectRoot24,
35911
36584
  purgeBrainNoise,
35912
36585
  runBrainMaintenance
35913
36586
  } from "@cleocode/core/internal";
@@ -35946,7 +36619,7 @@ var init_brain2 = __esm({
35946
36619
  json: { type: "boolean", description: "Output results as JSON" }
35947
36620
  },
35948
36621
  async run({ args }) {
35949
- const root = getProjectRoot21();
36622
+ const root = getProjectRoot24();
35950
36623
  try {
35951
36624
  const result = await runBrainMaintenance(root, {
35952
36625
  skipDecay: !!args["skip-decay"],
@@ -36017,7 +36690,7 @@ var init_brain2 = __esm({
36017
36690
  json: { type: "boolean", description: "Output results as JSON" }
36018
36691
  },
36019
36692
  async run({ args: _args }) {
36020
- const root = getProjectRoot21();
36693
+ const root = getProjectRoot24();
36021
36694
  try {
36022
36695
  const result = await backfillBrainGraph(root);
36023
36696
  cliOutput(
@@ -36058,7 +36731,7 @@ var init_brain2 = __esm({
36058
36731
  json: { type: "boolean", description: "Output results as JSON" }
36059
36732
  },
36060
36733
  async run({ args: _args }) {
36061
- const root = getProjectRoot21();
36734
+ const root = getProjectRoot24();
36062
36735
  try {
36063
36736
  const result = await purgeBrainNoise(root);
36064
36737
  cliOutput(
@@ -36104,7 +36777,7 @@ var init_brain2 = __esm({
36104
36777
  json: { type: "boolean", description: "Output results as JSON" }
36105
36778
  },
36106
36779
  async run({ args }) {
36107
- const root = getProjectRoot21();
36780
+ const root = getProjectRoot24();
36108
36781
  const limit = Number.parseInt(args.limit, 10) || 20;
36109
36782
  try {
36110
36783
  const stats = await getPlasticityStats(root, limit);
@@ -36154,7 +36827,7 @@ var init_brain2 = __esm({
36154
36827
  json: { type: "boolean", description: "Output results as JSON" }
36155
36828
  },
36156
36829
  async run({ args: _args }) {
36157
- const root = getProjectRoot21();
36830
+ const root = getProjectRoot24();
36158
36831
  try {
36159
36832
  const report = await getMemoryQualityReport(root);
36160
36833
  cliOutput(
@@ -36203,7 +36876,7 @@ var init_brain2 = __esm({
36203
36876
  }
36204
36877
  },
36205
36878
  async run({ args }) {
36206
- const root = getProjectRoot21();
36879
+ const root = getProjectRoot24();
36207
36880
  const format = args.format ?? "gexf";
36208
36881
  if (format !== "gexf" && format !== "json") {
36209
36882
  cliError(`Invalid format: ${format}. Use 'gexf' or 'json'.`, "E_VALIDATION", {
@@ -36611,9 +37284,9 @@ __export(cant_exports, {
36611
37284
  cantCommand: () => cantCommand
36612
37285
  });
36613
37286
  import { existsSync as existsSync8, mkdirSync as mkdirSync2, readFileSync as readFileSync9, writeFileSync as writeFileSync3 } from "node:fs";
36614
- import { dirname as dirname4, isAbsolute, join as join10, resolve as resolve3 } from "node:path";
37287
+ import { dirname as dirname5, isAbsolute, join as join10, resolve as resolve4 } from "node:path";
36615
37288
  function resolveFilePath(file) {
36616
- return isAbsolute(file) ? file : resolve3(process.cwd(), file);
37289
+ return isAbsolute(file) ? file : resolve4(process.cwd(), file);
36617
37290
  }
36618
37291
  function ensureExists(filePath, operation) {
36619
37292
  if (existsSync8(filePath)) return true;
@@ -36777,7 +37450,7 @@ var init_cant = __esm({
36777
37450
  let written = 0;
36778
37451
  for (const outputFile of result.outputFiles) {
36779
37452
  const outputPath = isAbsolute(outputFile.path) ? outputFile.path : join10(projectRoot, outputFile.path);
36780
- mkdirSync2(dirname4(outputPath), { recursive: true });
37453
+ mkdirSync2(dirname5(outputPath), { recursive: true });
36781
37454
  writeFileSync3(outputPath, outputFile.content, "utf-8");
36782
37455
  written++;
36783
37456
  }
@@ -38774,7 +39447,7 @@ __export(daemon_exports, {
38774
39447
  import { existsSync as existsSync9 } from "node:fs";
38775
39448
  import { homedir as homedir4 } from "node:os";
38776
39449
  import { join as join11 } from "node:path";
38777
- import { fileURLToPath as fileURLToPath3 } from "node:url";
39450
+ import { fileURLToPath as fileURLToPath4 } from "node:url";
38778
39451
  import { getGCDaemonStatus, spawnGCDaemon, stopGCDaemon } from "@cleocode/core/gc/daemon.js";
38779
39452
  import {
38780
39453
  bootstrapDaemon as bootstrapSentientDaemon,
@@ -38837,7 +39510,7 @@ async function showDaemonStatus(cleoDir, projectRoot) {
38837
39510
  }
38838
39511
  }
38839
39512
  function resolveDaemonInstallerScript() {
38840
- const filePath = fileURLToPath3(import.meta.url);
39513
+ const filePath = fileURLToPath4(import.meta.url);
38841
39514
  const candidate1 = join11(filePath, "..", "..", "..", "scripts", "install-daemon-service.mjs");
38842
39515
  if (existsSync9(candidate1)) return candidate1;
38843
39516
  const candidate2 = join11(
@@ -39548,14 +40221,14 @@ __export(detect_drift_exports, {
39548
40221
  detectDriftCommand: () => detectDriftCommand
39549
40222
  });
39550
40223
  import { existsSync as existsSync10, readdirSync, readFileSync as readFileSync11 } from "node:fs";
39551
- import { dirname as dirname5, join as join12 } from "node:path";
40224
+ import { dirname as dirname6, join as join12 } from "node:path";
39552
40225
  function findProjectRoot() {
39553
40226
  let currentDir = process.cwd();
39554
40227
  while (currentDir !== "/") {
39555
40228
  if (existsSync10(join12(currentDir, "package.json"))) {
39556
40229
  return currentDir;
39557
40230
  }
39558
- const parent = dirname5(currentDir);
40231
+ const parent = dirname6(currentDir);
39559
40232
  if (parent === currentDir) break;
39560
40233
  currentDir = parent;
39561
40234
  }
@@ -40073,14 +40746,14 @@ __export(docs_exports, {
40073
40746
  docsCommand: () => docsCommand
40074
40747
  });
40075
40748
  import { mkdir, readdir, readFile as readFile2, writeFile } from "node:fs/promises";
40076
- import { dirname as dirname6, isAbsolute as isAbsolute2, join as join13, resolve as resolve4 } from "node:path";
40749
+ import { dirname as dirname7, isAbsolute as isAbsolute2, join as join13, resolve as resolve5 } from "node:path";
40077
40750
  import {
40078
40751
  buildDocsGraph,
40079
40752
  CleoError as CleoError3,
40080
40753
  exportDocument,
40081
40754
  formatError as formatError5,
40082
40755
  getAgentOutputsAbsolute,
40083
- getProjectRoot as getProjectRoot22,
40756
+ getProjectRoot as getProjectRoot25,
40084
40757
  listDocVersions,
40085
40758
  mergeDocs,
40086
40759
  publishDocs,
@@ -40376,7 +41049,7 @@ var init_docs3 = __esm({
40376
41049
  const taskId = String(args.task);
40377
41050
  const includeAttachments = args["include-attachments"] !== false;
40378
41051
  const includeMemoryRefs = args["include-memory-refs"] === true;
40379
- const projectRoot = getProjectRoot22();
41052
+ const projectRoot = getProjectRoot25();
40380
41053
  try {
40381
41054
  const result = await exportDocument({
40382
41055
  taskId,
@@ -40386,8 +41059,8 @@ var init_docs3 = __esm({
40386
41059
  });
40387
41060
  let writtenPath;
40388
41061
  if (typeof args.out === "string" && args.out.length > 0) {
40389
- const outPath = isAbsolute2(args.out) ? args.out : resolve4(projectRoot, args.out);
40390
- await mkdir(dirname6(outPath), { recursive: true });
41062
+ const outPath = isAbsolute2(args.out) ? args.out : resolve5(projectRoot, args.out);
41063
+ await mkdir(dirname7(outPath), { recursive: true });
40391
41064
  await writeFile(outPath, result.markdown, "utf8");
40392
41065
  writtenPath = outPath;
40393
41066
  }
@@ -40439,7 +41112,7 @@ var init_docs3 = __esm({
40439
41112
  }
40440
41113
  },
40441
41114
  async run({ args }) {
40442
- const projectRoot = getProjectRoot22();
41115
+ const projectRoot = getProjectRoot25();
40443
41116
  try {
40444
41117
  const result = await searchDocs2(String(args.query), {
40445
41118
  ownerId: args.owner ?? void 0,
@@ -40491,7 +41164,7 @@ var init_docs3 = __esm({
40491
41164
  }
40492
41165
  },
40493
41166
  async run({ args }) {
40494
- const projectRoot = getProjectRoot22();
41167
+ const projectRoot = getProjectRoot25();
40495
41168
  const rawStrategy = args.strategy ?? "three-way";
40496
41169
  const strategy = rawStrategy === "cherry-pick" || rawStrategy === "multi-diff" ? rawStrategy : "three-way";
40497
41170
  try {
@@ -40500,8 +41173,8 @@ var init_docs3 = __esm({
40500
41173
  base: args.base ?? void 0
40501
41174
  });
40502
41175
  if (typeof args.out === "string" && args.out.length > 0) {
40503
- const outPath = isAbsolute2(args.out) ? args.out : resolve4(projectRoot, args.out);
40504
- await mkdir(dirname6(outPath), { recursive: true });
41176
+ const outPath = isAbsolute2(args.out) ? args.out : resolve5(projectRoot, args.out);
41177
+ await mkdir(dirname7(outPath), { recursive: true });
40505
41178
  await writeFile(outPath, result.merged, "utf8");
40506
41179
  humanInfo(`Wrote merged content to ${outPath}`);
40507
41180
  }
@@ -40541,7 +41214,7 @@ var init_docs3 = __esm({
40541
41214
  }
40542
41215
  },
40543
41216
  async run({ args }) {
40544
- const projectRoot = getProjectRoot22();
41217
+ const projectRoot = getProjectRoot25();
40545
41218
  const fmt = args.format ?? "mermaid";
40546
41219
  try {
40547
41220
  const result = await buildDocsGraph({ ownerId: String(args.for), projectRoot });
@@ -40571,8 +41244,8 @@ var init_docs3 = __esm({
40571
41244
  output2 = lines.join("\n");
40572
41245
  }
40573
41246
  if (typeof args.out === "string" && args.out.length > 0) {
40574
- const outPath = isAbsolute2(args.out) ? args.out : resolve4(projectRoot, args.out);
40575
- await mkdir(dirname6(outPath), { recursive: true });
41247
+ const outPath = isAbsolute2(args.out) ? args.out : resolve5(projectRoot, args.out);
41248
+ await mkdir(dirname7(outPath), { recursive: true });
40576
41249
  await writeFile(outPath, output2, "utf8");
40577
41250
  humanInfo(`Wrote graph to ${outPath}`);
40578
41251
  }
@@ -40611,7 +41284,7 @@ var init_docs3 = __esm({
40611
41284
  }
40612
41285
  },
40613
41286
  async run({ args }) {
40614
- const projectRoot = getProjectRoot22();
41287
+ const projectRoot = getProjectRoot25();
40615
41288
  try {
40616
41289
  const result = await rankDocs({
40617
41290
  ownerId: String(args.for),
@@ -40650,7 +41323,7 @@ var init_docs3 = __esm({
40650
41323
  }
40651
41324
  },
40652
41325
  async run({ args }) {
40653
- const projectRoot = getProjectRoot22();
41326
+ const projectRoot = getProjectRoot25();
40654
41327
  try {
40655
41328
  const result = await listDocVersions({
40656
41329
  ownerId: String(args.for),
@@ -40694,7 +41367,7 @@ var init_docs3 = __esm({
40694
41367
  }
40695
41368
  },
40696
41369
  async run({ args }) {
40697
- const projectRoot = getProjectRoot22();
41370
+ const projectRoot = getProjectRoot25();
40698
41371
  try {
40699
41372
  const result = await publishDocs({
40700
41373
  ownerId: String(args.for),
@@ -41099,7 +41772,7 @@ __export(migrate_agents_v2_exports, {
41099
41772
  import { createHash as createHash2 } from "node:crypto";
41100
41773
  import { appendFileSync as appendFileSync2, existsSync as existsSync11, mkdirSync as mkdirSync3, readdirSync as readdirSync2, readFileSync as readFileSync12 } from "node:fs";
41101
41774
  import { join as join14 } from "node:path";
41102
- import { getProjectRoot as getProjectRoot23, installAgentFromCant } from "@cleocode/core/internal";
41775
+ import { getProjectRoot as getProjectRoot26, installAgentFromCant } from "@cleocode/core/internal";
41103
41776
  import { openCleoDb } from "@cleocode/core/store/open-cleo-db";
41104
41777
  function sha256Hex(bytes) {
41105
41778
  return createHash2("sha256").update(bytes).digest("hex");
@@ -41286,7 +41959,7 @@ var init_migrate_agents_v2 = __esm({
41286
41959
  }
41287
41960
  },
41288
41961
  async run({ args }) {
41289
- const projectRoot = getProjectRoot23();
41962
+ const projectRoot = getProjectRoot26();
41290
41963
  const verbose = args.quiet !== true;
41291
41964
  if (verbose) {
41292
41965
  humanInfo("Scanning .cleo/cant/agents/ and .cleo/agents/ for unregistered agents...");
@@ -41330,7 +42003,7 @@ __export(doctor_exports, {
41330
42003
  });
41331
42004
  import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "node:fs";
41332
42005
  import { join as join15 } from "node:path";
41333
- import { getProjectRoot as getProjectRoot24, quarantineRogueCleoDir, scanRogueCleoDirs } from "@cleocode/core/internal";
42006
+ import { getProjectRoot as getProjectRoot27, quarantineRogueCleoDir, scanRogueCleoDirs } from "@cleocode/core/internal";
41334
42007
  async function scanTestFixturesInProd(projectRoot) {
41335
42008
  const { getDb: getDb3, getNativeDb } = await import("@cleocode/core/internal");
41336
42009
  await getDb3(projectRoot);
@@ -41552,7 +42225,7 @@ var init_doctor = __esm({
41552
42225
  try {
41553
42226
  if (args.brain) {
41554
42227
  const { computeBrainHealthDashboard } = await import("@cleocode/core/internal");
41555
- const projectRoot = getProjectRoot24();
42228
+ const projectRoot = getProjectRoot27();
41556
42229
  const dashboard = await computeBrainHealthDashboard(projectRoot);
41557
42230
  cliOutput(dashboard, { command: "doctor", operation: "doctor.brain" });
41558
42231
  if (dashboard.hasP0Failure) {
@@ -41561,7 +42234,7 @@ var init_doctor = __esm({
41561
42234
  return;
41562
42235
  }
41563
42236
  if (args["scan-test-fixtures-in-prod"]) {
41564
- const projectRoot = getProjectRoot24();
42237
+ const projectRoot = getProjectRoot27();
41565
42238
  const matches = await scanTestFixturesInProd(projectRoot);
41566
42239
  const dryRun = args["dry-run"] !== false && args.quarantine !== true;
41567
42240
  const quarantined = !dryRun && matches.length > 0 ? await quarantineTestFixtures(projectRoot, matches) : void 0;
@@ -41649,7 +42322,7 @@ var init_doctor = __esm({
41649
42322
  progress.complete("Comprehensive diagnostics complete");
41650
42323
  } else if (args["scan-rogue-cleo-dirs"]) {
41651
42324
  progress.step(0, "Scanning for rogue .cleo/ directories");
41652
- const projectRoot = getProjectRoot24();
42325
+ const projectRoot = getProjectRoot27();
41653
42326
  const reports = scanRogueCleoDirs(projectRoot);
41654
42327
  progress.complete(
41655
42328
  `Found ${reports.length} rogue .cleo/ director${reports.length === 1 ? "y" : "ies"}`
@@ -41658,7 +42331,7 @@ var init_doctor = __esm({
41658
42331
  } else if (args["quarantine-rogue-cleo-dirs"]) {
41659
42332
  const isDryRun = args["dry-run"] === true;
41660
42333
  progress.step(0, `${isDryRun ? "[DRY RUN] " : ""}Scanning for rogue .cleo/ directories`);
41661
- const projectRoot = getProjectRoot24();
42334
+ const projectRoot = getProjectRoot27();
41662
42335
  const reports = scanRogueCleoDirs(projectRoot);
41663
42336
  if (reports.length === 0) {
41664
42337
  progress.complete("No rogue .cleo/ directories found \u2014 nothing to quarantine");
@@ -41712,7 +42385,7 @@ var init_doctor = __esm({
41712
42385
  const { detectAndRemoveLegacyGlobalFiles, detectAndRemoveStrayProjectNexus } = await import("@cleocode/core/internal");
41713
42386
  const { getCleoHome: getCleoHome3 } = await import("@cleocode/core/internal");
41714
42387
  const cleoHome = getCleoHome3();
41715
- const projectRoot = getProjectRoot24();
42388
+ const projectRoot = getProjectRoot27();
41716
42389
  const legacyResult = detectAndRemoveLegacyGlobalFiles(cleoHome);
41717
42390
  const strayResult = detectAndRemoveStrayProjectNexus(projectRoot);
41718
42391
  const isDryRun = args["dry-run"] === true;
@@ -41761,7 +42434,7 @@ var init_doctor = __esm({
41761
42434
  { command: "doctor", operation: "admin.health" }
41762
42435
  );
41763
42436
  try {
41764
- const projectRoot = getProjectRoot24();
42437
+ const projectRoot = getProjectRoot27();
41765
42438
  const conflicts = readMigrationConflicts(projectRoot);
41766
42439
  if (conflicts.length > 0) {
41767
42440
  progress.complete(
@@ -42705,8 +43378,8 @@ __export(generate_changelog_exports, {
42705
43378
  });
42706
43379
  import { execFileSync as execFileSync2 } from "node:child_process";
42707
43380
  import { existsSync as existsSync12, mkdirSync as mkdirSync5, readFileSync as readFileSync13, writeFileSync as writeFileSync5 } from "node:fs";
42708
- import { dirname as dirname7, join as join18 } from "node:path";
42709
- import { CleoError as CleoError4, formatError as formatError6, getConfigPath, getProjectRoot as getProjectRoot25 } from "@cleocode/core";
43381
+ import { dirname as dirname8, join as join18 } from "node:path";
43382
+ import { CleoError as CleoError4, formatError as formatError6, getConfigPath, getProjectRoot as getProjectRoot28 } from "@cleocode/core";
42710
43383
  function getChangelogSource(cwd) {
42711
43384
  const configPath = getConfigPath(cwd);
42712
43385
  try {
@@ -42737,7 +43410,7 @@ function getDefaultOutputPath(platform) {
42737
43410
  }
42738
43411
  }
42739
43412
  function getGitHubRepoSlug(cwd) {
42740
- const projectRoot = getProjectRoot25(cwd);
43413
+ const projectRoot = getProjectRoot28(cwd);
42741
43414
  try {
42742
43415
  const remoteUrl = execFileSync2("git", ["remote", "get-url", "origin"], {
42743
43416
  cwd: projectRoot,
@@ -42870,7 +43543,7 @@ var init_generate_changelog = __esm({
42870
43543
  const targetPlatform = args.platform;
42871
43544
  const dryRun = args["dry-run"] === true;
42872
43545
  const sourceFile = getChangelogSource();
42873
- const sourcePath = join18(getProjectRoot25(), sourceFile);
43546
+ const sourcePath = join18(getProjectRoot28(), sourceFile);
42874
43547
  if (!existsSync12(sourcePath)) {
42875
43548
  throw new CleoError4(4 /* NOT_FOUND */, `Changelog source not found: ${sourcePath}`);
42876
43549
  }
@@ -42883,8 +43556,8 @@ var init_generate_changelog = __esm({
42883
43556
  const outputPath = platformConfig?.path ?? getDefaultOutputPath(targetPlatform);
42884
43557
  const content = generateForPlatform(targetPlatform, sourceContent, repoSlug, limit);
42885
43558
  if (!dryRun) {
42886
- const fullPath = join18(getProjectRoot25(), outputPath);
42887
- mkdirSync5(dirname7(fullPath), { recursive: true });
43559
+ const fullPath = join18(getProjectRoot28(), outputPath);
43560
+ mkdirSync5(dirname8(fullPath), { recursive: true });
42888
43561
  writeFileSync5(fullPath, content, "utf-8");
42889
43562
  }
42890
43563
  results.push({ platform: targetPlatform, path: outputPath, written: !dryRun });
@@ -42904,8 +43577,8 @@ var init_generate_changelog = __esm({
42904
43577
  limit
42905
43578
  );
42906
43579
  if (!dryRun) {
42907
- const fullPath = join18(getProjectRoot25(), platformConfig.path);
42908
- mkdirSync5(dirname7(fullPath), { recursive: true });
43580
+ const fullPath = join18(getProjectRoot28(), platformConfig.path);
43581
+ mkdirSync5(dirname8(fullPath), { recursive: true });
42909
43582
  writeFileSync5(fullPath, content, "utf-8");
42910
43583
  }
42911
43584
  results.push({
@@ -44041,15 +44714,21 @@ var init_import = __esm({
44041
44714
  var init_exports = {};
44042
44715
  __export(init_exports, {
44043
44716
  getGitignoreTemplate: () => getGitignoreTemplate,
44717
+ getWorkflowTemplatesDir: () => getWorkflowTemplatesDir,
44044
44718
  initCommand: () => initCommand2
44045
44719
  });
44046
44720
  import { existsSync as existsSync13, readFileSync as readFileSync14 } from "node:fs";
44047
- import { join as join19 } from "node:path";
44048
- import { fileURLToPath as fileURLToPath4 } from "node:url";
44049
- import { CleoError as CleoError5, formatError as formatError7, initProject as initProject2 } from "@cleocode/core";
44721
+ import { dirname as dirname9, join as join19, resolve as resolve6 } from "node:path";
44722
+ import { fileURLToPath as fileURLToPath5 } from "node:url";
44723
+ import {
44724
+ CleoError as CleoError5,
44725
+ formatError as formatError7,
44726
+ initProject as initProject2,
44727
+ scaffoldWorkflows
44728
+ } from "@cleocode/core";
44050
44729
  function getGitignoreTemplate() {
44051
44730
  try {
44052
- const thisFile = fileURLToPath4(import.meta.url);
44731
+ const thisFile = fileURLToPath5(import.meta.url);
44053
44732
  const packageRoot = join19(thisFile, "..", "..", "..", "..");
44054
44733
  const localTemplatePath = join19(packageRoot, "templates", "cleo-gitignore");
44055
44734
  const monorepoTemplatePath = join19(packageRoot, "..", "..", "templates", "cleo-gitignore");
@@ -44061,6 +44740,11 @@ function getGitignoreTemplate() {
44061
44740
  }
44062
44741
  return "# CLEO Project Data - Selective Git Tracking\nagent-outputs/\n";
44063
44742
  }
44743
+ function getWorkflowTemplatesDir() {
44744
+ const thisFile = fileURLToPath5(import.meta.url);
44745
+ const packageRoot = resolve6(dirname9(thisFile), "..", "..", "..", "..");
44746
+ return join19(packageRoot, "templates", "workflows");
44747
+ }
44064
44748
  var initCommand2;
44065
44749
  var init_init = __esm({
44066
44750
  "packages/cleo/src/cli/commands/init.ts"() {
@@ -44098,10 +44782,43 @@ var init_init = __esm({
44098
44782
  type: "boolean",
44099
44783
  description: "Install canonical CleoOS seed agent personas (.cant)",
44100
44784
  default: false
44785
+ },
44786
+ workflows: {
44787
+ type: "boolean",
44788
+ description: "Scaffold the release-prepare.yml workflow into .github/workflows/ (T9531).",
44789
+ default: false
44790
+ },
44791
+ "dry-run": {
44792
+ type: "boolean",
44793
+ description: "With --workflows: print the rendered YAML without writing.",
44794
+ default: false
44101
44795
  }
44102
44796
  },
44103
44797
  async run({ args }) {
44104
44798
  try {
44799
+ if (args.workflows) {
44800
+ const projectRoot = process.cwd();
44801
+ const templatesDir = getWorkflowTemplatesDir();
44802
+ const result2 = await scaffoldWorkflows({
44803
+ projectRoot,
44804
+ templatesDir,
44805
+ dryRun: !!args["dry-run"],
44806
+ force: !!args.force
44807
+ });
44808
+ cliOutput(
44809
+ {
44810
+ scaffolded: result2.outcomes.map((o) => ({
44811
+ template: o.template,
44812
+ targetPath: o.targetPath,
44813
+ status: o.status
44814
+ })),
44815
+ resolvedTools: result2.resolvedTools,
44816
+ ...args["dry-run"] ? { rendered: result2.outcomes.map((o) => o.rendered) } : {}
44817
+ },
44818
+ { command: "init" }
44819
+ );
44820
+ return;
44821
+ }
44105
44822
  const initOpts = {
44106
44823
  name: args.name || args.projectName || void 0,
44107
44824
  force: !!args.force,
@@ -44941,7 +45658,7 @@ var llm_cost_exports = {};
44941
45658
  __export(llm_cost_exports, {
44942
45659
  costCommand: () => costCommand
44943
45660
  });
44944
- import { getProjectRoot as getProjectRoot26 } from "@cleocode/core/internal";
45661
+ import { getProjectRoot as getProjectRoot29 } from "@cleocode/core/internal";
44945
45662
  import { computeCost } from "@cleocode/core/llm/usage-pricing";
44946
45663
  function resolveSessionId(raw) {
44947
45664
  if (raw === "current") {
@@ -45014,7 +45731,7 @@ var init_llm_cost = __esm({
45014
45731
  process.exit(6);
45015
45732
  }
45016
45733
  const sessionId = resolveSessionId(rawSessionId);
45017
- const projectRoot = getProjectRoot26(process.cwd());
45734
+ const projectRoot = getProjectRoot29(process.cwd());
45018
45735
  let breakdown;
45019
45736
  try {
45020
45737
  breakdown = await loadSessionCostBreakdown(projectRoot, sessionId);
@@ -45370,7 +46087,7 @@ async function _headlessPkceFlow(provider, authUrl) {
45370
46087
  ` After approving, paste the full redirect URL (http://localhost?code=\u2026&state=\u2026):
45371
46088
  `
45372
46089
  );
45373
- return new Promise((resolve5, reject) => {
46090
+ return new Promise((resolve8, reject) => {
45374
46091
  let buf = "";
45375
46092
  process.stdin.setEncoding("utf8");
45376
46093
  process.stdin.once("data", (chunk) => {
@@ -45382,7 +46099,7 @@ async function _headlessPkceFlow(provider, authUrl) {
45382
46099
  reject(new Error('Redirect URL is missing the "code" parameter'));
45383
46100
  return;
45384
46101
  }
45385
- resolve5(code);
46102
+ resolve8(code);
45386
46103
  } catch {
45387
46104
  reject(new Error(`Invalid redirect URL: ${buf}`));
45388
46105
  }
@@ -45390,7 +46107,7 @@ async function _headlessPkceFlow(provider, authUrl) {
45390
46107
  });
45391
46108
  }
45392
46109
  async function _localCallbackPkceFlow(provider, authUrl, expectedState, port) {
45393
- return new Promise((resolve5) => {
46110
+ return new Promise((resolve8) => {
45394
46111
  const server = createServer((req, res) => {
45395
46112
  const url = new URL(req.url ?? "/", `http://localhost:${port}`);
45396
46113
  const code = url.searchParams.get("code");
@@ -45400,7 +46117,7 @@ async function _localCallbackPkceFlow(provider, authUrl, expectedState, port) {
45400
46117
  if (error) {
45401
46118
  res.end(`<h1>Authorization failed</h1><p>${error}</p><p>You may close this tab.</p>`);
45402
46119
  server.close();
45403
- resolve5({
46120
+ resolve8({
45404
46121
  error: {
45405
46122
  code: "E_PKCE_AUTH_DENIED",
45406
46123
  codeName: "E_PKCE_AUTH_DENIED",
@@ -45412,7 +46129,7 @@ async function _localCallbackPkceFlow(provider, authUrl, expectedState, port) {
45412
46129
  if (!code || state !== expectedState) {
45413
46130
  res.end("<h1>Invalid callback</h1><p>You may close this tab.</p>");
45414
46131
  server.close();
45415
- resolve5({
46132
+ resolve8({
45416
46133
  error: {
45417
46134
  code: "E_PKCE_INVALID_CALLBACK",
45418
46135
  codeName: "E_PKCE_INVALID_CALLBACK",
@@ -45423,7 +46140,7 @@ async function _localCallbackPkceFlow(provider, authUrl, expectedState, port) {
45423
46140
  }
45424
46141
  res.end("<h1>Authorized</h1><p>You may close this tab and return to your terminal.</p>");
45425
46142
  server.close();
45426
- resolve5({ code });
46143
+ resolve8({ code });
45427
46144
  });
45428
46145
  server.listen(port, "localhost", () => {
45429
46146
  process.stderr.write("\n");
@@ -45556,7 +46273,7 @@ function _generateState() {
45556
46273
  return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
45557
46274
  }
45558
46275
  function _findFreePort() {
45559
- return new Promise((resolve5, reject) => {
46276
+ return new Promise((resolve8, reject) => {
45560
46277
  const srv = createServer();
45561
46278
  srv.listen(0, "localhost", () => {
45562
46279
  const addr = srv.address();
@@ -45566,7 +46283,7 @@ function _findFreePort() {
45566
46283
  return;
45567
46284
  }
45568
46285
  const port = addr.port;
45569
- srv.close(() => resolve5(port));
46286
+ srv.close(() => resolve8(port));
45570
46287
  });
45571
46288
  srv.on("error", reject);
45572
46289
  });
@@ -46159,14 +46876,14 @@ async function readStdin() {
46159
46876
  if (process.stdin.isTTY) {
46160
46877
  return "";
46161
46878
  }
46162
- return new Promise((resolve5, reject) => {
46879
+ return new Promise((resolve8, reject) => {
46163
46880
  let data = "";
46164
46881
  process.stdin.setEncoding("utf-8");
46165
46882
  process.stdin.on("data", (chunk) => {
46166
46883
  data += chunk;
46167
46884
  });
46168
46885
  process.stdin.on("end", () => {
46169
- resolve5(data.trim());
46886
+ resolve8(data.trim());
46170
46887
  });
46171
46888
  process.stdin.on("error", reject);
46172
46889
  });
@@ -46525,7 +47242,7 @@ import {
46525
47242
  getBrainDb as getBrainDb2,
46526
47243
  getBrainNativeDb as getBrainNativeDb3,
46527
47244
  getDreamStatus,
46528
- getProjectRoot as getProjectRoot27,
47245
+ getProjectRoot as getProjectRoot30,
46529
47246
  runConsolidation,
46530
47247
  triggerManualDream
46531
47248
  } from "@cleocode/core/internal";
@@ -47486,7 +48203,7 @@ var init_memory3 = __esm({
47486
48203
  },
47487
48204
  args: {},
47488
48205
  async run() {
47489
- const root = getProjectRoot27();
48206
+ const root = getProjectRoot30();
47490
48207
  try {
47491
48208
  const result = await runConsolidation(root);
47492
48209
  cliOutput(result, { command: "memory-consolidate", operation: "memory.consolidate" });
@@ -47510,7 +48227,7 @@ var init_memory3 = __esm({
47510
48227
  }
47511
48228
  },
47512
48229
  async run({ args }) {
47513
- const root = getProjectRoot27();
48230
+ const root = getProjectRoot30();
47514
48231
  if (args.status) {
47515
48232
  try {
47516
48233
  const status = await getDreamStatus(root);
@@ -47547,7 +48264,7 @@ var init_memory3 = __esm({
47547
48264
  }
47548
48265
  },
47549
48266
  async run({ args }) {
47550
- const root = getProjectRoot27();
48267
+ const root = getProjectRoot30();
47551
48268
  try {
47552
48269
  const { runObserver, runReflector } = await import("@cleocode/core/internal");
47553
48270
  const observerResult = await runObserver(root, args.session, {
@@ -47587,7 +48304,7 @@ var init_memory3 = __esm({
47587
48304
  }
47588
48305
  },
47589
48306
  async run({ args }) {
47590
- const root = getProjectRoot27();
48307
+ const root = getProjectRoot30();
47591
48308
  try {
47592
48309
  const { getBrainDb: getBrainDbInner, getBrainNativeDb: getBrainNativeDbInner } = await import("@cleocode/core/internal");
47593
48310
  await getBrainDbInner(root);
@@ -47685,7 +48402,7 @@ var init_memory3 = __esm({
47685
48402
  async run({ args }) {
47686
48403
  const sourceDir = args.from ?? join20(homedir6(), ".claude", "projects", "-mnt-projects-cleocode", "memory");
47687
48404
  const isDryRun = !!args["dry-run"];
47688
- const projectRoot = getProjectRoot27();
48405
+ const projectRoot = getProjectRoot30();
47689
48406
  const stateFile = join20(projectRoot, CLEO_DIR_NAME, MIGRATE_MEMORY_HASHES_JSON);
47690
48407
  if (!existsSync14(sourceDir)) {
47691
48408
  cliError(`Source directory not found: ${sourceDir}`, "E_NOT_FOUND", { name: "E_NOT_FOUND" });
@@ -47898,7 +48615,7 @@ var init_memory3 = __esm({
47898
48615
  },
47899
48616
  args: {},
47900
48617
  async run() {
47901
- const root = getProjectRoot27();
48618
+ const root = getProjectRoot30();
47902
48619
  try {
47903
48620
  await getBrainDb2(root);
47904
48621
  const nativeDb = getBrainNativeDb3();
@@ -47997,7 +48714,7 @@ var init_memory3 = __esm({
47997
48714
  }
47998
48715
  },
47999
48716
  async run({ args }) {
48000
- const root = getProjectRoot27();
48717
+ const root = getProjectRoot30();
48001
48718
  const targetTier = args.to;
48002
48719
  const reason = args.reason;
48003
48720
  const validTiers = ["medium", "long"];
@@ -48101,7 +48818,7 @@ var init_memory3 = __esm({
48101
48818
  }
48102
48819
  },
48103
48820
  async run({ args }) {
48104
- const root = getProjectRoot27();
48821
+ const root = getProjectRoot30();
48105
48822
  const targetTier = args.to;
48106
48823
  const reason = args.reason;
48107
48824
  const validTiers = ["short", "medium"];
@@ -48488,8 +49205,8 @@ data: ${JSON.stringify(event)}
48488
49205
  cursor = data.nextCursor;
48489
49206
  }
48490
49207
  if (!running) break;
48491
- await new Promise((resolve5) => {
48492
- const timer = setTimeout(resolve5, intervalMs);
49208
+ await new Promise((resolve8) => {
49209
+ const timer = setTimeout(resolve8, intervalMs);
48493
49210
  timer.unref?.();
48494
49211
  });
48495
49212
  }
@@ -48615,7 +49332,7 @@ var migrate_claude_mem_exports = {};
48615
49332
  __export(migrate_claude_mem_exports, {
48616
49333
  migrateClaudeMemCommand: () => migrateClaudeMemCommand
48617
49334
  });
48618
- import { getProjectRoot as getProjectRoot28, migrateClaudeMem } from "@cleocode/core/internal";
49335
+ import { getProjectRoot as getProjectRoot31, migrateClaudeMem } from "@cleocode/core/internal";
48619
49336
  import { ingestLooseAgentOutputs, ingestRcasdDirectories } from "@cleocode/core/memory";
48620
49337
  import { getDb as getDb2 } from "@cleocode/core/store/sqlite";
48621
49338
  var storageCommand, claudeMemCommand, manifestIngestCommand, migrateClaudeMemCommand;
@@ -48678,7 +49395,7 @@ var init_migrate_claude_mem = __esm({
48678
49395
  }
48679
49396
  },
48680
49397
  async run({ args }) {
48681
- const root = getProjectRoot28();
49398
+ const root = getProjectRoot31();
48682
49399
  try {
48683
49400
  const result = await migrateClaudeMem(root, {
48684
49401
  sourcePath: args.source,
@@ -48727,7 +49444,7 @@ var init_migrate_claude_mem = __esm({
48727
49444
  }
48728
49445
  },
48729
49446
  async run({ args }) {
48730
- const projectRoot = getProjectRoot28();
49447
+ const projectRoot = getProjectRoot31();
48731
49448
  try {
48732
49449
  const db = await getDb2(projectRoot);
48733
49450
  const rcasdFlag = Boolean(args.rcasd);
@@ -49682,7 +50399,7 @@ var init_nexus4 = __esm({
49682
50399
  const repoPath = args.path ? path4.resolve(args.path) : process.cwd();
49683
50400
  humanInfo(`[nexus] Analyzing: ${repoPath}${isIncremental ? " (incremental)" : ""}`);
49684
50401
  try {
49685
- const [{ getNexusDb, nexusSchema }, { runPipeline }, { getProjectRoot: getProjectRoot34 }, { eq: eq2 }] = await Promise.all([
50402
+ const [{ getNexusDb, nexusSchema }, { runPipeline }, { getProjectRoot: getProjectRoot38 }, { eq: eq2 }] = await Promise.all([
49686
50403
  import("@cleocode/core/store/nexus-sqlite"),
49687
50404
  import("@cleocode/nexus/pipeline"),
49688
50405
  import("@cleocode/core/internal"),
@@ -49762,7 +50479,7 @@ var init_nexus4 = __esm({
49762
50479
  extensions: { duration_ms: durationMs }
49763
50480
  }
49764
50481
  );
49765
- void getProjectRoot34;
50482
+ void getProjectRoot38;
49766
50483
  } catch (err) {
49767
50484
  const msg = err instanceof Error ? err.message : String(err);
49768
50485
  cliError(
@@ -50089,13 +50806,13 @@ var init_nexus4 = __esm({
50089
50806
  if (!skipPrompt) {
50090
50807
  const { createInterface: createInterface4 } = await import("node:readline");
50091
50808
  const rl = createInterface4({ input: process.stdin, output: process.stdout });
50092
- const confirmed = await new Promise((resolve5) => {
50809
+ const confirmed = await new Promise((resolve8) => {
50093
50810
  rl.question(
50094
50811
  `
50095
50812
  [nexus] Delete ${matchCount} project(s) from the registry? [y/N] `,
50096
50813
  (answer) => {
50097
50814
  rl.close();
50098
- resolve5(answer.trim().toLowerCase() === "y");
50815
+ resolve8(answer.trim().toLowerCase() === "y");
50099
50816
  }
50100
50817
  );
50101
50818
  });
@@ -52098,23 +52815,29 @@ var init_orchestrate3 = __esm({
52098
52815
  worktreeCompleteCommand = defineCommand({
52099
52816
  meta: {
52100
52817
  name: "worktree-complete",
52101
- description: "Integrate subagent worktree into default branch via canonical git merge --no-ff (ADR-062)"
52818
+ description: "Integrate subagent worktree into default branch via canonical git merge --no-ff (ADR-062). T9548: idempotent \u2014 re-running on a completed worktree is a no-op."
52102
52819
  },
52103
52820
  args: {
52104
52821
  taskId: {
52105
52822
  type: "positional",
52106
52823
  description: "Task ID whose worktree branch should be merged (e.g. T1625)",
52107
52824
  required: true
52825
+ },
52826
+ resolve: {
52827
+ type: "string",
52828
+ description: 'T9548 conflict-recovery mode: "auto" (default \u2014 attempt merge) or "manual" (skip merge, mark worktree as manually-handled in audit log)',
52829
+ default: "auto"
52108
52830
  }
52109
52831
  },
52110
52832
  async run({ args }) {
52111
- await dispatchFromCli(
52112
- "mutate",
52113
- "orchestrate",
52114
- "worktree.complete",
52115
- { taskId: args.taskId },
52116
- { command: "orchestrate" }
52117
- );
52833
+ const resolveArg = typeof args.resolve === "string" ? args.resolve : void 0;
52834
+ const params = { taskId: args.taskId };
52835
+ if (resolveArg === "manual") {
52836
+ params.resolve = "manual";
52837
+ }
52838
+ await dispatchFromCli("mutate", "orchestrate", "worktree.complete", params, {
52839
+ command: "orchestrate"
52840
+ });
52118
52841
  }
52119
52842
  });
52120
52843
  conduitStatusCommand = defineCommand({
@@ -52753,7 +53476,7 @@ __export(plan_exports, {
52753
53476
  planCommand: () => planCommand2
52754
53477
  });
52755
53478
  var planCommand2;
52756
- var init_plan = __esm({
53479
+ var init_plan2 = __esm({
52757
53480
  "packages/cleo/src/cli/commands/plan.ts"() {
52758
53481
  "use strict";
52759
53482
  init_dist();
@@ -53018,6 +53741,114 @@ var init_promote = __esm({
53018
53741
  }
53019
53742
  });
53020
53743
 
53744
+ // packages/cleo/src/cli/commands/provenance.ts
53745
+ var provenance_exports = {};
53746
+ __export(provenance_exports, {
53747
+ provenanceCommand: () => provenanceCommand
53748
+ });
53749
+ var backfillCommand3, verifyCommand2, provenanceCommand;
53750
+ var init_provenance2 = __esm({
53751
+ "packages/cleo/src/cli/commands/provenance.ts"() {
53752
+ "use strict";
53753
+ init_dist();
53754
+ init_cli();
53755
+ backfillCommand3 = defineCommand({
53756
+ meta: {
53757
+ name: "backfill",
53758
+ description: "Walk historical git tags from --since and populate the 11 provenance tables"
53759
+ },
53760
+ args: {
53761
+ since: {
53762
+ type: "string",
53763
+ description: "Lower-bound version (exclusive). Tags newer than this are reconciled. Empty string = all tags.",
53764
+ required: true
53765
+ },
53766
+ "force-overwrite": {
53767
+ type: "boolean",
53768
+ description: "UPDATE existing rows on conflict (audit-logged). Default: UPSERT-on-insert only."
53769
+ },
53770
+ "dry-run": {
53771
+ type: "boolean",
53772
+ description: "Enumerate the tag set + return the plan without writing to the DB"
53773
+ },
53774
+ "reset-checkpoint": {
53775
+ type: "boolean",
53776
+ description: "Clear the existing .cleo/release/backfill-state.json before starting (do NOT resume)"
53777
+ },
53778
+ json: { type: "boolean", description: "Emit LAFS envelope" }
53779
+ },
53780
+ async run({ args }) {
53781
+ await dispatchFromCli(
53782
+ "mutate",
53783
+ "provenance",
53784
+ "provenance.backfill",
53785
+ {
53786
+ since: args.since,
53787
+ forceOverwrite: args["force-overwrite"] === true,
53788
+ dryRun: args["dry-run"] === true,
53789
+ resetCheckpoint: args["reset-checkpoint"] === true
53790
+ },
53791
+ { command: "provenance" }
53792
+ );
53793
+ }
53794
+ });
53795
+ verifyCommand2 = defineCommand({
53796
+ meta: {
53797
+ name: "verify",
53798
+ description: "Audit the 11 provenance tables for a release (FK integrity, orphans, evidence staleness)"
53799
+ },
53800
+ args: {
53801
+ version: {
53802
+ type: "positional",
53803
+ description: "Release version to verify (e.g. v2026.6.0). Optional when --all is set.",
53804
+ required: false
53805
+ },
53806
+ all: {
53807
+ type: "boolean",
53808
+ description: "Verify the most-recent N releases instead of a single version"
53809
+ },
53810
+ limit: {
53811
+ type: "string",
53812
+ description: "How many releases to verify in --all mode (default 5)"
53813
+ },
53814
+ json: { type: "boolean", description: "Emit LAFS envelope" }
53815
+ },
53816
+ async run({ args }) {
53817
+ const version = typeof args.version === "string" ? args.version : void 0;
53818
+ const all = args.all === true;
53819
+ const limitArg = typeof args.limit === "string" ? args.limit : void 0;
53820
+ const limit = limitArg ? Number.parseInt(limitArg, 10) : void 0;
53821
+ await dispatchFromCli(
53822
+ "query",
53823
+ "provenance",
53824
+ "provenance.verify",
53825
+ {
53826
+ ...version ? { version } : {},
53827
+ all,
53828
+ ...limit && Number.isFinite(limit) ? { limit } : {}
53829
+ },
53830
+ { command: "provenance" }
53831
+ );
53832
+ }
53833
+ });
53834
+ provenanceCommand = defineCommand({
53835
+ meta: {
53836
+ name: "provenance",
53837
+ description: "Provenance-graph maintenance: backfill, verify, repair"
53838
+ },
53839
+ subCommands: {
53840
+ backfill: backfillCommand3,
53841
+ verify: verifyCommand2
53842
+ },
53843
+ async run({ cmd, rawArgs }) {
53844
+ const firstArg = rawArgs?.find((a) => !a.startsWith("-"));
53845
+ if (firstArg && cmd.subCommands && firstArg in cmd.subCommands) return;
53846
+ await showUsage(cmd);
53847
+ }
53848
+ });
53849
+ }
53850
+ });
53851
+
53021
53852
  // packages/cleo/src/cli/commands/provider.ts
53022
53853
  var provider_exports = {};
53023
53854
  __export(provider_exports, {
@@ -53396,7 +54227,7 @@ var refresh_memory_exports = {};
53396
54227
  __export(refresh_memory_exports, {
53397
54228
  refreshMemoryCommand: () => refreshMemoryCommand
53398
54229
  });
53399
- import { getProjectRoot as getProjectRoot29 } from "@cleocode/core";
54230
+ import { getProjectRoot as getProjectRoot32 } from "@cleocode/core";
53400
54231
  var refreshMemoryCommand;
53401
54232
  var init_refresh_memory = __esm({
53402
54233
  "packages/cleo/src/cli/commands/refresh-memory.ts"() {
@@ -53409,7 +54240,7 @@ var init_refresh_memory = __esm({
53409
54240
  description: "Regenerate .cleo/memory-bridge.md from brain.db"
53410
54241
  },
53411
54242
  async run() {
53412
- const projectDir = getProjectRoot29();
54243
+ const projectDir = getProjectRoot32();
53413
54244
  const { writeMemoryBridge } = await import("@cleocode/core/internal");
53414
54245
  const result = await writeMemoryBridge(projectDir);
53415
54246
  if (result.written) {
@@ -53588,20 +54419,22 @@ var init_relates = __esm({
53588
54419
  // packages/cleo/src/cli/commands/release.ts
53589
54420
  var release_exports = {};
53590
54421
  __export(release_exports, {
54422
+ SHIP_DEPRECATION_NOTICE: () => SHIP_DEPRECATION_NOTICE,
53591
54423
  releaseCommand: () => releaseCommand
53592
54424
  });
53593
54425
  import { release as release2 } from "@cleocode/core";
53594
- var shipCommand, listCommand17, showCommand10, cancelCommand2, changelogCommand, rollbackCommand, rollbackFullCommand, prStatusCommand, channelCommand, startCommand7, verifyCommand2, publishCommand3, reconcileCommand4, releaseCommand;
54426
+ var SHIP_DEPRECATION_NOTICE, shipCommand, listCommand17, showCommand10, cancelCommand2, changelogCommand, rollbackCommand, rollbackFullCommand, prStatusCommand, channelCommand, planCommand3, openCommand, reconcileCommand4, releaseCommand;
53595
54427
  var init_release3 = __esm({
53596
54428
  "packages/cleo/src/cli/commands/release.ts"() {
53597
54429
  "use strict";
53598
54430
  init_dist();
53599
54431
  init_cli();
53600
54432
  init_renderers();
54433
+ SHIP_DEPRECATION_NOTICE = "[DEPRECATED] `cleo release ship` is a deprecated alias and will be removed no earlier than the third release cycle after T9498. Use `cleo release plan <version> --epic <id>` followed by `cleo release open <version>`; publish runs via GHA workflow. Docs: T9345-CHILD-1.";
53601
54434
  shipCommand = defineCommand({
53602
54435
  meta: {
53603
54436
  name: "ship",
53604
- description: "Ship a release: gates \u2192 changelog \u2192 commit \u2192 tag \u2192 push"
54437
+ description: "[DEPRECATED] Forwards to `release plan` + `release open`"
53605
54438
  },
53606
54439
  args: {
53607
54440
  version: {
@@ -53611,45 +54444,37 @@ var init_release3 = __esm({
53611
54444
  },
53612
54445
  epic: {
53613
54446
  type: "string",
53614
- description: "Epic task ID for commit message (e.g. T5576)",
54447
+ description: "Epic task ID (forwarded to release plan / release open)",
53615
54448
  required: true
53616
54449
  },
53617
54450
  "dry-run": {
53618
54451
  type: "boolean",
53619
- description: "Preview all actions without writing anything"
53620
- },
53621
- push: {
53622
- type: "boolean",
53623
- description: "Push commit and tag (default: true)",
53624
- default: true
53625
- },
53626
- bump: {
53627
- type: "boolean",
53628
- description: "Bump version files (default: true)",
53629
- default: true
53630
- },
53631
- remote: {
53632
- type: "string",
53633
- description: "Git remote to push to (default: origin)"
53634
- },
53635
- force: {
53636
- type: "boolean",
53637
- description: "Bypass IVTR gate check with owner warning (breaks accountability chain)"
54452
+ description: "Preview all actions without writing anything (plan dry-run only)"
53638
54453
  }
53639
54454
  },
53640
54455
  async run({ args }) {
54456
+ process.stderr.write(`${SHIP_DEPRECATION_NOTICE}
54457
+ `);
53641
54458
  await dispatchFromCli(
53642
54459
  "mutate",
53643
- "pipeline",
53644
- "release.ship",
54460
+ "release",
54461
+ "release.plan",
53645
54462
  {
53646
54463
  version: args.version,
53647
54464
  epicId: args.epic,
53648
- dryRun: args["dry-run"],
53649
- push: args.push !== false,
53650
- bump: args.bump !== false,
53651
- remote: args.remote,
53652
- force: args.force
54465
+ dryRun: args["dry-run"] === true
54466
+ },
54467
+ { command: "release" }
54468
+ );
54469
+ if (args["dry-run"] === true) {
54470
+ return;
54471
+ }
54472
+ await dispatchFromCli(
54473
+ "mutate",
54474
+ "release",
54475
+ "release.open",
54476
+ {
54477
+ version: args.version
53653
54478
  },
53654
54479
  { command: "release" }
53655
54480
  );
@@ -53818,75 +54643,148 @@ var init_release3 = __esm({
53818
54643
  await dispatchFromCli("query", "pipeline", "release.channel.show", {}, { command: "release" });
53819
54644
  }
53820
54645
  });
53821
- startCommand7 = defineCommand({
54646
+ planCommand3 = defineCommand({
53822
54647
  meta: {
53823
- name: "start",
53824
- description: "Begin a release (validates version, captures branch, persists handle)"
54648
+ name: "plan",
54649
+ description: "Build the canonical Release Plan envelope and persist status=planned (T9525)"
53825
54650
  },
53826
54651
  args: {
53827
- version: { type: "positional", description: "Version to release", required: true },
53828
- epic: { type: "string", description: "Epic ID this release ships" },
53829
- branch: { type: "string", description: "Override detected branch" }
54652
+ version: {
54653
+ type: "positional",
54654
+ description: "Candidate release version (e.g. v2026.6.0 or 2026.6.0)",
54655
+ required: true
54656
+ },
54657
+ epic: {
54658
+ type: "string",
54659
+ description: "Epic task ID whose children are candidates for inclusion",
54660
+ required: true
54661
+ },
54662
+ scheme: {
54663
+ type: "string",
54664
+ description: "Versioning scheme: calver | semver | calver-suffix"
54665
+ },
54666
+ channel: {
54667
+ type: "string",
54668
+ description: "Release channel: latest | beta | alpha | rc"
54669
+ },
54670
+ hotfix: {
54671
+ type: "boolean",
54672
+ description: "Mark plan as release_kind=hotfix"
54673
+ },
54674
+ "dry-run": {
54675
+ type: "boolean",
54676
+ description: "Compute plan + envelope without writing the plan file or DB row"
54677
+ }
53830
54678
  },
53831
54679
  async run({ args }) {
53832
- const handle = await release2.releaseStart(args.version, {
53833
- epicId: args.epic,
53834
- branch: args.branch
53835
- });
53836
- cliOutput(handle, { command: "release", operation: "release.start" });
53837
- }
53838
- });
53839
- verifyCommand2 = defineCommand({
53840
- meta: { name: "verify", description: "Verify release gates + child task gate state" },
53841
- async run() {
53842
- const projectRoot = process.cwd();
53843
- const handle = release2.loadActiveReleaseHandle(projectRoot);
53844
- const result = await release2.releaseVerify(handle, {
53845
- runGate: release2.makeAdr061GateRunner(projectRoot)
53846
- });
53847
- cliOutput(result, { command: "release", operation: "release.verify" });
53848
- if (!result.passed) process.exit(1);
54680
+ await dispatchFromCli(
54681
+ "mutate",
54682
+ "release",
54683
+ "release.plan",
54684
+ {
54685
+ version: args.version,
54686
+ epicId: args.epic,
54687
+ scheme: args.scheme,
54688
+ channel: args.channel,
54689
+ hotfix: args.hotfix === true,
54690
+ dryRun: args["dry-run"] === true
54691
+ },
54692
+ { command: "release" }
54693
+ );
53849
54694
  }
53850
54695
  });
53851
- publishCommand3 = defineCommand({
53852
- meta: { name: "publish", description: "Publish release artifact (project-context driven)" },
53853
- args: { "dry-run": { type: "boolean", description: "Print command without executing" } },
54696
+ openCommand = defineCommand({
54697
+ meta: {
54698
+ name: "open",
54699
+ description: "Dispatch release-prepare workflow + transition releases.status to pr-opened"
54700
+ },
54701
+ args: {
54702
+ version: {
54703
+ type: "positional",
54704
+ description: "Release version (e.g. v2026.6.0)",
54705
+ required: true
54706
+ },
54707
+ workflow: {
54708
+ type: "string",
54709
+ description: "Workflow file to dispatch (default: release-prepare.yml)"
54710
+ },
54711
+ watch: {
54712
+ type: "boolean",
54713
+ description: "Poll gh run watch until the run reaches a terminal state"
54714
+ },
54715
+ "commit-plan": {
54716
+ type: "boolean",
54717
+ description: "Commit the plan file to the active branch before dispatching"
54718
+ }
54719
+ },
53854
54720
  async run({ args }) {
53855
- const result = await release2.releasePublish(release2.loadActiveReleaseHandle(process.cwd()), {
53856
- dryRun: args["dry-run"] === true
53857
- });
53858
- cliOutput(result, { command: "release", operation: "release.publish" });
53859
- if (!result.success) process.exit(1);
54721
+ await dispatchFromCli(
54722
+ "mutate",
54723
+ "release",
54724
+ "release.open",
54725
+ {
54726
+ version: args.version,
54727
+ workflow: args.workflow,
54728
+ watch: args.watch === true,
54729
+ commitPlan: args["commit-plan"] === true
54730
+ },
54731
+ { command: "release" }
54732
+ );
53860
54733
  }
53861
54734
  });
53862
54735
  reconcileCommand4 = defineCommand({
53863
- meta: { name: "reconcile", description: "Run post-release invariants for the active release" },
53864
- args: { "dry-run": { type: "boolean", description: "Preview without mutations" } },
54736
+ meta: {
54737
+ name: "reconcile",
54738
+ description: "Reconcile a published release: backfill the 11 provenance tables"
54739
+ },
54740
+ args: {
54741
+ version: {
54742
+ type: "positional",
54743
+ description: "Version string (e.g. v2026.6.0)",
54744
+ required: true
54745
+ },
54746
+ "from-workflow": {
54747
+ type: "boolean",
54748
+ description: "Indicates invocation from release-publish.yml (affects logging only)"
54749
+ },
54750
+ rollback: {
54751
+ type: "boolean",
54752
+ description: "Reconcile a rollback rather than a publish (deferred to T9528)"
54753
+ },
54754
+ json: { type: "boolean", description: "Emit LAFS envelope" }
54755
+ },
53865
54756
  async run({ args }) {
53866
- const result = await release2.releaseReconcile(release2.loadActiveReleaseHandle(process.cwd()), {
53867
- dryRun: args["dry-run"] === true
54757
+ const result = await release2.releaseReconcileV2(args.version, {
54758
+ fromWorkflow: args["from-workflow"] === true,
54759
+ rollback: args.rollback === true
53868
54760
  });
53869
54761
  cliOutput(result, { command: "release", operation: "release.reconcile" });
53870
54762
  if (!result.success) process.exit(1);
53871
54763
  }
53872
54764
  });
53873
54765
  releaseCommand = defineCommand({
53874
- meta: { name: "release", description: "Release lifecycle management" },
54766
+ meta: {
54767
+ name: "release",
54768
+ description: "Release lifecycle management \u2014 4-verb pipeline: plan \u2192 open \u2192 reconcile / rollback. Deprecated: ship (forwards to plan + open; see SPEC-T9345 \xA712)."
54769
+ },
53875
54770
  subCommands: {
53876
- ship: shipCommand,
54771
+ // Canonical SPEC-T9345 4-verb pipeline — list these first so `--help`
54772
+ // surfaces them as the documented default (T9538 / R-420).
54773
+ plan: planCommand3,
54774
+ open: openCommand,
54775
+ reconcile: reconcileCommand4,
54776
+ rollback: rollbackCommand,
54777
+ // Read-only helpers — not deprecated.
53877
54778
  list: listCommand17,
53878
54779
  show: showCommand10,
53879
54780
  cancel: cancelCommand2,
53880
54781
  changelog: changelogCommand,
53881
- rollback: rollbackCommand,
53882
- "rollback-full": rollbackFullCommand,
53883
- channel: channelCommand,
53884
54782
  "pr-status": prStatusCommand,
53885
- // Canonical 4-step pipeline (T1597 / ADR-063)
53886
- start: startCommand7,
53887
- verify: verifyCommand2,
53888
- publish: publishCommand3,
53889
- reconcile: reconcileCommand4
54783
+ channel: channelCommand,
54784
+ "rollback-full": rollbackFullCommand,
54785
+ // Deprecated verbs (kept for the migration window — SPEC-T9345 §12).
54786
+ // R-420: ship → plan + open
54787
+ ship: shipCommand
53890
54788
  },
53891
54789
  async run({ cmd, rawArgs }) {
53892
54790
  const firstArg = rawArgs?.find((a) => !a.startsWith("-"));
@@ -54723,7 +55621,7 @@ __export(restore_exports, {
54723
55621
  import fs3 from "node:fs";
54724
55622
  import path5 from "node:path";
54725
55623
  import { CleoError as CleoError8, getTaskAccessor as getTaskAccessor3 } from "@cleocode/core";
54726
- import { getProjectRoot as getProjectRoot30 } from "@cleocode/core/internal";
55624
+ import { getProjectRoot as getProjectRoot33 } from "@cleocode/core/internal";
54727
55625
  function parseMarkdownValue(raw) {
54728
55626
  const trimmed = raw.trim();
54729
55627
  if (trimmed === "_(not present)_" || trimmed === "") return void 0;
@@ -54843,7 +55741,7 @@ var init_restore = __esm({
54843
55741
  description: "Apply manually-resolved conflicts from .cleo/restore-conflicts.md"
54844
55742
  },
54845
55743
  async run() {
54846
- const projectRoot = getProjectRoot30();
55744
+ const projectRoot = getProjectRoot33();
54847
55745
  const reportPath = path5.join(projectRoot, CLEO_DIR_NAME, RESTORE_CONFLICTS_MD);
54848
55746
  if (!fs3.existsSync(reportPath)) {
54849
55747
  humanLine("No pending restore conflicts. Nothing to finalize.");
@@ -55888,11 +56786,11 @@ async function runPostUpdateDiagnostics(opts) {
55888
56786
  input: process.stdin,
55889
56787
  output: process.stdout
55890
56788
  });
55891
- shouldMigrate = await new Promise((resolve5) => {
56789
+ shouldMigrate = await new Promise((resolve8) => {
55892
56790
  rl.question(" Do you want to run the upgrade now? [Y/n] ", (answer) => {
55893
56791
  rl.close();
55894
56792
  const clean = answer.trim().toLowerCase();
55895
- resolve5(clean === "" || clean === "y" || clean === "yes");
56793
+ resolve8(clean === "" || clean === "y" || clean === "yes");
55896
56794
  });
55897
56795
  });
55898
56796
  }
@@ -56965,7 +57863,7 @@ var sequence_exports = {};
56965
57863
  __export(sequence_exports, {
56966
57864
  sequenceCommand: () => sequenceCommand
56967
57865
  });
56968
- import { getProjectRoot as getProjectRoot31 } from "@cleocode/core/internal";
57866
+ import { getProjectRoot as getProjectRoot34 } from "@cleocode/core/internal";
56969
57867
  var showCommand12, checkCommand6, repairCommand, sequenceCommand;
56970
57868
  var init_sequence = __esm({
56971
57869
  "packages/cleo/src/cli/commands/sequence.ts"() {
@@ -57001,7 +57899,7 @@ var init_sequence = __esm({
57001
57899
  meta: { name: "repair", description: "Reset counter to max + 1 if behind" },
57002
57900
  async run() {
57003
57901
  const { repairSequence } = await import("@cleocode/core/internal");
57004
- const projectRoot = getProjectRoot31();
57902
+ const projectRoot = getProjectRoot34();
57005
57903
  const repair = await repairSequence(projectRoot);
57006
57904
  const result = {
57007
57905
  repaired: repair.repaired,
@@ -57055,7 +57953,7 @@ async function promptOwnerAuthPassword(sessionName) {
57055
57953
  terminal: true
57056
57954
  });
57057
57955
  process.stderr.write(`[cleo] Enter owner-auth password for session "${sessionName}": `);
57058
- const password = await new Promise((resolve5) => {
57956
+ const password = await new Promise((resolve8) => {
57059
57957
  if (process.stdin.setRawMode) {
57060
57958
  process.stdin.setRawMode(
57061
57959
  true
@@ -57073,10 +57971,10 @@ async function promptOwnerAuthPassword(sessionName) {
57073
57971
  );
57074
57972
  }
57075
57973
  process.stderr.write("\n");
57076
- resolve5(pw);
57974
+ resolve8(pw);
57077
57975
  } else if (ch === "") {
57078
57976
  process.stderr.write("\n[cleo] Cancelled.\n");
57079
- resolve5("");
57977
+ resolve8("");
57080
57978
  } else if (ch === "\x7F" || ch === "\b") {
57081
57979
  pw = pw.slice(0, -1);
57082
57980
  } else {
@@ -57090,7 +57988,7 @@ async function promptOwnerAuthPassword(sessionName) {
57090
57988
  const token = deriveOwnerAuthToken(sessionName, password);
57091
57989
  return token;
57092
57990
  }
57093
- var startCommand8, endCommand, handoffCommand2, statusCommand12, resumeCommand2, findCommand6, listCommand21, gcCommand2, showCommand13, driftCommand, contextDriftCommand, suspendCommand, recordAssumptionCommand, recordDecisionCommand, decisionLogCommand, sessionCommand;
57991
+ var startCommand7, endCommand, handoffCommand2, statusCommand12, resumeCommand2, findCommand6, listCommand21, gcCommand2, showCommand13, driftCommand, contextDriftCommand, suspendCommand, recordAssumptionCommand, recordDecisionCommand, decisionLogCommand, sessionCommand;
57094
57992
  var init_session4 = __esm({
57095
57993
  "packages/cleo/src/cli/commands/session.ts"() {
57096
57994
  "use strict";
@@ -57098,7 +57996,7 @@ var init_session4 = __esm({
57098
57996
  init_dist();
57099
57997
  init_cli();
57100
57998
  init_renderers();
57101
- startCommand8 = defineCommand({
57999
+ startCommand7 = defineCommand({
57102
58000
  meta: { name: "start", description: "Start a new session" },
57103
58001
  args: {
57104
58002
  scope: {
@@ -57444,8 +58342,8 @@ var init_session4 = __esm({
57444
58342
  "audit-scope": { type: "string", description: "Audit log scope (global|local)" }
57445
58343
  },
57446
58344
  async run({ args }) {
57447
- const { detectSessionDrift, getProjectRoot: getProjectRoot34 } = await import("@cleocode/core");
57448
- const projectRoot = await getProjectRoot34();
58345
+ const { detectSessionDrift, getProjectRoot: getProjectRoot38 } = await import("@cleocode/core");
58346
+ const projectRoot = await getProjectRoot38();
57449
58347
  const scope = args["audit-scope"] === "local" ? "local" : "global";
57450
58348
  const report = await detectSessionDrift({ projectRoot, auditScope: scope });
57451
58349
  cliOutput(report, { command: "session drift", operation: "session.drift" });
@@ -57614,7 +58512,7 @@ var init_session4 = __esm({
57614
58512
  sessionCommand = defineCommand({
57615
58513
  meta: { name: "session", description: "Manage work sessions" },
57616
58514
  subCommands: {
57617
- start: startCommand8,
58515
+ start: startCommand7,
57618
58516
  end: endCommand,
57619
58517
  stop: endCommand,
57620
58518
  handoff: handoffCommand2,
@@ -58358,15 +59256,15 @@ var init_snapshot = __esm({
58358
59256
  // packages/cleo/src/cli/commands/start.ts
58359
59257
  var start_exports = {};
58360
59258
  __export(start_exports, {
58361
- startCommand: () => startCommand9
59259
+ startCommand: () => startCommand8
58362
59260
  });
58363
- var startCommand9;
59261
+ var startCommand8;
58364
59262
  var init_start = __esm({
58365
59263
  "packages/cleo/src/cli/commands/start.ts"() {
58366
59264
  "use strict";
58367
59265
  init_dist();
58368
59266
  init_cli();
58369
- startCommand9 = defineCommand({
59267
+ startCommand8 = defineCommand({
58370
59268
  meta: {
58371
59269
  name: "start",
58372
59270
  description: "Start working on a task (sets it as the current task in the active session)"
@@ -59306,7 +60204,7 @@ __export(token_exports, {
59306
60204
  tokenCommand: () => tokenCommand
59307
60205
  });
59308
60206
  import { readFileSync as readFileSync16 } from "node:fs";
59309
- import { getProjectRoot as getProjectRoot32, measureTokenExchange, recordTokenExchange as recordTokenExchange2 } from "@cleocode/core/internal";
60207
+ import { getProjectRoot as getProjectRoot35, measureTokenExchange, recordTokenExchange as recordTokenExchange2 } from "@cleocode/core/internal";
59310
60208
  function readPayload(args, textKey, fileKey) {
59311
60209
  const text = args[textKey];
59312
60210
  const file = args[fileKey];
@@ -59470,7 +60368,7 @@ var init_token = __esm({
59470
60368
  domain: args.domain,
59471
60369
  operation: args.operation
59472
60370
  };
59473
- const result = args.record ? await recordTokenExchange2(getProjectRoot32(), input2) : await measureTokenExchange(input2);
60371
+ const result = args.record ? await recordTokenExchange2(getProjectRoot35(), input2) : await measureTokenExchange(input2);
59474
60372
  cliOutput(result, {
59475
60373
  command: "token",
59476
60374
  operation: args.record ? "admin.token.record" : "token.estimate"
@@ -59506,7 +60404,7 @@ __export(transcript_exports, {
59506
60404
  });
59507
60405
  import { homedir as homedir8 } from "node:os";
59508
60406
  import { join as join24 } from "node:path";
59509
- import { getProjectRoot as getProjectRoot33 } from "@cleocode/core";
60407
+ import { getProjectRoot as getProjectRoot36 } from "@cleocode/core";
59510
60408
  import {
59511
60409
  parseDurationMs,
59512
60410
  pruneTranscripts,
@@ -59536,7 +60434,7 @@ var init_transcript = __esm({
59536
60434
  async run({ args }) {
59537
60435
  if (args.pending) {
59538
60436
  try {
59539
- const projectRoot = getProjectRoot33();
60437
+ const projectRoot = getProjectRoot36();
59540
60438
  const { scanPendingTranscripts } = await import("@cleocode/core/memory/transcript-scanner.js");
59541
60439
  const pending = await scanPendingTranscripts(projectRoot);
59542
60440
  cliOutput(
@@ -59633,7 +60531,7 @@ var init_transcript = __esm({
59633
60531
  async run({ args }) {
59634
60532
  const tier = args.tier ?? "warm";
59635
60533
  const dryRun = args["dry-run"] ?? false;
59636
- const projectRoot = getProjectRoot33();
60534
+ const projectRoot = getProjectRoot36();
59637
60535
  try {
59638
60536
  const { extractTranscript } = await import("@cleocode/core/memory/transcript-extractor.js");
59639
60537
  const { findSessionTranscriptPath, listAllTranscripts } = await import("@cleocode/core/memory/transcript-scanner.js");
@@ -59745,7 +60643,7 @@ var init_transcript = __esm({
59745
60643
  const dryRun = args["dry-run"] ?? false;
59746
60644
  const olderThanHours = args["older-than-hours"] ? Number.parseInt(args["older-than-hours"], 10) : 24;
59747
60645
  const limit = args.limit ? Number.parseInt(args.limit, 10) : void 0;
59748
- const projectRoot = getProjectRoot33();
60646
+ const projectRoot = getProjectRoot36();
59749
60647
  try {
59750
60648
  const { extractTranscript } = await import("@cleocode/core/memory/transcript-extractor.js");
59751
60649
  const { listAllTranscripts } = await import("@cleocode/core/memory/transcript-scanner.js");
@@ -60229,19 +61127,90 @@ var upgrade_exports = {};
60229
61127
  __export(upgrade_exports, {
60230
61128
  upgradeCommand: () => upgradeCommand
60231
61129
  });
60232
- import { CleoError as CleoError11, diagnoseUpgrade, runUpgrade as runUpgrade2 } from "@cleocode/core/internal";
60233
- var upgradeCommand;
60234
- var init_upgrade = __esm({
61130
+ import { resolve as resolve7 } from "node:path";
61131
+ import { CleoError as CleoError11, diagnoseUpgrade, runUpgrade as runUpgrade2, upgradeWorkflows as upgradeWorkflows2 } from "@cleocode/core/internal";
61132
+ var workflowsSubcommand, upgradeCommand;
61133
+ var init_upgrade2 = __esm({
60235
61134
  "packages/cleo/src/cli/commands/upgrade.ts"() {
60236
61135
  "use strict";
60237
61136
  init_dist();
60238
61137
  init_progress();
60239
61138
  init_renderers();
61139
+ init_init();
61140
+ workflowsSubcommand = defineCommand({
61141
+ meta: {
61142
+ name: "workflows",
61143
+ description: "Re-render the four release-pipeline workflow templates and report drift (T9536)."
61144
+ },
61145
+ args: {
61146
+ "dry-run": {
61147
+ type: "boolean",
61148
+ description: "Print the per-template diff without writing.",
61149
+ default: false
61150
+ },
61151
+ check: {
61152
+ type: "boolean",
61153
+ description: "Exit 1 if drift is detected. Implies --dry-run for write semantics.",
61154
+ default: false
61155
+ },
61156
+ force: {
61157
+ type: "boolean",
61158
+ description: "Overwrite drifted files (excluding `.workflow-overrides.yml` keys).",
61159
+ default: false
61160
+ },
61161
+ json: { type: "boolean", description: "Output as JSON" },
61162
+ human: { type: "boolean", description: "Force human-readable output" },
61163
+ quiet: { type: "boolean", description: "Suppress non-essential output" }
61164
+ },
61165
+ async run({ args }) {
61166
+ try {
61167
+ const dryRun = args["dry-run"] === true || args.check === true;
61168
+ const force = args.force === true && !dryRun;
61169
+ const result = await upgradeWorkflows2({
61170
+ projectRoot: resolve7(process.cwd()),
61171
+ templatesDir: getWorkflowTemplatesDir(),
61172
+ dryRun,
61173
+ force
61174
+ });
61175
+ cliOutput(
61176
+ {
61177
+ outcomes: result.outcomes.map((o) => ({
61178
+ template: o.template,
61179
+ targetPath: o.targetPath,
61180
+ status: o.status,
61181
+ overrideDeclared: o.overrideDeclared
61182
+ })),
61183
+ resolvedTools: result.resolvedTools,
61184
+ hasDrift: result.hasDrift,
61185
+ ...dryRun ? {
61186
+ rendered: result.outcomes.map((o) => ({
61187
+ template: o.template,
61188
+ rendered: o.rendered
61189
+ }))
61190
+ } : {}
61191
+ },
61192
+ { command: "upgrade", operation: "upgrade.workflows" }
61193
+ );
61194
+ if (args.check === true && result.hasDrift) {
61195
+ process.exit(1);
61196
+ }
61197
+ } catch (err) {
61198
+ if (err instanceof CleoError11) {
61199
+ cliError(err.message, err.code, { name: "CleoError", fix: err.fix });
61200
+ process.exit(err.code);
61201
+ }
61202
+ throw err;
61203
+ }
61204
+ }
61205
+ });
60240
61206
  upgradeCommand = defineCommand({
60241
61207
  meta: {
60242
61208
  name: "upgrade",
60243
61209
  description: "Unified project maintenance (storage migration, schema repair, structural fixes, doc refresh)"
60244
61210
  },
61211
+ subCommands: {
61212
+ workflows: workflowsSubcommand
61213
+ },
60245
61214
  args: {
60246
61215
  status: {
60247
61216
  type: "boolean",
@@ -60289,7 +61258,9 @@ var init_upgrade = __esm({
60289
61258
  description: "Suppress non-essential output"
60290
61259
  }
60291
61260
  },
60292
- async run({ args }) {
61261
+ async run({ args, cmd, rawArgs }) {
61262
+ const firstPositional = rawArgs?.find((a) => !a.startsWith("-"));
61263
+ if (firstPositional && cmd.subCommands && firstPositional in cmd.subCommands) return;
60293
61264
  const isHuman = args.human === true || !!process.stdout.isTTY && args.json !== true;
60294
61265
  const progress = createUpgradeProgress(isHuman);
60295
61266
  try {
@@ -60562,7 +61533,7 @@ Logs: ${logFile}`
60562
61533
  }
60563
61534
  } catch {
60564
61535
  }
60565
- await new Promise((resolve5) => setTimeout(resolve5, 500));
61536
+ await new Promise((resolve8) => setTimeout(resolve8, 500));
60566
61537
  }
60567
61538
  if (!started) {
60568
61539
  try {
@@ -60583,7 +61554,7 @@ Logs: ${logFile}`
60583
61554
  { command: "web", message: `CLEO Web UI running on port ${port}` }
60584
61555
  );
60585
61556
  }
60586
- var DEFAULT_PORT, DEFAULT_HOST, startCommand10, stopCommand5, restartCommand, statusCommand15, openCommand, webCommand;
61557
+ var DEFAULT_PORT, DEFAULT_HOST, startCommand9, stopCommand5, restartCommand, statusCommand15, openCommand2, webCommand;
60587
61558
  var init_web = __esm({
60588
61559
  "packages/cleo/src/cli/commands/web.ts"() {
60589
61560
  "use strict";
@@ -60592,7 +61563,7 @@ var init_web = __esm({
60592
61563
  init_renderers();
60593
61564
  DEFAULT_PORT = 3456;
60594
61565
  DEFAULT_HOST = "127.0.0.1";
60595
- startCommand10 = defineCommand({
61566
+ startCommand9 = defineCommand({
60596
61567
  meta: { name: "start", description: "Start the web server" },
60597
61568
  args: {
60598
61569
  port: {
@@ -60639,7 +61610,7 @@ var init_web = __esm({
60639
61610
  }
60640
61611
  for (let i = 0; i < 60; i++) {
60641
61612
  if (!isProcessRunning(status.pid)) break;
60642
- await new Promise((resolve5) => setTimeout(resolve5, 500));
61613
+ await new Promise((resolve8) => setTimeout(resolve8, 500));
60643
61614
  }
60644
61615
  if (isProcessRunning(status.pid)) {
60645
61616
  try {
@@ -60691,7 +61662,7 @@ var init_web = __esm({
60691
61662
  }
60692
61663
  for (let i = 0; i < 60; i++) {
60693
61664
  if (!isProcessRunning(status.pid)) break;
60694
- await new Promise((resolve5) => setTimeout(resolve5, 500));
61665
+ await new Promise((resolve8) => setTimeout(resolve8, 500));
60695
61666
  }
60696
61667
  if (isProcessRunning(status.pid)) {
60697
61668
  try {
@@ -60730,7 +61701,7 @@ var init_web = __esm({
60730
61701
  }
60731
61702
  }
60732
61703
  });
60733
- openCommand = defineCommand({
61704
+ openCommand2 = defineCommand({
60734
61705
  meta: { name: "open", description: "Open browser to the UI" },
60735
61706
  async run() {
60736
61707
  try {
@@ -60766,11 +61737,11 @@ var init_web = __esm({
60766
61737
  webCommand = defineCommand({
60767
61738
  meta: { name: "web", description: "Manage CLEO Web UI server" },
60768
61739
  subCommands: {
60769
- start: startCommand10,
61740
+ start: startCommand9,
60770
61741
  stop: stopCommand5,
60771
61742
  restart: restartCommand,
60772
61743
  status: statusCommand15,
60773
- open: openCommand
61744
+ open: openCommand2
60774
61745
  },
60775
61746
  async run({ cmd, rawArgs }) {
60776
61747
  const firstArg = rawArgs?.find((a) => !a.startsWith("-"));
@@ -60781,13 +61752,242 @@ var init_web = __esm({
60781
61752
  }
60782
61753
  });
60783
61754
 
61755
+ // packages/cleo/src/cli/commands/worktree.ts
61756
+ var worktree_exports = {};
61757
+ __export(worktree_exports, {
61758
+ worktreeCommand: () => worktreeCommand
61759
+ });
61760
+ import readline4 from "node:readline";
61761
+ import { getProjectRoot as getProjectRoot37, listWorktrees as listWorktrees2 } from "@cleocode/core/internal";
61762
+ async function promptYesNo2(question) {
61763
+ return new Promise((resolve8) => {
61764
+ const rl = readline4.createInterface({ input: process.stdin, output: process.stdout });
61765
+ rl.question(`${question} [y/N]: `, (answer) => {
61766
+ rl.close();
61767
+ const trimmed = answer.trim().toLowerCase();
61768
+ resolve8(trimmed === "y" || trimmed === "yes");
61769
+ });
61770
+ });
61771
+ }
61772
+ function renderOrphanPreamble(wt) {
61773
+ return [
61774
+ "Orphaned worktree found:",
61775
+ ` Path: ${wt.path}`,
61776
+ ` Branch: ${wt.branch}${wt.isMerged ? " (merged to main)" : ""}`,
61777
+ ` Task status: ${wt.owningTaskStatus ?? "(missing)"}`,
61778
+ ` Last activity: ${wt.lastActivity}`,
61779
+ ""
61780
+ ].join("\n");
61781
+ }
61782
+ var VALID_STATUS_VALUES, listCommand25, pruneCommand3, forceUnlockCommand, worktreeCommand;
61783
+ var init_worktree3 = __esm({
61784
+ "packages/cleo/src/cli/commands/worktree.ts"() {
61785
+ "use strict";
61786
+ init_dist();
61787
+ init_cli();
61788
+ init_renderers();
61789
+ VALID_STATUS_VALUES = ["active", "stale", "merged", "orphan", "locked"];
61790
+ listCommand25 = defineCommand({
61791
+ meta: {
61792
+ name: "list",
61793
+ description: "List worktrees attached to this project with status classification (active|stale|merged|orphan|locked)."
61794
+ },
61795
+ args: {
61796
+ status: {
61797
+ type: "string",
61798
+ description: `Filter by status category (single value or comma-separated list of ${VALID_STATUS_VALUES.join("|")}).`
61799
+ },
61800
+ days: {
61801
+ type: "string",
61802
+ description: "Staleness threshold in days for the isStale classifier (default: 7)."
61803
+ }
61804
+ },
61805
+ async run({ args }) {
61806
+ const statusFilter = typeof args["status"] === "string" && args["status"].length > 0 ? args["status"] : void 0;
61807
+ const staleDaysRaw = typeof args["days"] === "string" ? args["days"] : void 0;
61808
+ const staleDays = staleDaysRaw !== void 0 ? Number.parseInt(staleDaysRaw, 10) : void 0;
61809
+ await dispatchFromCli(
61810
+ "query",
61811
+ "worktree",
61812
+ "list",
61813
+ {
61814
+ ...statusFilter !== void 0 ? { statusFilter } : {},
61815
+ ...staleDays !== void 0 && !Number.isNaN(staleDays) ? { staleDays } : {}
61816
+ },
61817
+ { command: "worktree-list", operation: "worktree.list" }
61818
+ );
61819
+ }
61820
+ });
61821
+ pruneCommand3 = defineCommand({
61822
+ meta: {
61823
+ name: "prune",
61824
+ description: "Remove orphan/merged worktrees with per-orphan Y/N confirmation."
61825
+ },
61826
+ args: {
61827
+ orphaned: {
61828
+ type: "boolean",
61829
+ description: "Prune worktrees classified as orphan or merged (required).",
61830
+ default: false
61831
+ },
61832
+ yes: {
61833
+ type: "boolean",
61834
+ description: "Skip per-orphan confirmation. Required on non-TTY (CI / pipe) input.",
61835
+ default: false
61836
+ },
61837
+ "dry-run": {
61838
+ type: "boolean",
61839
+ description: "Show what would be pruned without acting. No audit-log entries written.",
61840
+ default: false
61841
+ },
61842
+ days: {
61843
+ type: "string",
61844
+ description: "Override staleness threshold passed through to the listing (default: 7)."
61845
+ }
61846
+ },
61847
+ async run({ args }) {
61848
+ if (args["orphaned"] !== true) {
61849
+ cliError(
61850
+ "cleo worktree prune requires --orphaned (other categories are reserved for future flags).",
61851
+ 2
61852
+ );
61853
+ process.exit(2);
61854
+ return;
61855
+ }
61856
+ const dryRun = args["dry-run"] === true;
61857
+ const yes = args["yes"] === true;
61858
+ const staleDaysRaw = typeof args["days"] === "string" ? args["days"] : void 0;
61859
+ const staleDays = staleDaysRaw !== void 0 ? Number.parseInt(staleDaysRaw, 10) : void 0;
61860
+ const projectRoot = getProjectRoot37();
61861
+ const listResult = await listWorktrees2({
61862
+ projectRoot,
61863
+ ...staleDays !== void 0 && !Number.isNaN(staleDays) ? { staleDays } : {}
61864
+ });
61865
+ if (!listResult.success) {
61866
+ cliError(`Failed to enumerate worktrees: ${listResult.error.message}`, 1);
61867
+ process.exit(1);
61868
+ return;
61869
+ }
61870
+ const candidates = listResult.data.worktrees.filter(
61871
+ (w) => w.statusCategory === "orphan" || w.statusCategory === "merged"
61872
+ );
61873
+ if (candidates.length === 0) {
61874
+ cliOutput(
61875
+ {
61876
+ prunedCount: 0,
61877
+ skippedCount: 0,
61878
+ outcomes: [],
61879
+ errors: [],
61880
+ dryRun,
61881
+ message: "No orphan or merged worktrees found."
61882
+ },
61883
+ { command: "worktree-prune", operation: "worktree.prune" }
61884
+ );
61885
+ return;
61886
+ }
61887
+ const isTty = process.stdin.isTTY === true;
61888
+ if (!isTty && !yes && !dryRun) {
61889
+ cliError(
61890
+ "cleo worktree prune is interactive \u2014 re-run with --yes or --dry-run on non-TTY input.",
61891
+ 2
61892
+ );
61893
+ process.exit(2);
61894
+ return;
61895
+ }
61896
+ let confirmedPaths;
61897
+ let skippedByUser = 0;
61898
+ if (dryRun || yes) {
61899
+ confirmedPaths = candidates.map((w) => w.path);
61900
+ } else {
61901
+ confirmedPaths = [];
61902
+ for (const wt of candidates) {
61903
+ process.stdout.write(renderOrphanPreamble(wt));
61904
+ const accepted = await promptYesNo2("Prune this worktree?");
61905
+ if (accepted) {
61906
+ confirmedPaths.push(wt.path);
61907
+ } else {
61908
+ skippedByUser += 1;
61909
+ }
61910
+ }
61911
+ }
61912
+ if (confirmedPaths.length === 0) {
61913
+ cliOutput(
61914
+ {
61915
+ prunedCount: 0,
61916
+ skippedCount: skippedByUser,
61917
+ outcomes: [],
61918
+ errors: [],
61919
+ dryRun,
61920
+ message: skippedByUser > 0 ? `Skipped ${skippedByUser} orphan(s) on user request.` : "No-op."
61921
+ },
61922
+ { command: "worktree-prune", operation: "worktree.prune" }
61923
+ );
61924
+ return;
61925
+ }
61926
+ await dispatchFromCli(
61927
+ "mutate",
61928
+ "worktree",
61929
+ "prune",
61930
+ {
61931
+ dryRun,
61932
+ paths: confirmedPaths,
61933
+ ...staleDays !== void 0 && !Number.isNaN(staleDays) ? { staleDays } : {}
61934
+ },
61935
+ { command: "worktree-prune", operation: "worktree.prune" }
61936
+ );
61937
+ }
61938
+ });
61939
+ forceUnlockCommand = defineCommand({
61940
+ meta: {
61941
+ name: "force-unlock",
61942
+ description: "Clear wedged lock state (.git/index.lock + git worktree unlock) for a task."
61943
+ },
61944
+ args: {
61945
+ taskId: {
61946
+ type: "positional",
61947
+ description: "The task ID whose worktree should be force-unlocked (e.g. T9547).",
61948
+ required: true
61949
+ }
61950
+ },
61951
+ async run({ args }) {
61952
+ const rawTaskId = typeof args["taskId"] === "string" ? args["taskId"] : "";
61953
+ if (rawTaskId.length === 0) {
61954
+ cliError("Missing required positional: <taskId>.", 2);
61955
+ process.exit(2);
61956
+ return;
61957
+ }
61958
+ await dispatchFromCli(
61959
+ "mutate",
61960
+ "worktree",
61961
+ "forceUnlock",
61962
+ { taskId: rawTaskId },
61963
+ { command: "worktree-force-unlock", operation: "worktree.forceUnlock" }
61964
+ );
61965
+ }
61966
+ });
61967
+ worktreeCommand = defineCommand({
61968
+ meta: {
61969
+ name: "worktree",
61970
+ description: "Inspect and manage CLEO-attached git worktrees. See `cleo worktree <subcommand> --help` for details."
61971
+ },
61972
+ subCommands: {
61973
+ list: listCommand25,
61974
+ prune: pruneCommand3,
61975
+ "force-unlock": forceUnlockCommand
61976
+ },
61977
+ async run() {
61978
+ await showUsage(worktreeCommand);
61979
+ }
61980
+ });
61981
+ }
61982
+ });
61983
+
60784
61984
  // packages/cleo/src/cli/index.ts
60785
61985
  init_dist();
60786
61986
  init_field_context();
60787
61987
  init_format_context();
60788
61988
  import { readFileSync as readFileSync17 } from "node:fs";
60789
- import { dirname as dirname8, join as join27 } from "node:path";
60790
- import { fileURLToPath as fileURLToPath5 } from "node:url";
61989
+ import { dirname as dirname10, join as join27 } from "node:path";
61990
+ import { fileURLToPath as fileURLToPath6 } from "node:url";
60791
61991
 
60792
61992
  // packages/cleo/src/cli/generated/command-manifest.ts
60793
61993
  var COMMAND_MANIFEST = [
@@ -61311,7 +62511,7 @@ var COMMAND_MANIFEST = [
61311
62511
  exportName: "planCommand",
61312
62512
  name: "plan",
61313
62513
  description: "Task prioritization view: in-progress epics, ready tasks, blocked tasks, open bugs with scoring. Use when deciding what to work on next.",
61314
- load: async () => (await Promise.resolve().then(() => (init_plan(), plan_exports))).planCommand
62514
+ load: async () => (await Promise.resolve().then(() => (init_plan2(), plan_exports))).planCommand
61315
62515
  },
61316
62516
  {
61317
62517
  exportName: "playbookCommand",
@@ -61325,6 +62525,12 @@ var COMMAND_MANIFEST = [
61325
62525
  description: "Remove parent from task, making it root-level",
61326
62526
  load: async () => (await Promise.resolve().then(() => (init_promote(), promote_exports))).promoteCommand
61327
62527
  },
62528
+ {
62529
+ exportName: "provenanceCommand",
62530
+ name: "provenance",
62531
+ description: "Provenance-graph maintenance: backfill, verify, repair",
62532
+ load: async () => (await Promise.resolve().then(() => (init_provenance2(), provenance_exports))).provenanceCommand
62533
+ },
61328
62534
  {
61329
62535
  exportName: "providerCommand",
61330
62536
  name: "provider",
@@ -61557,7 +62763,7 @@ var COMMAND_MANIFEST = [
61557
62763
  exportName: "upgradeCommand",
61558
62764
  name: "upgrade",
61559
62765
  description: "Unified project maintenance (storage migration, schema repair, structural fixes, doc refresh)",
61560
- load: async () => (await Promise.resolve().then(() => (init_upgrade(), upgrade_exports))).upgradeCommand
62766
+ load: async () => (await Promise.resolve().then(() => (init_upgrade2(), upgrade_exports))).upgradeCommand
61561
62767
  },
61562
62768
  {
61563
62769
  exportName: "verifyCommand",
@@ -61570,6 +62776,12 @@ var COMMAND_MANIFEST = [
61570
62776
  name: "web",
61571
62777
  description: "Manage CLEO Web UI server",
61572
62778
  load: async () => (await Promise.resolve().then(() => (init_web(), web_exports))).webCommand
62779
+ },
62780
+ {
62781
+ exportName: "worktreeCommand",
62782
+ name: "worktree",
62783
+ description: "Inspect CLEO-managed git worktrees attached to this project. ",
62784
+ load: async () => (await Promise.resolve().then(() => (init_worktree3(), worktree_exports))).worktreeCommand
61573
62785
  }
61574
62786
  ];
61575
62787
 
@@ -61893,7 +63105,7 @@ async function detectFirstRun() {
61893
63105
  return true;
61894
63106
  }
61895
63107
  function waitForEnterOrTimeout(timeoutMs) {
61896
- return new Promise((resolve5) => {
63108
+ return new Promise((resolve8) => {
61897
63109
  let resolved = false;
61898
63110
  const finish = () => {
61899
63111
  if (resolved) return;
@@ -61905,7 +63117,7 @@ function waitForEnterOrTimeout(timeoutMs) {
61905
63117
  process.stdin.pause();
61906
63118
  } catch {
61907
63119
  }
61908
- resolve5();
63120
+ resolve8();
61909
63121
  };
61910
63122
  const onData = (chunk) => {
61911
63123
  const s = typeof chunk === "string" ? chunk : chunk.toString("utf8");
@@ -61970,7 +63182,7 @@ Or via NodeSource: https://github.com/nodesource/distributions
61970
63182
  }
61971
63183
  }
61972
63184
  function getPackageVersion() {
61973
- const pkgPath = join27(dirname8(fileURLToPath5(import.meta.url)), "../../package.json");
63185
+ const pkgPath = join27(dirname10(fileURLToPath6(import.meta.url)), "../../package.json");
61974
63186
  const pkg = JSON.parse(readFileSync17(pkgPath, "utf-8"));
61975
63187
  return pkg.version;
61976
63188
  }
@@ -62073,8 +63285,8 @@ async function runStartupMaintenance() {
62073
63285
  detectAndRemoveLegacyGlobalFiles,
62074
63286
  detectAndRemoveStrayProjectNexus,
62075
63287
  getGlobalSalt,
62076
- getLogger: getLogger17,
62077
- getProjectRoot: getProjectRoot34,
63288
+ getLogger: getLogger20,
63289
+ getProjectRoot: getProjectRoot38,
62078
63290
  isCleanupMarkerSet,
62079
63291
  migrateSignaldockToConduit,
62080
63292
  needsSignaldockToConduitMigration,
@@ -62083,7 +63295,7 @@ async function runStartupMaintenance() {
62083
63295
  } = await import("@cleocode/core/internal");
62084
63296
  let projectRootForCleanup = "";
62085
63297
  try {
62086
- projectRootForCleanup = getProjectRoot34();
63298
+ projectRootForCleanup = getProjectRoot38();
62087
63299
  } catch {
62088
63300
  }
62089
63301
  if (!isCleanupMarkerSet(CLI_VERSION, projectRootForCleanup)) {
@@ -62099,11 +63311,11 @@ async function runStartupMaintenance() {
62099
63311
  }
62100
63312
  setCleanupMarker(CLI_VERSION, projectRootForCleanup);
62101
63313
  }
62102
- const _startupLog = getLogger17("cli-startup");
63314
+ const _startupLog = getLogger20("cli-startup");
62103
63315
  const isInitInvocation = process.argv.slice(2).some((a) => a === "init");
62104
63316
  if (!isInitInvocation) {
62105
63317
  try {
62106
- const _projectRootForMigration = getProjectRoot34();
63318
+ const _projectRootForMigration = getProjectRoot38();
62107
63319
  if (needsSignaldockToConduitMigration(_projectRootForMigration)) {
62108
63320
  const migrationResult = migrateSignaldockToConduit(_projectRootForMigration);
62109
63321
  if (migrationResult.status === "failed") {