@cleocode/cleo 2026.5.90 → 2026.5.92

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
@@ -2582,8 +2582,41 @@ var init_peer = __esm({
2582
2582
  }
2583
2583
  });
2584
2584
 
2585
- // packages/contracts/src/release/plan.ts
2585
+ // packages/contracts/src/release/evidence-atoms.ts
2586
2586
  import { z as z5 } from "zod";
2587
+ var parsedPrEvidenceAtomSchema, ghPrViewSchema, PR_REQUIRED_WORKFLOWS;
2588
+ var init_evidence_atoms = __esm({
2589
+ "packages/contracts/src/release/evidence-atoms.ts"() {
2590
+ "use strict";
2591
+ parsedPrEvidenceAtomSchema = z5.object({
2592
+ kind: z5.literal("pr"),
2593
+ prNumber: z5.number().int().positive()
2594
+ });
2595
+ ghPrViewSchema = z5.object({
2596
+ state: z5.enum(["OPEN", "CLOSED", "MERGED"]),
2597
+ mergedAt: z5.string().nullable(),
2598
+ headRefOid: z5.string().optional(),
2599
+ mergeable: z5.string().optional(),
2600
+ statusCheckRollup: z5.array(
2601
+ z5.object({
2602
+ __typename: z5.string().optional(),
2603
+ name: z5.string().optional(),
2604
+ workflowName: z5.string().optional(),
2605
+ conclusion: z5.string().nullable().optional(),
2606
+ status: z5.string().optional()
2607
+ }).passthrough()
2608
+ ).optional().default([])
2609
+ }).passthrough();
2610
+ PR_REQUIRED_WORKFLOWS = Object.freeze([
2611
+ "CI",
2612
+ "Lockfile Check",
2613
+ "Contracts Dep Lint"
2614
+ ]);
2615
+ }
2616
+ });
2617
+
2618
+ // packages/contracts/src/release/plan.ts
2619
+ import { z as z6 } from "zod";
2587
2620
  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;
2588
2621
  var init_plan = __esm({
2589
2622
  "packages/contracts/src/release/plan.ts"() {
@@ -2626,20 +2659,20 @@ var init_plan = __esm({
2626
2659
  ];
2627
2660
  IMPACT = ["major", "minor", "patch"];
2628
2661
  RESOLVED_SOURCE = ["project-context", "language-default", "legacy-alias"];
2629
- ReleaseChannelSchema = z5.enum(RELEASE_CHANNEL);
2630
- ReleaseSchemeSchema = z5.enum(RELEASE_SCHEME);
2631
- ReleaseKindSchema = z5.enum(RELEASE_KIND);
2632
- ReleaseStatusSchema = z5.enum(RELEASE_STATUS);
2633
- GateStatusSchema = z5.enum(GATE_STATUS);
2634
- GateNameSchema = z5.enum(GATE_NAME);
2635
- PlatformTupleSchema = z5.enum(PLATFORM_TUPLE);
2636
- PublisherSchema = z5.enum(PUBLISHER);
2637
- TaskKindSchema = z5.enum(TASK_KIND);
2638
- ImpactSchema = z5.enum(IMPACT);
2639
- ResolvedSourceSchema = z5.enum(RESOLVED_SOURCE);
2640
- Iso8601 = z5.iso.datetime({ offset: true });
2641
- NonEmptyString = z5.string().min(1);
2642
- ReleasePlanTaskSchema = z5.object({
2662
+ ReleaseChannelSchema = z6.enum(RELEASE_CHANNEL);
2663
+ ReleaseSchemeSchema = z6.enum(RELEASE_SCHEME);
2664
+ ReleaseKindSchema = z6.enum(RELEASE_KIND);
2665
+ ReleaseStatusSchema = z6.enum(RELEASE_STATUS);
2666
+ GateStatusSchema = z6.enum(GATE_STATUS);
2667
+ GateNameSchema = z6.enum(GATE_NAME);
2668
+ PlatformTupleSchema = z6.enum(PLATFORM_TUPLE);
2669
+ PublisherSchema = z6.enum(PUBLISHER);
2670
+ TaskKindSchema = z6.enum(TASK_KIND);
2671
+ ImpactSchema = z6.enum(IMPACT);
2672
+ ResolvedSourceSchema = z6.enum(RESOLVED_SOURCE);
2673
+ Iso8601 = z6.iso.datetime({ offset: true });
2674
+ NonEmptyString = z6.string().min(1);
2675
+ ReleasePlanTaskSchema = z6.object({
2643
2676
  /** Task ID (e.g. "T10001"). Format intentionally loose so historical IDs validate. */
2644
2677
  id: NonEmptyString,
2645
2678
  /** Conventional-commit-aligned task classification. */
@@ -2647,20 +2680,20 @@ var init_plan = __esm({
2647
2680
  /** SemVer impact classification. */
2648
2681
  impact: ImpactSchema,
2649
2682
  /** Human-readable changelog line for this task. */
2650
- userFacingSummary: z5.string(),
2683
+ userFacingSummary: z6.string(),
2651
2684
  /**
2652
2685
  * ADR-051 evidence atoms attesting the task's gate results. Format is
2653
2686
  * `kind:value` (e.g. `commit:abc123`, `test-run:vitest.json`). The contract
2654
2687
  * accepts empty arrays so legacy plans validate; `cleo release plan`
2655
2688
  * enforces non-empty via R-301.
2656
2689
  */
2657
- evidenceAtoms: z5.array(NonEmptyString),
2690
+ evidenceAtoms: z6.array(NonEmptyString),
2658
2691
  /** IVTR phase at plan time — informational only per R-316. */
2659
- ivtrPhaseAtPlan: z5.string().optional(),
2692
+ ivtrPhaseAtPlan: z6.string().optional(),
2660
2693
  /** Epic this task rolls up to, locked at plan time per R-303. */
2661
2694
  epicAncestor: NonEmptyString
2662
2695
  });
2663
- ReleaseGateSchema = z5.object({
2696
+ ReleaseGateSchema = z6.object({
2664
2697
  /** Canonical gate name. */
2665
2698
  name: GateNameSchema,
2666
2699
  /** ADR-051 atom string identifying the resolved tool (e.g. `tool:test`). */
@@ -2670,11 +2703,11 @@ var init_plan = __esm({
2670
2703
  /** ISO-8601 timestamp the gate was last verified. */
2671
2704
  lastVerifiedAt: Iso8601,
2672
2705
  /** Resolved shell command (e.g. `pnpm run test`). Optional for unresolved gates. */
2673
- resolvedCommand: z5.string().optional(),
2706
+ resolvedCommand: z6.string().optional(),
2674
2707
  /** Provenance of the resolved command. Optional for unresolved gates. */
2675
2708
  resolvedSource: ResolvedSourceSchema.optional()
2676
2709
  });
2677
- ReleasePlatformMatrixEntrySchema = z5.object({
2710
+ ReleasePlatformMatrixEntrySchema = z6.object({
2678
2711
  /** Target platform tuple. */
2679
2712
  platform: PlatformTupleSchema,
2680
2713
  /** Distribution backend. */
@@ -2682,47 +2715,47 @@ var init_plan = __esm({
2682
2715
  /** Package identifier on the target backend (e.g. `@cleocode/cleo`). */
2683
2716
  package: NonEmptyString,
2684
2717
  /** Whether to run the GHA smoke job for this matrix entry. */
2685
- smoke: z5.boolean().default(true).optional()
2718
+ smoke: z6.boolean().default(true).optional()
2686
2719
  });
2687
- ReleasePreflightSummarySchema = z5.object({
2720
+ ReleasePreflightSummarySchema = z6.object({
2688
2721
  /** True if esbuild externals are out of sync with package.json. */
2689
- esbuildExternalsDrift: z5.boolean(),
2722
+ esbuildExternalsDrift: z6.boolean(),
2690
2723
  /** True if `pnpm-lock.yaml` diverges from the workspace manifest. */
2691
- lockfileDrift: z5.boolean(),
2724
+ lockfileDrift: z6.boolean(),
2692
2725
  /** True if all epic children are in terminal lifecycle states. */
2693
- epicCompletenessClean: z5.boolean(),
2726
+ epicCompletenessClean: z6.boolean(),
2694
2727
  /** True if no task appears in multiple in-flight release plans. */
2695
- doubleListingClean: z5.boolean(),
2728
+ doubleListingClean: z6.boolean(),
2696
2729
  /** Non-fatal preflight warnings (e.g. unresolved tools per R-024). */
2697
- preflightWarnings: z5.array(z5.string()).default([]).optional()
2730
+ preflightWarnings: z6.array(z6.string()).default([]).optional()
2698
2731
  });
2699
- ReleasePlanChangelogSchema = z5.object({
2732
+ ReleasePlanChangelogSchema = z6.object({
2700
2733
  /** `kind=feat` tasks. */
2701
- features: z5.array(NonEmptyString).default([]),
2734
+ features: z6.array(NonEmptyString).default([]),
2702
2735
  /** `kind=fix` or `kind=hotfix` tasks. */
2703
- fixes: z5.array(NonEmptyString).default([]),
2736
+ fixes: z6.array(NonEmptyString).default([]),
2704
2737
  /** `kind=chore`, `docs`, `refactor`, `test`, `perf` tasks. */
2705
- chores: z5.array(NonEmptyString).default([]),
2738
+ chores: z6.array(NonEmptyString).default([]),
2706
2739
  /** `kind=breaking` or `kind=revert` tasks. */
2707
- breaking: z5.array(NonEmptyString).default([])
2740
+ breaking: z6.array(NonEmptyString).default([])
2708
2741
  });
2709
- ReleasePlanMetaSchema = z5.object({
2742
+ ReleasePlanMetaSchema = z6.object({
2710
2743
  /** True if this is the project's first ever release. */
2711
- firstEverRelease: z5.boolean().optional(),
2744
+ firstEverRelease: z6.boolean().optional(),
2712
2745
  /** Canonical tool names that could not be resolved at plan time. */
2713
- unresolvedTools: z5.array(z5.string()).optional(),
2746
+ unresolvedTools: z6.array(z6.string()).optional(),
2714
2747
  /** Project archetype detected at plan time. */
2715
- archetype: z5.string().optional()
2716
- }).catchall(z5.unknown());
2717
- ReleasePlanSchema = z5.object({
2748
+ archetype: z6.string().optional()
2749
+ }).catchall(z6.unknown());
2750
+ ReleasePlanSchema = z6.object({
2718
2751
  /** Schema URL for this plan version. */
2719
- $schema: z5.string().optional(),
2752
+ $schema: z6.string().optional(),
2720
2753
  /** Requested version string (e.g. "v2026.6.0"). Includes the leading `v`. */
2721
2754
  version: NonEmptyString,
2722
2755
  /** Resolved version string after suffix application (e.g. "v2026.6.0.2"). */
2723
2756
  resolvedVersion: NonEmptyString,
2724
2757
  /** True if a `calver-suffix` was applied to disambiguate a same-day hotfix. */
2725
- suffixApplied: z5.boolean(),
2758
+ suffixApplied: z6.boolean(),
2726
2759
  /** Versioning scheme governing `version` / `resolvedVersion`. */
2727
2760
  scheme: ReleaseSchemeSchema,
2728
2761
  /** npm dist-tag channel for this release. */
@@ -2739,27 +2772,27 @@ var init_plan = __esm({
2739
2772
  * Version of the previous release on the same channel. MUST be `null` only
2740
2773
  * for first-ever releases (R-300, enforced at the verb layer).
2741
2774
  */
2742
- previousVersion: z5.string().nullable(),
2775
+ previousVersion: z6.string().nullable(),
2743
2776
  /** Git tag of the previous release (typically `previousVersion` prefixed). */
2744
- previousTag: z5.string().nullable(),
2777
+ previousTag: z6.string().nullable(),
2745
2778
  /** ISO-8601 timestamp the previous release was published. */
2746
2779
  previousShippedAt: Iso8601.nullable(),
2747
2780
  /** Tasks rolled into this release. */
2748
- tasks: z5.array(ReleasePlanTaskSchema),
2781
+ tasks: z6.array(ReleasePlanTaskSchema),
2749
2782
  /** Bucketed changelog. */
2750
2783
  changelog: ReleasePlanChangelogSchema,
2751
2784
  /** Per-gate verification status. */
2752
- gates: z5.array(ReleaseGateSchema),
2785
+ gates: z6.array(ReleaseGateSchema),
2753
2786
  /** Platform / publisher matrix. */
2754
- platformMatrix: z5.array(ReleasePlatformMatrixEntrySchema),
2787
+ platformMatrix: z6.array(ReleasePlatformMatrixEntrySchema),
2755
2788
  /** Preflight summary from `cleo release plan`. */
2756
2789
  preflightSummary: ReleasePreflightSummarySchema,
2757
2790
  /** URL of the GHA workflow run (populated by `release-prepare.yml`). */
2758
- workflowRunUrl: z5.string().nullable(),
2791
+ workflowRunUrl: z6.string().nullable(),
2759
2792
  /** URL of the bump PR (populated by `cleo release open`). */
2760
- prUrl: z5.string().nullable(),
2793
+ prUrl: z6.string().nullable(),
2761
2794
  /** Merge commit SHA on `main` (populated by `release-publish.yml`). */
2762
- mergeCommitSha: z5.string().nullable(),
2795
+ mergeCommitSha: z6.string().nullable(),
2763
2796
  /** Current FSM state per R-302. */
2764
2797
  status: ReleaseStatusSchema,
2765
2798
  /** Informational / forward-compat metadata. */
@@ -2776,52 +2809,52 @@ var init_session2 = __esm({
2776
2809
  });
2777
2810
 
2778
2811
  // packages/contracts/src/session-journal.ts
2779
- import { z as z6 } from "zod";
2812
+ import { z as z7 } from "zod";
2780
2813
  var SESSION_JOURNAL_SCHEMA_VERSION, sessionJournalDoctorSummarySchema, sessionJournalDebriefSummarySchema, sessionJournalEntrySchema;
2781
2814
  var init_session_journal = __esm({
2782
2815
  "packages/contracts/src/session-journal.ts"() {
2783
2816
  "use strict";
2784
2817
  SESSION_JOURNAL_SCHEMA_VERSION = "1.0";
2785
- sessionJournalDoctorSummarySchema = z6.object({
2818
+ sessionJournalDoctorSummarySchema = z7.object({
2786
2819
  /** `true` when zero noise patterns were detected. */
2787
- isClean: z6.boolean(),
2820
+ isClean: z7.boolean(),
2788
2821
  /** Total number of noise findings across all patterns. */
2789
- findingsCount: z6.number().int().nonnegative(),
2822
+ findingsCount: z7.number().int().nonnegative(),
2790
2823
  /** Pattern names that were detected (empty when isClean). */
2791
- patterns: z6.array(z6.string()),
2824
+ patterns: z7.array(z7.string()),
2792
2825
  /** Total brain entries scanned. `0` = empty or unavailable. */
2793
- totalScanned: z6.number().int().nonnegative()
2826
+ totalScanned: z7.number().int().nonnegative()
2794
2827
  });
2795
- sessionJournalDebriefSummarySchema = z6.object({
2828
+ sessionJournalDebriefSummarySchema = z7.object({
2796
2829
  /** First 200 characters of the session end note (if provided). */
2797
- noteExcerpt: z6.string().max(200).optional(),
2830
+ noteExcerpt: z7.string().max(200).optional(),
2798
2831
  /** Number of tasks completed during the session. */
2799
- tasksCompletedCount: z6.number().int().nonnegative(),
2832
+ tasksCompletedCount: z7.number().int().nonnegative(),
2800
2833
  /** Up to 5 task IDs (not titles) that were the focus of the session. */
2801
- tasksFocused: z6.array(z6.string()).max(5).optional()
2834
+ tasksFocused: z7.array(z7.string()).max(5).optional()
2802
2835
  });
2803
- sessionJournalEntrySchema = z6.object({
2836
+ sessionJournalEntrySchema = z7.object({
2804
2837
  // Identity
2805
2838
  /** Schema version for forward-compatibility. Always `'1.0'` in this release. */
2806
- schemaVersion: z6.literal(SESSION_JOURNAL_SCHEMA_VERSION),
2839
+ schemaVersion: z7.literal(SESSION_JOURNAL_SCHEMA_VERSION),
2807
2840
  /** ISO 8601 timestamp when the entry was written. */
2808
- timestamp: z6.string(),
2841
+ timestamp: z7.string(),
2809
2842
  /** CLEO session ID (e.g. `ses_20260424055456_ede571`). */
2810
- sessionId: z6.string(),
2843
+ sessionId: z7.string(),
2811
2844
  /** Event type that triggered this journal entry. */
2812
- eventType: z6.enum(["session_start", "session_end", "observation", "decision", "error"]),
2845
+ eventType: z7.enum(["session_start", "session_end", "observation", "decision", "error"]),
2813
2846
  // Session metadata (set on session_start / session_end)
2814
2847
  /** Agent identifier (e.g. `cleo-prime`, `claude-code`). */
2815
- agentIdentifier: z6.string().optional(),
2848
+ agentIdentifier: z7.string().optional(),
2816
2849
  /** Provider adapter ID active for this session. */
2817
- providerId: z6.string().optional(),
2850
+ providerId: z7.string().optional(),
2818
2851
  /** Session scope string (e.g. `'global'` or `'epic:T1263'`). */
2819
- scope: z6.string().optional(),
2852
+ scope: z7.string().optional(),
2820
2853
  // Session-end fields
2821
2854
  /** Duration of the session in seconds (session_end only). */
2822
- duration: z6.number().int().nonnegative().optional(),
2855
+ duration: z7.number().int().nonnegative().optional(),
2823
2856
  /** Task IDs (not titles) completed during the session. */
2824
- tasksCompleted: z6.array(z6.string()).optional(),
2857
+ tasksCompleted: z7.array(z7.string()).optional(),
2825
2858
  // Doctor summary (T1262 absorbed)
2826
2859
  /** Compact result of `scanBrainNoise` run at session-end. */
2827
2860
  doctorSummary: sessionJournalDoctorSummarySchema.optional(),
@@ -2830,7 +2863,7 @@ var init_session_journal = __esm({
2830
2863
  debriefSummary: sessionJournalDebriefSummarySchema.optional(),
2831
2864
  // Optional hash chain
2832
2865
  /** SHA-256 hex of the previous entry's raw JSON string (for integrity chain). */
2833
- prevEntryHash: z6.string().optional()
2866
+ prevEntryHash: z7.string().optional()
2834
2867
  });
2835
2868
  }
2836
2869
  });
@@ -2876,52 +2909,52 @@ var init_task = __esm({
2876
2909
  });
2877
2910
 
2878
2911
  // packages/contracts/src/task-evidence.ts
2879
- import { z as z7 } from "zod";
2912
+ import { z as z8 } from "zod";
2880
2913
  var fileEvidenceSchema, logEvidenceSchema, screenshotEvidenceSchema, testOutputEvidenceSchema, commandOutputEvidenceSchema, taskEvidenceSchema;
2881
2914
  var init_task_evidence = __esm({
2882
2915
  "packages/contracts/src/task-evidence.ts"() {
2883
2916
  "use strict";
2884
- fileEvidenceSchema = z7.object({
2885
- kind: z7.literal("file"),
2886
- sha256: z7.string().length(64),
2887
- timestamp: z7.string().datetime(),
2888
- path: z7.string().min(1),
2889
- mime: z7.string().optional(),
2890
- description: z7.string().optional()
2891
- });
2892
- logEvidenceSchema = z7.object({
2893
- kind: z7.literal("log"),
2894
- sha256: z7.string().length(64),
2895
- timestamp: z7.string().datetime(),
2896
- source: z7.string().min(1),
2897
- description: z7.string().optional()
2898
- });
2899
- screenshotEvidenceSchema = z7.object({
2900
- kind: z7.literal("screenshot"),
2901
- sha256: z7.string().length(64),
2902
- timestamp: z7.string().datetime(),
2903
- mime: z7.enum(["image/png", "image/jpeg", "image/webp"]).optional(),
2904
- description: z7.string().optional()
2905
- });
2906
- testOutputEvidenceSchema = z7.object({
2907
- kind: z7.literal("test-output"),
2908
- sha256: z7.string().length(64),
2909
- timestamp: z7.string().datetime(),
2910
- passed: z7.number().int().nonnegative(),
2911
- failed: z7.number().int().nonnegative(),
2912
- skipped: z7.number().int().nonnegative(),
2913
- exitCode: z7.number().int(),
2914
- description: z7.string().optional()
2915
- });
2916
- commandOutputEvidenceSchema = z7.object({
2917
- kind: z7.literal("command-output"),
2918
- sha256: z7.string().length(64),
2919
- timestamp: z7.string().datetime(),
2920
- cmd: z7.string().min(1),
2921
- exitCode: z7.number().int(),
2922
- description: z7.string().optional()
2923
- });
2924
- taskEvidenceSchema = z7.discriminatedUnion("kind", [
2917
+ fileEvidenceSchema = z8.object({
2918
+ kind: z8.literal("file"),
2919
+ sha256: z8.string().length(64),
2920
+ timestamp: z8.string().datetime(),
2921
+ path: z8.string().min(1),
2922
+ mime: z8.string().optional(),
2923
+ description: z8.string().optional()
2924
+ });
2925
+ logEvidenceSchema = z8.object({
2926
+ kind: z8.literal("log"),
2927
+ sha256: z8.string().length(64),
2928
+ timestamp: z8.string().datetime(),
2929
+ source: z8.string().min(1),
2930
+ description: z8.string().optional()
2931
+ });
2932
+ screenshotEvidenceSchema = z8.object({
2933
+ kind: z8.literal("screenshot"),
2934
+ sha256: z8.string().length(64),
2935
+ timestamp: z8.string().datetime(),
2936
+ mime: z8.enum(["image/png", "image/jpeg", "image/webp"]).optional(),
2937
+ description: z8.string().optional()
2938
+ });
2939
+ testOutputEvidenceSchema = z8.object({
2940
+ kind: z8.literal("test-output"),
2941
+ sha256: z8.string().length(64),
2942
+ timestamp: z8.string().datetime(),
2943
+ passed: z8.number().int().nonnegative(),
2944
+ failed: z8.number().int().nonnegative(),
2945
+ skipped: z8.number().int().nonnegative(),
2946
+ exitCode: z8.number().int(),
2947
+ description: z8.string().optional()
2948
+ });
2949
+ commandOutputEvidenceSchema = z8.object({
2950
+ kind: z8.literal("command-output"),
2951
+ sha256: z8.string().length(64),
2952
+ timestamp: z8.string().datetime(),
2953
+ cmd: z8.string().min(1),
2954
+ exitCode: z8.number().int(),
2955
+ description: z8.string().optional()
2956
+ });
2957
+ taskEvidenceSchema = z8.discriminatedUnion("kind", [
2925
2958
  fileEvidenceSchema,
2926
2959
  logEvidenceSchema,
2927
2960
  screenshotEvidenceSchema,
@@ -2932,12 +2965,12 @@ var init_task_evidence = __esm({
2932
2965
  });
2933
2966
 
2934
2967
  // packages/contracts/src/tasks/archive.ts
2935
- import { z as z8 } from "zod";
2968
+ import { z as z9 } from "zod";
2936
2969
  var ArchiveReason, ARCHIVE_REASON_VALUES;
2937
2970
  var init_archive = __esm({
2938
2971
  "packages/contracts/src/tasks/archive.ts"() {
2939
2972
  "use strict";
2940
- ArchiveReason = z8.enum([
2973
+ ArchiveReason = z9.enum([
2941
2974
  "verified",
2942
2975
  "reconciled",
2943
2976
  "superseded",
@@ -2969,6 +3002,7 @@ var init_src2 = __esm({
2969
3002
  init_nexus_scope_map();
2970
3003
  init_params();
2971
3004
  init_peer();
3005
+ init_evidence_atoms();
2972
3006
  init_plan();
2973
3007
  init_session2();
2974
3008
  init_session_journal();
@@ -3234,8 +3268,10 @@ function emitLafsViolation(err) {
3234
3268
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
3235
3269
  }
3236
3270
  };
3237
- process.stderr.write(`${JSON.stringify(envelope)}
3271
+ if (process.env["CLEO_DEBUG"]) {
3272
+ process.stderr.write(`${JSON.stringify(envelope)}
3238
3273
  `);
3274
+ }
3239
3275
  process.exitCode = 104 /* LAFS_VIOLATION */;
3240
3276
  }
3241
3277
  var ENVELOPE_SUCCESS_KEY, ENVELOPE_DATA_KEY, ENVELOPE_META_KEY, LafsViolationError;
@@ -5181,7 +5217,7 @@ __export(renderers_exports, {
5181
5217
  renderWaves: () => renderWaves
5182
5218
  });
5183
5219
  import { randomUUID } from "node:crypto";
5184
- import { formatSuccess } from "@cleocode/core";
5220
+ import { drainWarnings, formatSuccess } from "@cleocode/core";
5185
5221
  import { applyFieldFilter, extractFieldFromResult } from "@cleocode/lafs";
5186
5222
  function generateRequestId() {
5187
5223
  return randomUUID();
@@ -5369,6 +5405,11 @@ function cliError(message, code, details, meta) {
5369
5405
  timestamp: meta?.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
5370
5406
  ...meta
5371
5407
  };
5408
+ const drained = drainWarnings();
5409
+ if (drained && drained.length > 0) {
5410
+ const existing = errorMeta.warnings;
5411
+ errorMeta.warnings = Array.isArray(existing) ? [...existing, ...drained] : drained;
5412
+ }
5372
5413
  const envelope = {
5373
5414
  success: false,
5374
5415
  error: errorObj,
@@ -37763,6 +37804,7 @@ __export(briefing_exports, {
37763
37804
  });
37764
37805
  import { existsSync as existsSync8, readFileSync as readFileSync8 } from "node:fs";
37765
37806
  import { join as join9 } from "node:path";
37807
+ import { pushWarning } from "@cleocode/core";
37766
37808
  import { resolveLegacyCleoDir } from "@cleocode/paths";
37767
37809
  function resolveInjectionTemplatePath() {
37768
37810
  const xdgConfig = resolveLegacyCleoDir(process.env["XDG_CONFIG_HOME"]);
@@ -37794,8 +37836,19 @@ function renderForAdapter(sectionName, content, format) {
37794
37836
  async function runBriefingInject(sectionName, formatStr) {
37795
37837
  const templatePath = resolveInjectionTemplatePath();
37796
37838
  if (!existsSync8(templatePath)) {
37797
- process.stderr.write(`[briefing inject] CLEO-INJECTION.md not found at ${templatePath}
37798
- `);
37839
+ pushWarning({
37840
+ code: "W_TEMPLATE_INJECT_FAILED",
37841
+ message: `CLEO-INJECTION.md not found at ${templatePath}`
37842
+ });
37843
+ cliError(
37844
+ `CLEO-INJECTION.md not found at ${templatePath}`,
37845
+ 1,
37846
+ {
37847
+ name: "E_TEMPLATE_NOT_FOUND",
37848
+ fix: "Re-run `cleo init` or restore the templates directory."
37849
+ },
37850
+ { operation: "briefing.inject" }
37851
+ );
37799
37852
  process.exitCode = 1;
37800
37853
  return;
37801
37854
  }
@@ -37803,10 +37856,18 @@ async function runBriefingInject(sectionName, formatStr) {
37803
37856
  const section = extractSection(content, sectionName);
37804
37857
  if (section === null) {
37805
37858
  const available = INJECTION_SECTION_NAMES.join(", ");
37806
- process.stderr.write(
37807
- `[briefing inject] Section "${sectionName}" not found in CLEO-INJECTION.md.
37808
- Available sections: ${available}
37809
- `
37859
+ pushWarning({
37860
+ code: "W_TEMPLATE_INJECT_FAILED",
37861
+ message: `Section "${sectionName}" not found in CLEO-INJECTION.md.`
37862
+ });
37863
+ cliError(
37864
+ `Section "${sectionName}" not found in CLEO-INJECTION.md. Available sections: ${available}`,
37865
+ 1,
37866
+ {
37867
+ name: "E_VALIDATION",
37868
+ fix: `Pass one of: ${available}`
37869
+ },
37870
+ { operation: "briefing.inject" }
37810
37871
  );
37811
37872
  process.exitCode = 1;
37812
37873
  return;
@@ -37815,9 +37876,19 @@ Available sections: ${available}
37815
37876
  if (formatStr.startsWith("adapter:")) {
37816
37877
  const adapterName = formatStr.slice("adapter:".length);
37817
37878
  if (!ADAPTER_FORMATS.includes(adapterName)) {
37818
- process.stderr.write(
37819
- `[briefing inject] Unknown adapter format "${adapterName}". Supported: ${ADAPTER_FORMATS.join(", ")}
37820
- `
37879
+ const supported = ADAPTER_FORMATS.join(", ");
37880
+ pushWarning({
37881
+ code: "W_TEMPLATE_INJECT_FAILED",
37882
+ message: `Unknown adapter format "${adapterName}".`
37883
+ });
37884
+ cliError(
37885
+ `Unknown adapter format "${adapterName}". Supported: ${supported}`,
37886
+ 1,
37887
+ {
37888
+ name: "E_VALIDATION",
37889
+ fix: `Pass one of: ${supported}`
37890
+ },
37891
+ { operation: "briefing.inject" }
37821
37892
  );
37822
37893
  process.exitCode = 1;
37823
37894
  return;
@@ -37833,6 +37904,7 @@ var init_briefing = __esm({
37833
37904
  init_dist();
37834
37905
  init_cli();
37835
37906
  init_subcommand_guard();
37907
+ init_renderers();
37836
37908
  INJECTION_SECTION_NAMES = [
37837
37909
  "session-start",
37838
37910
  "work-loop",
@@ -48051,6 +48123,7 @@ var init_llm_stream = __esm({
48051
48123
  "packages/cleo/src/cli/commands/llm-stream.ts"() {
48052
48124
  "use strict";
48053
48125
  init_dist();
48126
+ init_renderers();
48054
48127
  streamCommand = defineCommand({
48055
48128
  meta: {
48056
48129
  name: "stream",
@@ -48094,11 +48167,21 @@ var init_llm_stream = __esm({
48094
48167
  const provider = String(a["provider"] ?? "").trim();
48095
48168
  const prompt = String(a["prompt"] ?? "").trim();
48096
48169
  if (!provider) {
48097
- process.stderr.write("[error] cleo llm stream: <provider> is required.\n");
48170
+ cliError(
48171
+ "cleo llm stream: <provider> is required.",
48172
+ 2,
48173
+ { name: "E_VALIDATION", fix: "Pass a provider as the first positional argument." },
48174
+ { operation: "llm.stream" }
48175
+ );
48098
48176
  process.exit(2);
48099
48177
  }
48100
48178
  if (!prompt) {
48101
- process.stderr.write("[error] cleo llm stream: <prompt> is required.\n");
48179
+ cliError(
48180
+ "cleo llm stream: <prompt> is required.",
48181
+ 2,
48182
+ { name: "E_VALIDATION", fix: "Pass a prompt as the second positional argument." },
48183
+ { operation: "llm.stream" }
48184
+ );
48102
48185
  process.exit(2);
48103
48186
  }
48104
48187
  const model = typeof a["model"] === "string" && a["model"] ? a["model"] : void 0;
@@ -48114,8 +48197,12 @@ var init_llm_stream = __esm({
48114
48197
  await runLlmStream({ provider, prompt, model, maxTokens, temperature, showThink, system });
48115
48198
  } catch (err) {
48116
48199
  const msg = err instanceof Error ? err.message : String(err);
48117
- process.stderr.write(`[error] cleo llm stream: ${msg}
48118
- `);
48200
+ cliError(
48201
+ `cleo llm stream: ${msg}`,
48202
+ 1,
48203
+ { name: "E_LLM_STREAM_FAILED" },
48204
+ { operation: "llm.stream" }
48205
+ );
48119
48206
  process.exit(1);
48120
48207
  }
48121
48208
  }
@@ -48525,6 +48612,7 @@ var llm_exports = {};
48525
48612
  __export(llm_exports, {
48526
48613
  llmCommand: () => llmCommand
48527
48614
  });
48615
+ import { pushWarning as pushWarning2 } from "@cleocode/core";
48528
48616
  async function getListProviders() {
48529
48617
  const { listProviders } = await import(
48530
48618
  /* webpackIgnore: true */
@@ -48629,8 +48717,11 @@ var init_llm3 = __esm({
48629
48717
  apiKey = await readApiKeyFromStdin();
48630
48718
  source = "stdin";
48631
48719
  if (!apiKey) {
48632
- process.stderr.write(
48633
- '[error] --api-key-stdin set but stdin is empty or a TTY. Pipe the secret in, e.g. `echo "$KEY" | cleo llm add ...`.\n'
48720
+ cliError(
48721
+ '--api-key-stdin set but stdin is empty or a TTY. Pipe the secret in, e.g. `echo "$KEY" | cleo llm add ...`.',
48722
+ 2,
48723
+ { name: "E_VALIDATION", fix: "Pipe the secret to stdin or use --api-key-env=NAME." },
48724
+ { operation: "llm.add" }
48634
48725
  );
48635
48726
  process.exit(2);
48636
48727
  }
@@ -48638,20 +48729,37 @@ var init_llm3 = __esm({
48638
48729
  const envName = a["api-key-env"];
48639
48730
  const envValue = process.env[envName];
48640
48731
  if (!envValue) {
48641
- process.stderr.write(`[error] --api-key-env=${envName} is not set in the environment.
48642
- `);
48732
+ cliError(
48733
+ `--api-key-env=${envName} is not set in the environment.`,
48734
+ 2,
48735
+ {
48736
+ name: "E_VALIDATION",
48737
+ fix: `Export ${envName} before running, or use --api-key-stdin.`
48738
+ },
48739
+ { operation: "llm.add" }
48740
+ );
48643
48741
  process.exit(2);
48644
48742
  }
48645
48743
  apiKey = envValue;
48646
48744
  source = "env";
48647
48745
  } else if (typeof a["api-key"] === "string" && a["api-key"]) {
48648
- process.stderr.write(`${API_KEY_FLAG_DEPRECATION}
48649
- `);
48746
+ pushWarning2({
48747
+ code: "W_DEPRECATED_FLAG",
48748
+ message: API_KEY_FLAG_DEPRECATION,
48749
+ deprecated: "--api-key=<value>",
48750
+ replacement: "--api-key-stdin or --api-key-env=NAME"
48751
+ });
48650
48752
  apiKey = a["api-key"];
48651
48753
  source = "flag";
48652
48754
  } else {
48653
- process.stderr.write(
48654
- "[error] cleo llm add requires one of --api-key-stdin (recommended), --api-key-env=NAME, or --api-key=<value> (deprecated).\n"
48755
+ cliError(
48756
+ "cleo llm add requires one of --api-key-stdin (recommended), --api-key-env=NAME, or --api-key=<value> (deprecated).",
48757
+ 2,
48758
+ {
48759
+ name: "E_VALIDATION",
48760
+ fix: "Provide the credential via --api-key-stdin, --api-key-env=NAME, or --api-key=<value>."
48761
+ },
48762
+ { operation: "llm.add" }
48655
48763
  );
48656
48764
  process.exit(2);
48657
48765
  }
@@ -48913,8 +49021,12 @@ var init_llm3 = __esm({
48913
49021
  `Logged in to ${result.data.provider} as '${result.data.label}'` + (result.data.expiresIn != null ? ` (expires in ${Math.round(result.data.expiresIn / 60)} min)` : "") + "\n"
48914
49022
  );
48915
49023
  } else if (result.error) {
48916
- process.stderr.write(`[error] ${result.error.message}
48917
- `);
49024
+ cliError(
49025
+ result.error.message,
49026
+ result.error.code || 1,
49027
+ { name: result.error.codeName },
49028
+ { operation: "llm.login" }
49029
+ );
48918
49030
  process.exit(1);
48919
49031
  }
48920
49032
  }
@@ -48943,8 +49055,12 @@ var init_llm3 = __esm({
48943
49055
  `
48944
49056
  );
48945
49057
  } else if (!result.success) {
48946
- process.stderr.write(`[error] ${result.error?.message ?? "refresh failed"}
48947
- `);
49058
+ cliError(
49059
+ result.error?.message ?? "refresh failed",
49060
+ result.error?.code ?? 1,
49061
+ { name: "E_REFRESH_FAILED" },
49062
+ { operation: "llm.refreshCatalog" }
49063
+ );
48948
49064
  process.exit(1);
48949
49065
  }
48950
49066
  }
@@ -56399,7 +56515,7 @@ __export(release_exports, {
56399
56515
  SHIP_DEPRECATION_NOTICE: () => SHIP_DEPRECATION_NOTICE,
56400
56516
  releaseCommand: () => releaseCommand
56401
56517
  });
56402
- import { release as release2 } from "@cleocode/core";
56518
+ import { pushWarning as pushWarning3, release as release2 } from "@cleocode/core";
56403
56519
  var SHIP_DEPRECATION_NOTICE, shipCommand, listCommand18, showCommand10, cancelCommand2, changelogCommand, rollbackCommand, rollbackFullCommand, prStatusCommand, channelCommand, planCommand3, openCommand2, reconcileCommand4, releaseCommand;
56404
56520
  var init_release3 = __esm({
56405
56521
  "packages/cleo/src/cli/commands/release.ts"() {
@@ -56430,8 +56546,12 @@ var init_release3 = __esm({
56430
56546
  }
56431
56547
  },
56432
56548
  async run({ args }) {
56433
- process.stderr.write(`${SHIP_DEPRECATION_NOTICE}
56434
- `);
56549
+ pushWarning3({
56550
+ code: "W_DEPRECATED_COMMAND",
56551
+ message: SHIP_DEPRECATION_NOTICE,
56552
+ deprecated: "cleo release ship",
56553
+ replacement: "cleo release plan <version> --epic <id> && cleo release open <version>"
56554
+ });
56435
56555
  await dispatchFromCli(
56436
56556
  "mutate",
56437
56557
  "release",
@@ -66444,6 +66564,32 @@ function resolveFormat(opts, defaults) {
66444
66564
  return resolveOutputFormat(input2);
66445
66565
  }
66446
66566
 
66567
+ // packages/cleo/src/cli/resolve-subcommand.ts
66568
+ async function resolveLazyValue(input2) {
66569
+ if (typeof input2 === "function") {
66570
+ return resolveLazyValue(input2());
66571
+ }
66572
+ return Promise.resolve(input2);
66573
+ }
66574
+ async function resolveSubCommandForHelp(cmd, rawArgs) {
66575
+ let current = cmd;
66576
+ let parent;
66577
+ let remaining = [...rawArgs];
66578
+ while (true) {
66579
+ const subCommands2 = await resolveLazyValue(current.subCommands);
66580
+ if (!subCommands2 || Object.keys(subCommands2).length === 0) return [current, parent];
66581
+ const subIndex = remaining.findIndex((arg) => !arg.startsWith("-"));
66582
+ if (subIndex < 0) return [current, parent];
66583
+ const subName = remaining[subIndex];
66584
+ if (subName === void 0 || !(subName in subCommands2)) return [current, parent];
66585
+ const next = await resolveLazyValue(subCommands2[subName]);
66586
+ if (!next) return [current, parent];
66587
+ parent = current;
66588
+ current = next;
66589
+ remaining = remaining.slice(subIndex + 1);
66590
+ }
66591
+ }
66592
+
66447
66593
  // packages/cleo/src/cli/index.ts
66448
66594
  {
66449
66595
  const [major] = process.versions.node.split(".").map(Number);
@@ -66577,7 +66723,8 @@ async function runMainWithLafsEnvelope(cmd, rawArgs, showUsage2) {
66577
66723
  const helpFlags = ["--help", "-h"];
66578
66724
  const versionFlags = ["--version", "-V"];
66579
66725
  if (rawArgs.some((a) => helpFlags.includes(a))) {
66580
- await showUsage2(cmd);
66726
+ const [leafCmd, parentCmd] = await resolveSubCommandForHelp(cmd, rawArgs);
66727
+ await showUsage2(leafCmd, parentCmd);
66581
66728
  process.exit(0);
66582
66729
  }
66583
66730
  if (rawArgs.length === 1 && versionFlags.includes(rawArgs[0])) {
@@ -66592,22 +66739,26 @@ async function runMainWithLafsEnvelope(cmd, rawArgs, showUsage2) {
66592
66739
  `);
66593
66740
  process.exit(0);
66594
66741
  }
66595
- try {
66596
- await runCommand(cmd, { rawArgs });
66597
- } catch (err) {
66598
- const { cliError: cliError2 } = await Promise.resolve().then(() => (init_renderers(), renderers_exports));
66599
- const cittyCliError = asCittyCliError(err);
66600
- if (cittyCliError) {
66601
- cliError2(cittyCliError.message, 1, {
66602
- name: cittyCliError.code === "EARG" ? "E_VALIDATION" : `E_${cittyCliError.code}`,
66603
- fix: `Run 'cleo <command> --help' to see required arguments.`
66604
- });
66742
+ const { WarningCollector, withWarningCollector } = await import("@cleocode/lafs");
66743
+ const collector = new WarningCollector();
66744
+ await withWarningCollector(collector, async () => {
66745
+ try {
66746
+ await runCommand(cmd, { rawArgs });
66747
+ } catch (err) {
66748
+ const { cliError: cliError2 } = await Promise.resolve().then(() => (init_renderers(), renderers_exports));
66749
+ const cittyCliError = asCittyCliError(err);
66750
+ if (cittyCliError) {
66751
+ cliError2(cittyCliError.message, 1, {
66752
+ name: cittyCliError.code === "EARG" ? "E_VALIDATION" : `E_${cittyCliError.code}`,
66753
+ fix: `Run 'cleo <command> --help' to see required arguments.`
66754
+ });
66755
+ process.exit(1);
66756
+ }
66757
+ const message = err instanceof Error ? err.message : String(err);
66758
+ cliError2(message, 1, { name: "E_CLI_UNCAUGHT" });
66605
66759
  process.exit(1);
66606
66760
  }
66607
- const message = err instanceof Error ? err.message : String(err);
66608
- cliError2(message, 1, { name: "E_CLI_UNCAUGHT" });
66609
- process.exit(1);
66610
- }
66761
+ });
66611
66762
  }
66612
66763
  async function runStartupMaintenance() {
66613
66764
  const {