@cleocode/cleo 2026.5.79 → 2026.5.81

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
@@ -12312,6 +12312,92 @@ var init_registry = __esm({
12312
12312
  // 4-verb pipeline registered below: `release.plan`, `release.open`,
12313
12313
  // `release.reconcile`, plus `cleo verify <task> --gate X --evidence …`
12314
12314
  // for per-task gate verification (R-422 / ADR-051).
12315
+ // release mutate: plan (T9525 / SPEC-T9345 §4.2 — Phase 1 plan verb)
12316
+ {
12317
+ gateway: "mutate",
12318
+ domain: "release",
12319
+ operation: "plan",
12320
+ description: "release.plan (mutate) \u2014 build canonical Release Plan envelope, write .cleo/release/<version>.plan.json, INSERT/UPDATE releases row status=planned (T9525 / SPEC-T9345 \xA74.2).",
12321
+ tier: 1,
12322
+ idempotent: true,
12323
+ sessionRequired: false,
12324
+ requiredParams: ["version", "epicId"],
12325
+ params: [
12326
+ {
12327
+ name: "version",
12328
+ type: "string",
12329
+ required: true,
12330
+ description: "Candidate version (e.g. v2026.5.80)"
12331
+ },
12332
+ {
12333
+ name: "epicId",
12334
+ type: "string",
12335
+ required: true,
12336
+ description: "Epic task ID whose children scope the release (R-303)"
12337
+ },
12338
+ {
12339
+ name: "scheme",
12340
+ type: "string",
12341
+ required: false,
12342
+ description: "Versioning scheme: calver | semver | calver-suffix"
12343
+ },
12344
+ {
12345
+ name: "channel",
12346
+ type: "string",
12347
+ required: false,
12348
+ description: "Release channel: latest | beta | alpha | rc"
12349
+ },
12350
+ {
12351
+ name: "hotfix",
12352
+ type: "boolean",
12353
+ required: false,
12354
+ description: "Mark plan as release_kind=hotfix"
12355
+ },
12356
+ {
12357
+ name: "dryRun",
12358
+ type: "boolean",
12359
+ required: false,
12360
+ description: "Compute the plan without writing file or DB row"
12361
+ }
12362
+ ]
12363
+ },
12364
+ // release mutate: open (T9530 / SPEC-T9345 §4.3 — Phase 3 open verb)
12365
+ {
12366
+ gateway: "mutate",
12367
+ domain: "release",
12368
+ operation: "open",
12369
+ description: "release.open (mutate) \u2014 dispatch release-prepare.yml via gh workflow run, UPDATE releases.status to pr-opened (T9530 / SPEC-T9345 \xA74.3).",
12370
+ tier: 1,
12371
+ idempotent: true,
12372
+ sessionRequired: false,
12373
+ requiredParams: ["version"],
12374
+ params: [
12375
+ {
12376
+ name: "version",
12377
+ type: "string",
12378
+ required: true,
12379
+ description: "Release version whose plan file lives at .cleo/release/<version>.plan.json"
12380
+ },
12381
+ {
12382
+ name: "workflow",
12383
+ type: "string",
12384
+ required: false,
12385
+ description: "Workflow file name (default: release-prepare.yml)"
12386
+ },
12387
+ {
12388
+ name: "watch",
12389
+ type: "boolean",
12390
+ required: false,
12391
+ description: "Poll gh run watch until terminal state"
12392
+ },
12393
+ {
12394
+ name: "commitPlan",
12395
+ type: "boolean",
12396
+ required: false,
12397
+ description: "Commit plan file before dispatching"
12398
+ }
12399
+ ]
12400
+ },
12315
12401
  // release mutate: reconcile (T9526 / SPEC-T9345 §4.4 — v2 reconcile verb)
12316
12402
  {
12317
12403
  gateway: "mutate",
@@ -12699,6 +12785,75 @@ var init_registry = __esm({
12699
12785
  description: "Include the freshly rendered YAML in the response (for diff display)"
12700
12786
  }
12701
12787
  ]
12788
+ },
12789
+ // ---------------------------------------------------------------------------
12790
+ // Worktree domain — `cleo worktree list/prune/force-unlock` (T9546/T9547)
12791
+ // ---------------------------------------------------------------------------
12792
+ {
12793
+ gateway: "query",
12794
+ domain: "worktree",
12795
+ operation: "list",
12796
+ description: "worktree.list (query) \u2014 enumerate git worktrees with 5 status categories (active|stale|merged|orphan|locked). Reads tasks.db for owning-task status. 60s git timeout (T9546).",
12797
+ tier: 1,
12798
+ idempotent: true,
12799
+ sessionRequired: false,
12800
+ requiredParams: [],
12801
+ params: [
12802
+ {
12803
+ name: "statusFilter",
12804
+ type: "string",
12805
+ required: false,
12806
+ description: "Filter to one or more status categories (comma-separated)"
12807
+ },
12808
+ {
12809
+ name: "staleDays",
12810
+ type: "number",
12811
+ required: false,
12812
+ description: "Days of inactivity before flagging stale (default 7)"
12813
+ }
12814
+ ]
12815
+ },
12816
+ {
12817
+ gateway: "mutate",
12818
+ domain: "worktree",
12819
+ operation: "prune",
12820
+ description: "worktree.prune (mutate) \u2014 remove orphaned worktrees with per-orphan confirmation. Audit-logs to .cleo/audit/worktree-lifecycle.jsonl (T9547).",
12821
+ tier: 1,
12822
+ idempotent: true,
12823
+ sessionRequired: false,
12824
+ requiredParams: [],
12825
+ params: [
12826
+ {
12827
+ name: "paths",
12828
+ type: "array",
12829
+ required: false,
12830
+ description: "Pre-confirmed paths to remove"
12831
+ },
12832
+ {
12833
+ name: "dryRun",
12834
+ type: "boolean",
12835
+ required: false,
12836
+ description: "Enumerate orphans without acting"
12837
+ }
12838
+ ]
12839
+ },
12840
+ {
12841
+ gateway: "mutate",
12842
+ domain: "worktree",
12843
+ operation: "forceUnlock",
12844
+ description: "worktree.forceUnlock (mutate) \u2014 remove .git/index.lock and run git worktree unlock for a task. Warns on uncommitted changes (T9547).",
12845
+ tier: 1,
12846
+ idempotent: true,
12847
+ sessionRequired: false,
12848
+ requiredParams: ["taskId"],
12849
+ params: [
12850
+ {
12851
+ name: "taskId",
12852
+ type: "string",
12853
+ required: true,
12854
+ description: "Task ID whose worktree (branch task/T<id>) to unlock"
12855
+ }
12856
+ ]
12702
12857
  }
12703
12858
  ];
12704
12859
  counts = getCounts();
@@ -25507,16 +25662,16 @@ async function orchestrateRejectOp(params) {
25507
25662
  async function orchestrateClassify(request, context, projectRoot) {
25508
25663
  try {
25509
25664
  const { getCleoCantWorkflowsDir } = await import("@cleocode/core/internal");
25510
- const { readFileSync: readFileSync18, readdirSync: readdirSync4, existsSync: existsSync16 } = await import("node:fs");
25511
- const { join: join28 } = await import("node:path");
25665
+ const { readFileSync: readFileSync18, readdirSync: readdirSync4, existsSync: existsSync17 } = await import("node:fs");
25666
+ const { join: join29 } = await import("node:path");
25512
25667
  const workflowsDir = getCleoCantWorkflowsDir();
25513
25668
  const combined = `${request} ${context ?? ""}`.toLowerCase();
25514
25669
  const matches = [];
25515
- if (existsSync16(workflowsDir)) {
25670
+ if (existsSync17(workflowsDir)) {
25516
25671
  const files = readdirSync4(workflowsDir).filter((f) => f.endsWith(".cant"));
25517
25672
  for (const file of files) {
25518
25673
  try {
25519
- const src = readFileSync18(join28(workflowsDir, file), "utf-8");
25674
+ const src = readFileSync18(join29(workflowsDir, file), "utf-8");
25520
25675
  const teamMatch = /^team\s+(\S+):/m.exec(src);
25521
25676
  if (!teamMatch) continue;
25522
25677
  const teamName = teamMatch[1];
@@ -25531,12 +25686,12 @@ async function orchestrateClassify(request, context, projectRoot) {
25531
25686
  }
25532
25687
  }
25533
25688
  }
25534
- const localCantDir = join28(projectRoot, CLEO_DIR_NAME, WORKFLOWS_SUBDIR);
25535
- if (existsSync16(localCantDir)) {
25689
+ const localCantDir = join29(projectRoot, CLEO_DIR_NAME, WORKFLOWS_SUBDIR);
25690
+ if (existsSync17(localCantDir)) {
25536
25691
  const files = readdirSync4(localCantDir).filter((f) => f.endsWith(".cant"));
25537
25692
  for (const file of files) {
25538
25693
  try {
25539
- const src = readFileSync18(join28(localCantDir, file), "utf-8");
25694
+ const src = readFileSync18(join29(localCantDir, file), "utf-8");
25540
25695
  const teamMatch = /^team\s+(\S+):/m.exec(src);
25541
25696
  if (!teamMatch) continue;
25542
25697
  const teamName = teamMatch[1];
@@ -32238,7 +32393,7 @@ import {
32238
32393
  detectStaleAgents,
32239
32394
  getHealthReport,
32240
32395
  STALE_THRESHOLD_MS
32241
- } from "@cleocode/core/internal";
32396
+ } from "@cleocode/core/agents";
32242
32397
  function inferTierFromRole(role) {
32243
32398
  if (role === "orchestrator") return "high";
32244
32399
  return "mid";
@@ -32621,7 +32776,8 @@ var init_agent = __esm({
32621
32776
  },
32622
32777
  async run({ args }) {
32623
32778
  try {
32624
- const { AgentRegistryAccessor, getDb: getDb3 } = await import("@cleocode/core/internal");
32779
+ const { AgentRegistryAccessor } = await import("@cleocode/core/agents");
32780
+ const { getDb: getDb3 } = await import("@cleocode/core/internal");
32625
32781
  await getDb3();
32626
32782
  const registry = new AgentRegistryAccessor(process.cwd());
32627
32783
  const agentId = args.id;
@@ -32640,12 +32796,12 @@ var init_agent = __esm({
32640
32796
  transportConfig: {},
32641
32797
  isActive: true
32642
32798
  });
32643
- const { existsSync: existsSync16, mkdirSync: mkdirSync7, writeFileSync: writeFileSync7 } = await import("node:fs");
32644
- const { join: join28 } = await import("node:path");
32645
- const cantDir = join28(CLEO_DIR_NAME, AGENTS_SUBDIR);
32646
- const cantPath = join28(cantDir, `${agentId}.cant`);
32799
+ const { existsSync: existsSync17, mkdirSync: mkdirSync7, writeFileSync: writeFileSync7 } = await import("node:fs");
32800
+ const { join: join29 } = await import("node:path");
32801
+ const cantDir = join29(CLEO_DIR_NAME, AGENTS_SUBDIR);
32802
+ const cantPath = join29(cantDir, `${agentId}.cant`);
32647
32803
  let cantScaffolded = false;
32648
- if (!existsSync16(cantPath)) {
32804
+ if (!existsSync17(cantPath)) {
32649
32805
  mkdirSync7(cantDir, { recursive: true });
32650
32806
  const role = classification ?? "specialist";
32651
32807
  const cantContent = `---
@@ -32705,7 +32861,7 @@ agent ${agentId}:
32705
32861
  data: {
32706
32862
  agentId: credential.agentId,
32707
32863
  displayName: credential.displayName,
32708
- cantFile: cantScaffolded ? cantPath : existsSync16(cantPath) ? cantPath : null,
32864
+ cantFile: cantScaffolded ? cantPath : existsSync17(cantPath) ? cantPath : null,
32709
32865
  cantScaffolded
32710
32866
  }
32711
32867
  },
@@ -32738,7 +32894,8 @@ agent ${agentId}:
32738
32894
  },
32739
32895
  async run({ args }) {
32740
32896
  try {
32741
- const { AgentRegistryAccessor, getDb: getDb3 } = await import("@cleocode/core/internal");
32897
+ const { AgentRegistryAccessor } = await import("@cleocode/core/agents");
32898
+ const { getDb: getDb3 } = await import("@cleocode/core/internal");
32742
32899
  await getDb3();
32743
32900
  const registry = new AgentRegistryAccessor(process.cwd());
32744
32901
  const credential = await registry.get(args.agentId);
@@ -32822,10 +32979,11 @@ agent ${agentId}:
32822
32979
  },
32823
32980
  async run({ args }) {
32824
32981
  try {
32825
- const { AgentRegistryAccessor, getDb: getDb3 } = await import("@cleocode/core/internal");
32982
+ const { AgentRegistryAccessor } = await import("@cleocode/core/agents");
32983
+ const { getDb: getDb3 } = await import("@cleocode/core/internal");
32826
32984
  const { createRuntime } = await import("@cleocode/runtime");
32827
- const { existsSync: existsSync16, readFileSync: readFileSync18 } = await import("node:fs");
32828
- const { join: join28 } = await import("node:path");
32985
+ const { existsSync: existsSync17, readFileSync: readFileSync18 } = await import("node:fs");
32986
+ const { join: join29 } = await import("node:path");
32829
32987
  await getDb3();
32830
32988
  const registry = new AgentRegistryAccessor(process.cwd());
32831
32989
  const credential = await registry.get(args.agentId);
@@ -32845,8 +33003,8 @@ agent ${agentId}:
32845
33003
  }
32846
33004
  let profile = null;
32847
33005
  let cantValidation = null;
32848
- const cantPath = args.cant ?? join28(CLEO_DIR_NAME, AGENTS_SUBDIR, `${args.agentId}.cant`);
32849
- if (existsSync16(cantPath)) {
33006
+ const cantPath = args.cant ?? join29(CLEO_DIR_NAME, AGENTS_SUBDIR, `${args.agentId}.cant`);
33007
+ if (existsSync17(cantPath)) {
32850
33008
  profile = readFileSync18(cantPath, "utf-8");
32851
33009
  try {
32852
33010
  const cantModule = await import("@cleocode/cant");
@@ -32943,7 +33101,8 @@ agent ${agentId}:
32943
33101
  },
32944
33102
  async run({ args }) {
32945
33103
  try {
32946
- const { AgentRegistryAccessor, getDb: getDb3 } = await import("@cleocode/core/internal");
33104
+ const { AgentRegistryAccessor } = await import("@cleocode/core/agents");
33105
+ const { getDb: getDb3 } = await import("@cleocode/core/internal");
32947
33106
  await getDb3();
32948
33107
  const registry = new AgentRegistryAccessor(process.cwd());
32949
33108
  const credential = await registry.get(args.agentId);
@@ -32999,7 +33158,8 @@ agent ${agentId}:
32999
33158
  },
33000
33159
  async run({ args }) {
33001
33160
  try {
33002
- const { AgentRegistryAccessor, getDb: getDb3 } = await import("@cleocode/core/internal");
33161
+ const { AgentRegistryAccessor } = await import("@cleocode/core/agents");
33162
+ const { getDb: getDb3 } = await import("@cleocode/core/internal");
33003
33163
  await getDb3();
33004
33164
  const registry = new AgentRegistryAccessor(process.cwd());
33005
33165
  if (args.agentId) {
@@ -33074,7 +33234,8 @@ agent ${agentId}:
33074
33234
  },
33075
33235
  async run({ args }) {
33076
33236
  try {
33077
- const { AgentRegistryAccessor, getDb: getDb3, createConduit } = await import("@cleocode/core/internal");
33237
+ const { AgentRegistryAccessor, createConduit } = await import("@cleocode/core/agents");
33238
+ const { getDb: getDb3 } = await import("@cleocode/core/internal");
33078
33239
  await getDb3();
33079
33240
  const registry = new AgentRegistryAccessor(process.cwd());
33080
33241
  const active = await registry.getActive();
@@ -33130,7 +33291,8 @@ Assigned task ${args.taskId}. Run: cleo show ${args.taskId} && cleo start ${args
33130
33291
  },
33131
33292
  async run({ args }) {
33132
33293
  try {
33133
- const { AgentRegistryAccessor, getDb: getDb3, createConduit } = await import("@cleocode/core/internal");
33294
+ const { AgentRegistryAccessor, createConduit } = await import("@cleocode/core/agents");
33295
+ const { getDb: getDb3 } = await import("@cleocode/core/internal");
33134
33296
  await getDb3();
33135
33297
  const registry = new AgentRegistryAccessor(process.cwd());
33136
33298
  const active = await registry.getActive();
@@ -33195,7 +33357,8 @@ You are idle. Check your queue: cleo current || cleo next. Report status immedia
33195
33357
  },
33196
33358
  async run({ args }) {
33197
33359
  try {
33198
- const { AgentRegistryAccessor, getDb: getDb3 } = await import("@cleocode/core/internal");
33360
+ const { AgentRegistryAccessor } = await import("@cleocode/core/agents");
33361
+ const { getDb: getDb3 } = await import("@cleocode/core/internal");
33199
33362
  await getDb3();
33200
33363
  const registry = new AgentRegistryAccessor(process.cwd());
33201
33364
  const role = args.role;
@@ -33259,7 +33422,8 @@ You are idle. Check your queue: cleo current || cleo next. Report status immedia
33259
33422
  },
33260
33423
  async run({ args }) {
33261
33424
  try {
33262
- const { AgentRegistryAccessor, getDb: getDb3, createConduit } = await import("@cleocode/core/internal");
33425
+ const { AgentRegistryAccessor, createConduit } = await import("@cleocode/core/agents");
33426
+ const { getDb: getDb3 } = await import("@cleocode/core/internal");
33263
33427
  await getDb3();
33264
33428
  const registry = new AgentRegistryAccessor(process.cwd());
33265
33429
  const active = await registry.getActive();
@@ -33302,7 +33466,8 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
33302
33466
  },
33303
33467
  async run() {
33304
33468
  try {
33305
- const { AgentRegistryAccessor, getDb: getDb3 } = await import("@cleocode/core/internal");
33469
+ const { AgentRegistryAccessor } = await import("@cleocode/core/agents");
33470
+ const { getDb: getDb3 } = await import("@cleocode/core/internal");
33306
33471
  await getDb3();
33307
33472
  const registry = new AgentRegistryAccessor(process.cwd());
33308
33473
  const agents = await registry.list({ active: true });
@@ -33368,10 +33533,11 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
33368
33533
  },
33369
33534
  async run({ args }) {
33370
33535
  try {
33371
- const { AgentRegistryAccessor, getDb: getDb3 } = await import("@cleocode/core/internal");
33536
+ const { AgentRegistryAccessor } = await import("@cleocode/core/agents");
33537
+ const { getDb: getDb3 } = await import("@cleocode/core/internal");
33372
33538
  const { createRuntime } = await import("@cleocode/runtime");
33373
- const { existsSync: existsSync16 } = await import("node:fs");
33374
- const { join: join28 } = await import("node:path");
33539
+ const { existsSync: existsSync17 } = await import("node:fs");
33540
+ const { join: join29 } = await import("node:path");
33375
33541
  const { execFile: execFile2 } = await import("node:child_process");
33376
33542
  const { promisify: promisify2 } = await import("node:util");
33377
33543
  const execFileAsync = promisify2(execFile2);
@@ -33391,8 +33557,8 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
33391
33557
  }
33392
33558
  await registry.update(args.agentId, { isActive: true });
33393
33559
  await registry.markUsed(args.agentId);
33394
- const cantPath = join28(CLEO_DIR_NAME, AGENTS_SUBDIR, `${args.agentId}.cant`);
33395
- const hasProfile = existsSync16(cantPath);
33560
+ const cantPath = join29(CLEO_DIR_NAME, AGENTS_SUBDIR, `${args.agentId}.cant`);
33561
+ const hasProfile = existsSync17(cantPath);
33396
33562
  const runtime = await createRuntime(registry, {
33397
33563
  agentId: args.agentId,
33398
33564
  pollIntervalMs: 5e3,
@@ -33528,7 +33694,8 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
33528
33694
  },
33529
33695
  async run({ args }) {
33530
33696
  try {
33531
- const { listAgentsForProject, getDb: getDb3 } = await import("@cleocode/core/internal");
33697
+ const { listAgentsForProject } = await import("@cleocode/core/agents");
33698
+ const { getDb: getDb3 } = await import("@cleocode/core/internal");
33532
33699
  await getDb3();
33533
33700
  const includeGlobal = args.global === true;
33534
33701
  const includeDisabled = args["include-disabled"] === true;
@@ -33579,7 +33746,8 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
33579
33746
  },
33580
33747
  async run({ args }) {
33581
33748
  try {
33582
- const { lookupAgent, getDb: getDb3 } = await import("@cleocode/core/internal");
33749
+ const { lookupAgent } = await import("@cleocode/core/agents");
33750
+ const { getDb: getDb3 } = await import("@cleocode/core/internal");
33583
33751
  await getDb3();
33584
33752
  const includeGlobal = args.global === true;
33585
33753
  const agent = lookupAgent(process.cwd(), args.agentId, { includeGlobal });
@@ -33645,7 +33813,8 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
33645
33813
  },
33646
33814
  async run({ args }) {
33647
33815
  try {
33648
- const { AgentRegistryAccessor, attachAgentToProject, lookupAgent, getDb: getDb3 } = await import("@cleocode/core/internal");
33816
+ const { AgentRegistryAccessor, attachAgentToProject, lookupAgent } = await import("@cleocode/core/agents");
33817
+ const { getDb: getDb3 } = await import("@cleocode/core/internal");
33649
33818
  await getDb3();
33650
33819
  const projectRoot = process.cwd();
33651
33820
  const _registry = new AgentRegistryAccessor(projectRoot);
@@ -33700,7 +33869,8 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
33700
33869
  },
33701
33870
  async run({ args }) {
33702
33871
  try {
33703
- const { AgentRegistryAccessor, detachAgentFromProject, getProjectAgentRef, getDb: getDb3 } = await import("@cleocode/core/internal");
33872
+ const { AgentRegistryAccessor, detachAgentFromProject, getProjectAgentRef } = await import("@cleocode/core/agents");
33873
+ const { getDb: getDb3 } = await import("@cleocode/core/internal");
33704
33874
  await getDb3();
33705
33875
  const projectRoot = process.cwd();
33706
33876
  const _registry = new AgentRegistryAccessor(projectRoot);
@@ -33756,7 +33926,8 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
33756
33926
  },
33757
33927
  async run({ args }) {
33758
33928
  try {
33759
- const { AgentRegistryAccessor, detachAgentFromProject, getProjectAgentRef, getDb: getDb3 } = await import("@cleocode/core/internal");
33929
+ const { AgentRegistryAccessor, detachAgentFromProject, getProjectAgentRef } = await import("@cleocode/core/agents");
33930
+ const { getDb: getDb3 } = await import("@cleocode/core/internal");
33760
33931
  await getDb3();
33761
33932
  const projectRoot = process.cwd();
33762
33933
  if (!args.global) {
@@ -33837,7 +34008,8 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
33837
34008
  },
33838
34009
  async run({ args }) {
33839
34010
  try {
33840
- const { AgentRegistryAccessor, getDb: getDb3 } = await import("@cleocode/core/internal");
34011
+ const { AgentRegistryAccessor } = await import("@cleocode/core/agents");
34012
+ const { getDb: getDb3 } = await import("@cleocode/core/internal");
33841
34013
  await getDb3();
33842
34014
  const registry = new AgentRegistryAccessor(process.cwd());
33843
34015
  const result = await registry.rotateKey(args.agentId);
@@ -33875,7 +34047,8 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
33875
34047
  },
33876
34048
  async run({ args }) {
33877
34049
  try {
33878
- const { AgentRegistryAccessor, getDb: getDb3 } = await import("@cleocode/core/internal");
34050
+ const { AgentRegistryAccessor } = await import("@cleocode/core/agents");
34051
+ const { getDb: getDb3 } = await import("@cleocode/core/internal");
33879
34052
  await getDb3();
33880
34053
  const registry = new AgentRegistryAccessor(process.cwd());
33881
34054
  const credential = await registry.get(args.agentId);
@@ -33948,7 +34121,8 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
33948
34121
  },
33949
34122
  async run({ args }) {
33950
34123
  try {
33951
- const { AgentRegistryAccessor, getDb: getDb3 } = await import("@cleocode/core/internal");
34124
+ const { AgentRegistryAccessor } = await import("@cleocode/core/agents");
34125
+ const { getDb: getDb3 } = await import("@cleocode/core/internal");
33952
34126
  const { createRuntime } = await import("@cleocode/runtime");
33953
34127
  await getDb3();
33954
34128
  const registry = new AgentRegistryAccessor(process.cwd());
@@ -34031,7 +34205,8 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
34031
34205
  },
34032
34206
  async run({ args }) {
34033
34207
  try {
34034
- const { AgentRegistryAccessor, createConduit, getDb: getDb3 } = await import("@cleocode/core/internal");
34208
+ const { AgentRegistryAccessor, createConduit } = await import("@cleocode/core/agents");
34209
+ const { getDb: getDb3 } = await import("@cleocode/core/internal");
34035
34210
  await getDb3();
34036
34211
  const registry = new AgentRegistryAccessor(process.cwd());
34037
34212
  const agentId = args.agent;
@@ -34082,7 +34257,8 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
34082
34257
  },
34083
34258
  async run({ args }) {
34084
34259
  try {
34085
- const { AgentRegistryAccessor, createConduit, getDb: getDb3 } = await import("@cleocode/core/internal");
34260
+ const { AgentRegistryAccessor, createConduit } = await import("@cleocode/core/agents");
34261
+ const { getDb: getDb3 } = await import("@cleocode/core/internal");
34086
34262
  await getDb3();
34087
34263
  const registry = new AgentRegistryAccessor(process.cwd());
34088
34264
  const agentId = args.agent;
@@ -34240,11 +34416,11 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
34240
34416
  async run({ args }) {
34241
34417
  let tempDir = null;
34242
34418
  try {
34243
- const { existsSync: existsSync16, mkdirSync: mkdirSync7, statSync, readdirSync: readdirSync4, copyFileSync } = await import("node:fs");
34244
- const { join: join28, basename, resolve: resolve8, extname } = await import("node:path");
34419
+ const { existsSync: existsSync17, mkdirSync: mkdirSync7, statSync, readdirSync: readdirSync4, copyFileSync } = await import("node:fs");
34420
+ const { join: join29, basename, resolve: resolve8, extname } = await import("node:path");
34245
34421
  const { tmpdir: tmpdir2 } = await import("node:os");
34246
34422
  const resolvedPath = resolve8(args.path);
34247
- if (!existsSync16(resolvedPath)) {
34423
+ if (!existsSync17(resolvedPath)) {
34248
34424
  cliOutput(
34249
34425
  {
34250
34426
  success: false,
@@ -34265,7 +34441,7 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
34265
34441
  cantPath = resolvedPath;
34266
34442
  } else if (stat2.isFile() && ext === ".cantz") {
34267
34443
  const { execFileSync: execFileSync5 } = await import("node:child_process");
34268
- tempDir = join28(tmpdir2(), `cleo-agent-install-${Date.now()}`);
34444
+ tempDir = join29(tmpdir2(), `cleo-agent-install-${Date.now()}`);
34269
34445
  mkdirSync7(tempDir, { recursive: true });
34270
34446
  try {
34271
34447
  execFileSync5("unzip", ["-o", "-q", resolvedPath, "-d", tempDir], {
@@ -34287,7 +34463,7 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
34287
34463
  return;
34288
34464
  }
34289
34465
  const topLevel = readdirSync4(tempDir).filter(
34290
- (entry) => statSync(join28(tempDir, entry)).isDirectory()
34466
+ (entry) => statSync(join29(tempDir, entry)).isDirectory()
34291
34467
  );
34292
34468
  if (topLevel.length !== 1) {
34293
34469
  cliOutput(
@@ -34304,8 +34480,8 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
34304
34480
  return;
34305
34481
  }
34306
34482
  const agentName = topLevel[0];
34307
- const personaPath = join28(tempDir, agentName, "persona.cant");
34308
- if (!existsSync16(personaPath)) {
34483
+ const personaPath = join29(tempDir, agentName, "persona.cant");
34484
+ if (!existsSync17(personaPath)) {
34309
34485
  cliOutput(
34310
34486
  {
34311
34487
  success: false,
@@ -34319,12 +34495,12 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
34319
34495
  process.exitCode = 6;
34320
34496
  return;
34321
34497
  }
34322
- cantPath = join28(tempDir, `${agentName}.cant`);
34498
+ cantPath = join29(tempDir, `${agentName}.cant`);
34323
34499
  copyFileSync(personaPath, cantPath);
34324
34500
  } else if (stat2.isDirectory()) {
34325
34501
  const agentName = basename(resolvedPath);
34326
- const personaPath = join28(resolvedPath, "persona.cant");
34327
- if (!existsSync16(personaPath)) {
34502
+ const personaPath = join29(resolvedPath, "persona.cant");
34503
+ if (!existsSync17(personaPath)) {
34328
34504
  cliOutput(
34329
34505
  {
34330
34506
  success: false,
@@ -34338,9 +34514,9 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
34338
34514
  process.exitCode = 6;
34339
34515
  return;
34340
34516
  }
34341
- tempDir = join28(tmpdir2(), `cleo-agent-install-${Date.now()}`);
34517
+ tempDir = join29(tmpdir2(), `cleo-agent-install-${Date.now()}`);
34342
34518
  mkdirSync7(tempDir, { recursive: true });
34343
- cantPath = join28(tempDir, `${agentName}.cant`);
34519
+ cantPath = join29(tempDir, `${agentName}.cant`);
34344
34520
  copyFileSync(personaPath, cantPath);
34345
34521
  } else {
34346
34522
  cliOutput(
@@ -34356,7 +34532,7 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
34356
34532
  process.exitCode = 6;
34357
34533
  return;
34358
34534
  }
34359
- const { installAgentFromCant: installAgentFromCant2, attachAgentToProject } = await import("@cleocode/core/internal");
34535
+ const { installAgentFromCant: installAgentFromCant2, attachAgentToProject } = await import("@cleocode/core/agents");
34360
34536
  const { openCleoDb: openCleoDb2 } = await import("@cleocode/core/store/open-cleo-db");
34361
34537
  const { db: _sdDb } = await openCleoDb2("signaldock");
34362
34538
  const db = _sdDb;
@@ -34459,11 +34635,11 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
34459
34635
  },
34460
34636
  async run({ args }) {
34461
34637
  try {
34462
- const { existsSync: existsSync16, statSync } = await import("node:fs");
34638
+ const { existsSync: existsSync17, statSync } = await import("node:fs");
34463
34639
  const { resolve: resolve8, basename, dirname: dirname11 } = await import("node:path");
34464
34640
  const { execFileSync: execFileSync5 } = await import("node:child_process");
34465
34641
  const resolvedDir = resolve8(args.dir);
34466
- if (!existsSync16(resolvedDir) || !statSync(resolvedDir).isDirectory()) {
34642
+ if (!existsSync17(resolvedDir) || !statSync(resolvedDir).isDirectory()) {
34467
34643
  cliOutput(
34468
34644
  {
34469
34645
  success: false,
@@ -34477,9 +34653,9 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
34477
34653
  process.exitCode = 4;
34478
34654
  return;
34479
34655
  }
34480
- const { join: join28 } = await import("node:path");
34481
- const personaPath = join28(resolvedDir, "persona.cant");
34482
- if (!existsSync16(personaPath)) {
34656
+ const { join: join29 } = await import("node:path");
34657
+ const personaPath = join29(resolvedDir, "persona.cant");
34658
+ if (!existsSync17(personaPath)) {
34483
34659
  cliOutput(
34484
34660
  {
34485
34661
  success: false,
@@ -34526,7 +34702,7 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
34526
34702
  if (entry.isFile()) {
34527
34703
  fileCount++;
34528
34704
  } else if (entry.isDirectory()) {
34529
- countFiles(join28(dirPath, entry.name));
34705
+ countFiles(join29(dirPath, entry.name));
34530
34706
  }
34531
34707
  }
34532
34708
  };
@@ -34595,9 +34771,9 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
34595
34771
  },
34596
34772
  async run({ args }) {
34597
34773
  try {
34598
- const { existsSync: existsSync16, mkdirSync: mkdirSync7, writeFileSync: writeFileSync7 } = await import("node:fs");
34599
- const { join: join28 } = await import("node:path");
34600
- const { homedir: homedir9 } = await import("node:os");
34774
+ const { existsSync: existsSync17, mkdirSync: mkdirSync7, writeFileSync: writeFileSync7 } = await import("node:fs");
34775
+ const { join: join29 } = await import("node:path");
34776
+ const { homedir: homedir10 } = await import("node:os");
34601
34777
  const name = args.name;
34602
34778
  const role = args.role;
34603
34779
  const tier = args.tier ?? inferTierFromRole(role);
@@ -34655,14 +34831,14 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
34655
34831
  }
34656
34832
  let targetRoot;
34657
34833
  if (isGlobal) {
34658
- const home = homedir9();
34659
- const xdgData = process.env["XDG_DATA_HOME"] ?? join28(home, ".local", "share");
34660
- targetRoot = join28(xdgData, "cleo", "cant", "agents");
34834
+ const home = homedir10();
34835
+ const xdgData = process.env["XDG_DATA_HOME"] ?? join29(home, ".local", "share");
34836
+ targetRoot = join29(xdgData, "cleo", "cant", "agents");
34661
34837
  } else {
34662
- targetRoot = join28(process.cwd(), CLEO_DIR_NAME, CANT_AGENTS_SUBDIR);
34838
+ targetRoot = join29(process.cwd(), CLEO_DIR_NAME, CANT_AGENTS_SUBDIR);
34663
34839
  }
34664
- const agentDir = join28(targetRoot, name);
34665
- if (existsSync16(agentDir)) {
34840
+ const agentDir = join29(targetRoot, name);
34841
+ if (existsSync17(agentDir)) {
34666
34842
  cliOutput(
34667
34843
  {
34668
34844
  success: false,
@@ -34686,29 +34862,29 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
34686
34862
  domain,
34687
34863
  parent
34688
34864
  });
34689
- writeFileSync7(join28(agentDir, "persona.cant"), personaContent, "utf-8");
34865
+ writeFileSync7(join29(agentDir, "persona.cant"), personaContent, "utf-8");
34690
34866
  const manifest = generateManifest({ name, role, tier, domain });
34691
34867
  writeFileSync7(
34692
- join28(agentDir, "manifest.json"),
34868
+ join29(agentDir, "manifest.json"),
34693
34869
  `${JSON.stringify(manifest, null, 2)}
34694
34870
  `,
34695
34871
  "utf-8"
34696
34872
  );
34697
34873
  const createdFiles = [
34698
- join28(agentDir, "persona.cant"),
34699
- join28(agentDir, "manifest.json")
34874
+ join29(agentDir, "persona.cant"),
34875
+ join29(agentDir, "manifest.json")
34700
34876
  ];
34701
34877
  if (team) {
34702
34878
  const teamConfigContent = generateTeamConfig(name, role, team);
34703
- writeFileSync7(join28(agentDir, "team-config.cant"), teamConfigContent, "utf-8");
34704
- createdFiles.push(join28(agentDir, "team-config.cant"));
34879
+ writeFileSync7(join29(agentDir, "team-config.cant"), teamConfigContent, "utf-8");
34880
+ createdFiles.push(join29(agentDir, "team-config.cant"));
34705
34881
  }
34706
34882
  if (seedBrain) {
34707
- const expertiseDir = join28(agentDir, "expertise");
34883
+ const expertiseDir = join29(agentDir, "expertise");
34708
34884
  mkdirSync7(expertiseDir, { recursive: true });
34709
34885
  const seedContent = generateMentalModelSeed(name, role, domain);
34710
- writeFileSync7(join28(expertiseDir, "mental-model-seed.md"), seedContent, "utf-8");
34711
- createdFiles.push(join28(expertiseDir, "mental-model-seed.md"));
34886
+ writeFileSync7(join29(expertiseDir, "mental-model-seed.md"), seedContent, "utf-8");
34887
+ createdFiles.push(join29(expertiseDir, "mental-model-seed.md"));
34712
34888
  try {
34713
34889
  const { execFile: execFile2 } = await import("node:child_process");
34714
34890
  const { promisify: promisify2 } = await import("node:util");
@@ -34729,7 +34905,8 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
34729
34905
  }
34730
34906
  let registered = false;
34731
34907
  try {
34732
- const { AgentRegistryAccessor, getDb: getDb3 } = await import("@cleocode/core/internal");
34908
+ const { AgentRegistryAccessor } = await import("@cleocode/core/agents");
34909
+ const { getDb: getDb3 } = await import("@cleocode/core/internal");
34733
34910
  await getDb3();
34734
34911
  const registry = new AgentRegistryAccessor(process.cwd());
34735
34912
  const existing = await registry.get(name);
@@ -34806,17 +34983,17 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
34806
34983
  },
34807
34984
  async run({ args }) {
34808
34985
  try {
34809
- const { existsSync: existsSync16, readFileSync: readFileSync18, mkdirSync: mkdirSync7 } = await import("node:fs");
34810
- const { resolve: resolve8, join: join28 } = await import("node:path");
34986
+ const { existsSync: existsSync17, readFileSync: readFileSync18, mkdirSync: mkdirSync7 } = await import("node:fs");
34987
+ const { resolve: resolve8, join: join29 } = await import("node:path");
34811
34988
  const specPath = resolve8(args.spec);
34812
- if (!existsSync16(specPath)) {
34989
+ if (!existsSync17(specPath)) {
34813
34990
  cliError(`spec file not found: ${specPath}`, 4, { name: "E_NOT_FOUND" });
34814
34991
  process.exitCode = 4;
34815
34992
  return;
34816
34993
  }
34817
34994
  const specContent = readFileSync18(specPath, "utf-8");
34818
34995
  const projectRoot = process.cwd();
34819
- const outputDir = args["output-dir"] ? resolve8(args["output-dir"]) : join28(projectRoot, ".cleo", "cant", "agents");
34996
+ const outputDir = args["output-dir"] ? resolve8(args["output-dir"]) : join29(projectRoot, ".cleo", "cant", "agents");
34820
34997
  mkdirSync7(outputDir, { recursive: true });
34821
34998
  if (args["dry-run"]) {
34822
34999
  cliOutput(
@@ -34875,7 +35052,7 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
34875
35052
  },
34876
35053
  async run({ args }) {
34877
35054
  try {
34878
- const { buildDoctorReport, reconcileDoctor } = await import("@cleocode/core/internal");
35055
+ const { buildDoctorReport, reconcileDoctor } = await import("@cleocode/core/agents");
34879
35056
  const { openCleoDb: openCleoDb2 } = await import("@cleocode/core/store/open-cleo-db");
34880
35057
  const { db: _sdDb2 } = await openCleoDb2("signaldock");
34881
35058
  const db = _sdDb2;
@@ -34941,7 +35118,7 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
34941
35118
  },
34942
35119
  async run({ args }) {
34943
35120
  try {
34944
- const { buildDoctorReport, reconcileDoctor } = await import("@cleocode/core/internal");
35121
+ const { buildDoctorReport, reconcileDoctor } = await import("@cleocode/core/agents");
34945
35122
  const { openCleoDb: openCleoDb2 } = await import("@cleocode/core/store/open-cleo-db");
34946
35123
  const { db: _sdDb3 } = await openCleoDb2("signaldock");
34947
35124
  const db = _sdDb3;
@@ -35286,7 +35463,140 @@ var init_audit2 = __esm({
35286
35463
  }
35287
35464
  });
35288
35465
 
35466
+ // packages/cleo/src/cli/commands/auth/consent.ts
35467
+ var authConsentCommand;
35468
+ var init_consent = __esm({
35469
+ "packages/cleo/src/cli/commands/auth/consent.ts"() {
35470
+ "use strict";
35471
+ init_dist();
35472
+ init_renderers();
35473
+ authConsentCommand = defineCommand({
35474
+ meta: {
35475
+ name: "consent",
35476
+ description: "Manage consent gates for external credential sources (e.g. Claude Code OAuth). Use --enable-claude-code / --disable-claude-code to toggle, --status to inspect."
35477
+ },
35478
+ args: {
35479
+ "enable-claude-code": {
35480
+ type: "boolean",
35481
+ description: "Grant consent for the claude-code seeder: sets auth.claudeCodeConsentGiven=true in the global config and removes any suppression entry."
35482
+ },
35483
+ "disable-claude-code": {
35484
+ type: "boolean",
35485
+ description: "Revoke consent for the claude-code seeder: sets auth.claudeCodeConsentGiven=false, adds a suppression entry, and purges all source:claude-code entries from the pool."
35486
+ },
35487
+ status: {
35488
+ type: "boolean",
35489
+ description: "Print the current state of all consent gates."
35490
+ },
35491
+ json: {
35492
+ type: "boolean",
35493
+ description: "Output as JSON envelope"
35494
+ }
35495
+ },
35496
+ async run({ args }) {
35497
+ const a = args;
35498
+ const enableClaudeCode = a["enable-claude-code"] === true;
35499
+ const disableClaudeCode = a["disable-claude-code"] === true;
35500
+ const showStatus = a["status"] === true;
35501
+ if (!enableClaudeCode && !disableClaudeCode && !showStatus) {
35502
+ cliError("Specify one of --enable-claude-code, --disable-claude-code, or --status.", 6, {
35503
+ name: "E_INVALID_INPUT",
35504
+ fix: "Run `cleo auth consent --status` to see current consent state."
35505
+ });
35506
+ process.exit(6);
35507
+ }
35508
+ if (enableClaudeCode && disableClaudeCode) {
35509
+ cliError("--enable-claude-code and --disable-claude-code are mutually exclusive.", 6, {
35510
+ name: "E_INVALID_INPUT"
35511
+ });
35512
+ process.exit(6);
35513
+ }
35514
+ const configMod = await import(
35515
+ /* webpackIgnore: true */
35516
+ "@cleocode/core/config.js"
35517
+ );
35518
+ const getConfigValue = configMod.getConfigValue;
35519
+ const setConfigValue = configMod.setConfigValue;
35520
+ const { addSuppression, removeSuppression, isSuppressed } = await import(
35521
+ /* webpackIgnore: true */
35522
+ "@cleocode/core/llm/credential-removal.js"
35523
+ );
35524
+ const CONSENT_KEY = "auth.claudeCodeConsentGiven";
35525
+ const SOURCE_ID = "claude-code";
35526
+ const PROVIDER = "anthropic";
35527
+ if (showStatus) {
35528
+ const resolved = await getConfigValue(CONSENT_KEY);
35529
+ const consentEnabled = resolved.value === true;
35530
+ const suppressed = isSuppressed(PROVIDER, SOURCE_ID);
35531
+ const result2 = {
35532
+ gates: [
35533
+ {
35534
+ gate: "claudeCode",
35535
+ configKey: CONSENT_KEY,
35536
+ enabled: consentEnabled,
35537
+ suppressed
35538
+ }
35539
+ ]
35540
+ };
35541
+ cliOutput(result2, {
35542
+ command: "auth-consent-status",
35543
+ operation: "auth.consent.status"
35544
+ });
35545
+ return;
35546
+ }
35547
+ if (enableClaudeCode) {
35548
+ await setConfigValue(CONSENT_KEY, true, void 0, { global: true });
35549
+ const suppressionChanged2 = removeSuppression(PROVIDER, SOURCE_ID);
35550
+ const result2 = {
35551
+ action: "enabled",
35552
+ gate: "claudeCode",
35553
+ configKey: CONSENT_KEY,
35554
+ value: true,
35555
+ suppressionChanged: suppressionChanged2,
35556
+ purgedCount: 0
35557
+ };
35558
+ cliOutput(result2, {
35559
+ command: "auth-consent-enable",
35560
+ operation: "auth.consent.enable"
35561
+ });
35562
+ return;
35563
+ }
35564
+ await setConfigValue(CONSENT_KEY, false, void 0, { global: true });
35565
+ const wasAlreadySuppressed = isSuppressed(PROVIDER, SOURCE_ID);
35566
+ addSuppression(PROVIDER, SOURCE_ID);
35567
+ const suppressionChanged = !wasAlreadySuppressed;
35568
+ const { listCredentials, removeCredential } = await import(
35569
+ /* webpackIgnore: true */
35570
+ "@cleocode/core/llm/credentials-store.js"
35571
+ );
35572
+ const allEntries = await listCredentials();
35573
+ const claudeCodeEntries = allEntries.filter((c) => c.source === SOURCE_ID);
35574
+ let purgedCount = 0;
35575
+ for (const entry of claudeCodeEntries) {
35576
+ const removed = await removeCredential(entry.provider, entry.label);
35577
+ if (removed) purgedCount++;
35578
+ }
35579
+ const result = {
35580
+ action: "disabled",
35581
+ gate: "claudeCode",
35582
+ configKey: CONSENT_KEY,
35583
+ value: false,
35584
+ suppressionChanged,
35585
+ purgedCount
35586
+ };
35587
+ cliOutput(result, {
35588
+ command: "auth-consent-disable",
35589
+ operation: "auth.consent.disable"
35590
+ });
35591
+ }
35592
+ });
35593
+ }
35594
+ });
35595
+
35289
35596
  // packages/cleo/src/cli/commands/auth/list.ts
35597
+ import { existsSync as existsSync6 } from "node:fs";
35598
+ import { homedir as homedir2 } from "node:os";
35599
+ import { join as join7 } from "node:path";
35290
35600
  function formatExpiry(expiresAt) {
35291
35601
  if (expiresAt == null) return "never";
35292
35602
  const remaining = expiresAt - Date.now();
@@ -35328,7 +35638,26 @@ var init_list = __esm({
35328
35638
  );
35329
35639
  const pool = getCredentialPool();
35330
35640
  await pool.seed();
35331
- const stored = await pool.list();
35641
+ const allStored = await pool.list();
35642
+ const ghCliEntries = allStored.filter((c) => c.source === "gh-cli");
35643
+ if (ghCliEntries.length > 0) {
35644
+ const { removeCredential } = await import(
35645
+ /* webpackIgnore: true */
35646
+ "@cleocode/core/llm/credentials-store.js"
35647
+ );
35648
+ const { addSuppression } = await import(
35649
+ /* webpackIgnore: true */
35650
+ "@cleocode/core/llm/credential-removal.js"
35651
+ );
35652
+ for (const entry of ghCliEntries) {
35653
+ await removeCredential(
35654
+ entry.provider,
35655
+ entry.label
35656
+ );
35657
+ }
35658
+ addSuppression("openai", "gh-cli");
35659
+ }
35660
+ const stored = allStored.filter((c) => c.source !== "gh-cli");
35332
35661
  const entries = stored.filter((c) => providerFilter ? c.provider === providerFilter : true).map((c) => ({
35333
35662
  provider: c.provider,
35334
35663
  label: c.label,
@@ -35344,8 +35673,10 @@ var init_list = __esm({
35344
35673
  const p = a2.provider.localeCompare(b.provider);
35345
35674
  return p !== 0 ? p : a2.label.localeCompare(b.label);
35346
35675
  });
35676
+ const claudeCredsPath = join7(homedir2(), ".claude", ".credentials.json");
35677
+ const hint = existsSync6(claudeCredsPath) && entries.every((e) => e.source !== "claude-code") ? "Hint: Claude Code OAuth detected at ~/.claude/.credentials.json but consent is off. Run `cleo auth consent --enable-claude-code` to seed it into the pool." : null;
35347
35678
  cliOutput(
35348
- { entries },
35679
+ { entries, ...hint !== null ? { hint } : {} },
35349
35680
  {
35350
35681
  command: "auth-list",
35351
35682
  operation: "auth.list"
@@ -35357,8 +35688,8 @@ var init_list = __esm({
35357
35688
  });
35358
35689
 
35359
35690
  // packages/cleo/src/cli/commands/auth/migrate-project-secrets.ts
35360
- import { existsSync as existsSync6, readFileSync as readFileSync7, writeFileSync as writeFileSync2 } from "node:fs";
35361
- import { join as join7 } from "node:path";
35691
+ import { existsSync as existsSync7, readFileSync as readFileSync7, writeFileSync as writeFileSync2 } from "node:fs";
35692
+ import { join as join8 } from "node:path";
35362
35693
  import { createInterface } from "node:readline";
35363
35694
  function resolveProjectRootArg(arg) {
35364
35695
  if (typeof arg === "string" && arg.length > 0) return arg;
@@ -35366,7 +35697,7 @@ function resolveProjectRootArg(arg) {
35366
35697
  }
35367
35698
  function projectConfigPath(projectRoot) {
35368
35699
  const cleoDir = process.env["CLEO_DIR"] ?? ".cleo";
35369
- return join7(projectRoot, cleoDir, "config.json");
35700
+ return join8(projectRoot, cleoDir, "config.json");
35370
35701
  }
35371
35702
  function extractApiKeyEntries(config) {
35372
35703
  if (!config || typeof config !== "object") return [];
@@ -35424,7 +35755,7 @@ async function promptYesNo(question) {
35424
35755
  }
35425
35756
  async function runMigrateProjectSecrets(opts) {
35426
35757
  const configPath = projectConfigPath(opts.projectRoot);
35427
- if (!existsSync6(configPath)) {
35758
+ if (!existsSync7(configPath)) {
35428
35759
  return {
35429
35760
  configPath,
35430
35761
  backupPath: null,
@@ -35685,6 +36016,7 @@ var init_remove = __esm({
35685
36016
  var init_auth = __esm({
35686
36017
  "packages/cleo/src/cli/commands/auth/index.ts"() {
35687
36018
  "use strict";
36019
+ init_consent();
35688
36020
  init_list();
35689
36021
  init_migrate_project_secrets();
35690
36022
  init_remove();
@@ -35708,6 +36040,7 @@ var init_auth2 = __esm({
35708
36040
  description: "Unified credential view across all seeded sources (cleo llm list is the LLM-scoped sister command)."
35709
36041
  },
35710
36042
  subCommands: {
36043
+ consent: authConsentCommand,
35711
36044
  list: authListCommand,
35712
36045
  remove: authRemoveCommand,
35713
36046
  "migrate-project-secrets": authMigrateProjectSecretsCommand
@@ -36277,7 +36610,8 @@ var init_backup = __esm({
36277
36610
  },
36278
36611
  async run({ args }) {
36279
36612
  const scope = args.scope;
36280
- const { packBundle, getProjectRoot: getProjectRoot38 } = await import("@cleocode/core/internal");
36613
+ const { packBundle } = await import("@cleocode/core/store/backup-pack.js");
36614
+ const { getProjectRoot: getProjectRoot38 } = await import("@cleocode/core");
36281
36615
  const includesProject = scope === "project" || scope === "all";
36282
36616
  const projectRoot = includesProject ? getProjectRoot38() : void 0;
36283
36617
  let passphrase;
@@ -36355,10 +36689,14 @@ var init_backup = __esm({
36355
36689
  },
36356
36690
  async run({ args }) {
36357
36691
  const bundlePath = args.bundle;
36358
- const core2 = await import("@cleocode/core/internal");
36359
- const projectRoot = core2.getProjectRoot();
36692
+ const { getProjectRoot: getProjectRoot38, getCleoHome: getCleoHome3, getCleoVersion } = await import("@cleocode/core");
36693
+ const { BundleError, cleanupStaging, unpackBundle } = await import("@cleocode/core/store/backup-unpack.js");
36694
+ const { regenerateConfigJson, regenerateProjectContextJson, regenerateProjectInfoJson } = await import("@cleocode/core/store/regenerators.js");
36695
+ const { regenerateAndCompare } = await import("@cleocode/core/store/restore-json-merge.js");
36696
+ const { buildConflictReport, writeConflictReport } = await import("@cleocode/core/store/restore-conflict-report.js");
36697
+ const projectRoot = getProjectRoot38();
36360
36698
  if (args.force !== true) {
36361
- const existing = checkForExistingData(projectRoot, core2.getCleoHome());
36699
+ const existing = checkForExistingData(projectRoot, getCleoHome3());
36362
36700
  if (existing.length > 0) {
36363
36701
  process.stderr.write(
36364
36702
  JSON.stringify({
@@ -36392,9 +36730,9 @@ var init_backup = __esm({
36392
36730
  }
36393
36731
  let result;
36394
36732
  try {
36395
- result = await core2.unpackBundle({ bundlePath, passphrase });
36733
+ result = await unpackBundle({ bundlePath, passphrase });
36396
36734
  } catch (err) {
36397
- if (err instanceof core2.BundleError) {
36735
+ if (err instanceof BundleError) {
36398
36736
  process.stderr.write(
36399
36737
  JSON.stringify({
36400
36738
  success: false,
@@ -36414,7 +36752,7 @@ var init_backup = __esm({
36414
36752
  for (const dbEntry of manifest.databases) {
36415
36753
  const src = path2.join(stagingDir, dbEntry.filename);
36416
36754
  if (!fs2.existsSync(src)) continue;
36417
- const dst = resolveDbTarget(projectRoot, dbEntry.name, core2.getCleoHome());
36755
+ const dst = resolveDbTarget(projectRoot, dbEntry.name, getCleoHome3());
36418
36756
  fs2.mkdirSync(path2.dirname(dst), { recursive: true });
36419
36757
  const tmpDst = `${dst}.import-tmp-${Date.now()}`;
36420
36758
  fs2.copyFileSync(src, tmpDst);
@@ -36436,13 +36774,13 @@ var init_backup = __esm({
36436
36774
  const basename = path2.basename(jsonEntry.filename);
36437
36775
  let localGenerated;
36438
36776
  if (basename === CONFIG_JSON) {
36439
- localGenerated = core2.regenerateConfigJson(projectRoot).content;
36777
+ localGenerated = regenerateConfigJson(projectRoot).content;
36440
36778
  } else if (basename === PROJECT_INFO_JSON) {
36441
- localGenerated = core2.regenerateProjectInfoJson(projectRoot).content;
36779
+ localGenerated = regenerateProjectInfoJson(projectRoot).content;
36442
36780
  } else {
36443
- localGenerated = core2.regenerateProjectContextJson(projectRoot).content;
36781
+ localGenerated = regenerateProjectContextJson(projectRoot).content;
36444
36782
  }
36445
- const report = core2.regenerateAndCompare({
36783
+ const report = regenerateAndCompare({
36446
36784
  filename: basename,
36447
36785
  imported,
36448
36786
  localGenerated
@@ -36452,12 +36790,12 @@ var init_backup = __esm({
36452
36790
  fs2.mkdirSync(path2.dirname(targetPath), { recursive: true });
36453
36791
  fs2.writeFileSync(targetPath, JSON.stringify(report.applied, null, 2), "utf-8");
36454
36792
  }
36455
- const cleoVersion = core2.getCleoVersion();
36456
- const conflictMd = core2.buildConflictReport({
36793
+ const cleoVersion = getCleoVersion();
36794
+ const conflictMd = buildConflictReport({
36457
36795
  reports: jsonReports,
36458
36796
  bundlePath,
36459
36797
  sourceMachineFingerprint: manifest.backup.machineFingerprint,
36460
- targetMachineFingerprint: sha256OfMachineKey(core2.getCleoHome()),
36798
+ targetMachineFingerprint: sha256OfMachineKey(getCleoHome3()),
36461
36799
  cleoVersion,
36462
36800
  schemaWarnings: warnings.map((w) => ({
36463
36801
  db: w.db,
@@ -36466,7 +36804,7 @@ var init_backup = __esm({
36466
36804
  severity: w.severity
36467
36805
  }))
36468
36806
  });
36469
- core2.writeConflictReport(projectRoot, conflictMd);
36807
+ writeConflictReport(projectRoot, conflictMd);
36470
36808
  const importedDir = path2.join(projectRoot, CLEO_DIR_NAME, RESTORE_IMPORTED_SUBDIR);
36471
36809
  fs2.mkdirSync(importedDir, { recursive: true });
36472
36810
  for (const jsonEntry of manifest.json) {
@@ -36508,7 +36846,7 @@ var init_backup = __esm({
36508
36846
  );
36509
36847
  process.exitCode = 79;
36510
36848
  } finally {
36511
- core2.cleanupStaging(stagingDir);
36849
+ cleanupStaging(stagingDir);
36512
36850
  }
36513
36851
  }
36514
36852
  });
@@ -36574,16 +36912,16 @@ var brain_exports = {};
36574
36912
  __export(brain_exports, {
36575
36913
  brainCommand: () => brainCommand
36576
36914
  });
36915
+ import { getProjectRoot as getProjectRoot24 } from "@cleocode/core";
36577
36916
  import {
36578
36917
  backfillBrainGraph,
36579
36918
  exportBrainAsGexf,
36580
36919
  exportBrainAsJson,
36581
36920
  getMemoryQualityReport,
36582
36921
  getPlasticityStats,
36583
- getProjectRoot as getProjectRoot24,
36584
36922
  purgeBrainNoise,
36585
36923
  runBrainMaintenance
36586
- } from "@cleocode/core/internal";
36924
+ } from "@cleocode/core/memory";
36587
36925
  var maintenanceCommand, backfillBrainCommand, purgeCommand, plasticityStatsCommand, plasticityCommand, qualityCommand, exportCommand2, brainCommand;
36588
36926
  var init_brain2 = __esm({
36589
36927
  "packages/cleo/src/cli/commands/brain.ts"() {
@@ -36956,12 +37294,12 @@ var briefing_exports = {};
36956
37294
  __export(briefing_exports, {
36957
37295
  briefingCommand: () => briefingCommand
36958
37296
  });
36959
- import { existsSync as existsSync7, readFileSync as readFileSync8 } from "node:fs";
36960
- import { homedir as homedir2 } from "node:os";
36961
- import { join as join8 } from "node:path";
37297
+ import { existsSync as existsSync8, readFileSync as readFileSync8 } from "node:fs";
37298
+ import { homedir as homedir3 } from "node:os";
37299
+ import { join as join9 } from "node:path";
36962
37300
  function resolveInjectionTemplatePath() {
36963
- const xdgConfig = process.env["XDG_CONFIG_HOME"] ?? join8(homedir2(), ".cleo");
36964
- return join8(xdgConfig, "templates", "CLEO-INJECTION.md");
37301
+ const xdgConfig = process.env["XDG_CONFIG_HOME"] ?? join9(homedir3(), ".cleo");
37302
+ return join9(xdgConfig, "templates", "CLEO-INJECTION.md");
36965
37303
  }
36966
37304
  function extractSection(content, sectionName) {
36967
37305
  const openTag = `<!-- CLEO-INJECTION:section=${sectionName} -->`;
@@ -36988,7 +37326,7 @@ function renderForAdapter(sectionName, content, format) {
36988
37326
  }
36989
37327
  async function runBriefingInject(sectionName, formatStr) {
36990
37328
  const templatePath = resolveInjectionTemplatePath();
36991
- if (!existsSync7(templatePath)) {
37329
+ if (!existsSync8(templatePath)) {
36992
37330
  process.stderr.write(`[briefing inject] CLEO-INJECTION.md not found at ${templatePath}
36993
37331
  `);
36994
37332
  process.exitCode = 1;
@@ -37136,8 +37474,8 @@ var caamp_exports = {};
37136
37474
  __export(caamp_exports, {
37137
37475
  caampCommand: () => caampCommand
37138
37476
  });
37139
- import { homedir as homedir3 } from "node:os";
37140
- import { join as join9 } from "node:path";
37477
+ import { homedir as homedir4 } from "node:os";
37478
+ import { join as join10 } from "node:path";
37141
37479
  var dedupeCommand, caampCommand;
37142
37480
  var init_caamp = __esm({
37143
37481
  "packages/cleo/src/cli/commands/caamp.ts"() {
@@ -37172,20 +37510,20 @@ var init_caamp = __esm({
37172
37510
  if (args.file) {
37173
37511
  filePaths = [args.file];
37174
37512
  } else {
37175
- const home = homedir3();
37513
+ const home = homedir4();
37176
37514
  filePaths = [
37177
- join9(home, ".agents", "AGENTS.md"),
37515
+ join10(home, ".agents", "AGENTS.md"),
37178
37516
  // project-level AGENTS.md in cwd
37179
- join9(process.cwd(), "AGENTS.md")
37517
+ join10(process.cwd(), "AGENTS.md")
37180
37518
  ];
37181
37519
  }
37182
37520
  if (args["dry-run"]) {
37183
37521
  const { parseCaampBlocks } = await import("@cleocode/caamp");
37184
- const { existsSync: existsSync16 } = await import("node:fs");
37522
+ const { existsSync: existsSync17 } = await import("node:fs");
37185
37523
  const { readFile: readFile6 } = await import("node:fs/promises");
37186
37524
  const dryResults = [];
37187
37525
  for (const filePath of filePaths) {
37188
- if (!existsSync16(filePath)) {
37526
+ if (!existsSync17(filePath)) {
37189
37527
  dryResults.push({ filePath, exists: false, blockCount: 0, wouldRemove: 0 });
37190
37528
  continue;
37191
37529
  }
@@ -37283,13 +37621,13 @@ var cant_exports = {};
37283
37621
  __export(cant_exports, {
37284
37622
  cantCommand: () => cantCommand
37285
37623
  });
37286
- import { existsSync as existsSync8, mkdirSync as mkdirSync2, readFileSync as readFileSync9, writeFileSync as writeFileSync3 } from "node:fs";
37287
- import { dirname as dirname5, isAbsolute, join as join10, resolve as resolve4 } from "node:path";
37624
+ import { existsSync as existsSync9, mkdirSync as mkdirSync2, readFileSync as readFileSync9, writeFileSync as writeFileSync3 } from "node:fs";
37625
+ import { dirname as dirname5, isAbsolute, join as join11, resolve as resolve4 } from "node:path";
37288
37626
  function resolveFilePath(file) {
37289
37627
  return isAbsolute(file) ? file : resolve4(process.cwd(), file);
37290
37628
  }
37291
37629
  function ensureExists(filePath, operation) {
37292
- if (existsSync8(filePath)) return true;
37630
+ if (existsSync9(filePath)) return true;
37293
37631
  cliError(`File not found: ${filePath}`, "E_FILE_READ");
37294
37632
  process.exitCode = 3;
37295
37633
  if (process.env["CLEO_DEBUG"]) humanWarn(`(operation: ${operation})`);
@@ -37449,7 +37787,7 @@ var init_cant = __esm({
37449
37787
  const projectRoot = process.cwd();
37450
37788
  let written = 0;
37451
37789
  for (const outputFile of result.outputFiles) {
37452
- const outputPath = isAbsolute(outputFile.path) ? outputFile.path : join10(projectRoot, outputFile.path);
37790
+ const outputPath = isAbsolute(outputFile.path) ? outputFile.path : join11(projectRoot, outputFile.path);
37453
37791
  mkdirSync2(dirname5(outputPath), { recursive: true });
37454
37792
  writeFileSync3(outputPath, outputFile.content, "utf-8");
37455
37793
  written++;
@@ -38207,9 +38545,9 @@ var init_code = __esm({
38207
38545
  async run({ args }) {
38208
38546
  await requireTreeSitter();
38209
38547
  const { smartOutline } = await import("@cleocode/core/internal");
38210
- const { join: join28 } = await import("node:path");
38548
+ const { join: join29 } = await import("node:path");
38211
38549
  const root = process.cwd();
38212
- const absPath = args.file.startsWith("/") ? args.file : join28(root, args.file);
38550
+ const absPath = args.file.startsWith("/") ? args.file : join29(root, args.file);
38213
38551
  const result = smartOutline(absPath, root);
38214
38552
  if (result.errors.length > 0 && result.symbols.length === 0) {
38215
38553
  cliError(result.errors.join(", "), 1, { name: "E_OUTLINE_FAILED" });
@@ -38300,9 +38638,9 @@ var init_code = __esm({
38300
38638
  async run({ args }) {
38301
38639
  await requireTreeSitter();
38302
38640
  const { smartUnfold } = await import("@cleocode/core/internal");
38303
- const { join: join28 } = await import("node:path");
38641
+ const { join: join29 } = await import("node:path");
38304
38642
  const root = process.cwd();
38305
- const absPath = args.file.startsWith("/") ? args.file : join28(root, args.file);
38643
+ const absPath = args.file.startsWith("/") ? args.file : join29(root, args.file);
38306
38644
  const result = smartUnfold(absPath, args.symbol, root);
38307
38645
  if (!result.found) {
38308
38646
  const errs = result.errors.length > 0 ? `: ${result.errors.join(", ")}` : "";
@@ -39444,9 +39782,9 @@ var daemon_exports = {};
39444
39782
  __export(daemon_exports, {
39445
39783
  daemonCommand: () => daemonCommand
39446
39784
  });
39447
- import { existsSync as existsSync9 } from "node:fs";
39448
- import { homedir as homedir4 } from "node:os";
39449
- import { join as join11 } from "node:path";
39785
+ import { existsSync as existsSync10 } from "node:fs";
39786
+ import { homedir as homedir5 } from "node:os";
39787
+ import { join as join12 } from "node:path";
39450
39788
  import { fileURLToPath as fileURLToPath4 } from "node:url";
39451
39789
  import { getGCDaemonStatus, spawnGCDaemon, stopGCDaemon } from "@cleocode/core/gc/daemon.js";
39452
39790
  import {
@@ -39511,9 +39849,9 @@ async function showDaemonStatus(cleoDir, projectRoot) {
39511
39849
  }
39512
39850
  function resolveDaemonInstallerScript() {
39513
39851
  const filePath = fileURLToPath4(import.meta.url);
39514
- const candidate1 = join11(filePath, "..", "..", "..", "scripts", "install-daemon-service.mjs");
39515
- if (existsSync9(candidate1)) return candidate1;
39516
- const candidate2 = join11(
39852
+ const candidate1 = join12(filePath, "..", "..", "..", "scripts", "install-daemon-service.mjs");
39853
+ if (existsSync10(candidate1)) return candidate1;
39854
+ const candidate2 = join12(
39517
39855
  filePath,
39518
39856
  "..",
39519
39857
  "..",
@@ -39548,7 +39886,7 @@ var init_daemon = __esm({
39548
39886
  }
39549
39887
  },
39550
39888
  async run({ args }) {
39551
- const cleoDir = args["cleo-dir"] ?? join11(homedir4(), ".cleo");
39889
+ const cleoDir = args["cleo-dir"] ?? join12(homedir5(), ".cleo");
39552
39890
  const foreground = args.foreground ?? false;
39553
39891
  if (foreground) {
39554
39892
  const projectRoot = process.cwd();
@@ -39585,13 +39923,13 @@ var init_daemon = __esm({
39585
39923
  {
39586
39924
  pid,
39587
39925
  cleoDir,
39588
- logs: join11(cleoDir, "logs", "gc.log"),
39926
+ logs: join12(cleoDir, "logs", "gc.log"),
39589
39927
  message: `GC daemon started (PID ${pid})`
39590
39928
  },
39591
39929
  {
39592
39930
  command: "daemon",
39593
39931
  operation: "daemon.start",
39594
- message: `GC daemon started (PID ${pid}) \u2014 Logs: ${join11(cleoDir, "logs", "gc.log")}`
39932
+ message: `GC daemon started (PID ${pid}) \u2014 Logs: ${join12(cleoDir, "logs", "gc.log")}`
39595
39933
  }
39596
39934
  );
39597
39935
  } catch (err) {
@@ -39621,7 +39959,7 @@ var init_daemon = __esm({
39621
39959
  }
39622
39960
  },
39623
39961
  async run({ args }) {
39624
- const cleoDir = args["cleo-dir"] ?? join11(homedir4(), ".cleo");
39962
+ const cleoDir = args["cleo-dir"] ?? join12(homedir5(), ".cleo");
39625
39963
  try {
39626
39964
  const stopResult = await stopGCDaemon(cleoDir);
39627
39965
  cliOutput(stopResult, {
@@ -39659,7 +39997,7 @@ var init_daemon = __esm({
39659
39997
  }
39660
39998
  },
39661
39999
  async run({ args }) {
39662
- const cleoDir = args["cleo-dir"] ?? join11(homedir4(), ".cleo");
40000
+ const cleoDir = args["cleo-dir"] ?? join12(homedir5(), ".cleo");
39663
40001
  await showDaemonStatus(cleoDir, process.cwd());
39664
40002
  }
39665
40003
  });
@@ -39757,7 +40095,7 @@ var init_daemon = __esm({
39757
40095
  },
39758
40096
  async run({ args, cmd, rawArgs }) {
39759
40097
  if (isSubCommandDispatch(rawArgs, cmd.subCommands)) return;
39760
- const cleoDir = args["cleo-dir"] ?? join11(homedir4(), ".cleo");
40098
+ const cleoDir = args["cleo-dir"] ?? join12(homedir5(), ".cleo");
39761
40099
  await showDaemonStatus(cleoDir, process.cwd());
39762
40100
  }
39763
40101
  });
@@ -40220,12 +40558,12 @@ var detect_drift_exports = {};
40220
40558
  __export(detect_drift_exports, {
40221
40559
  detectDriftCommand: () => detectDriftCommand
40222
40560
  });
40223
- import { existsSync as existsSync10, readdirSync, readFileSync as readFileSync11 } from "node:fs";
40224
- import { dirname as dirname6, join as join12 } from "node:path";
40561
+ import { existsSync as existsSync11, readdirSync, readFileSync as readFileSync11 } from "node:fs";
40562
+ import { dirname as dirname6, join as join13 } from "node:path";
40225
40563
  function findProjectRoot() {
40226
40564
  let currentDir = process.cwd();
40227
40565
  while (currentDir !== "/") {
40228
- if (existsSync10(join12(currentDir, "package.json"))) {
40566
+ if (existsSync11(join13(currentDir, "package.json"))) {
40229
40567
  return currentDir;
40230
40568
  }
40231
40569
  const parent = dirname6(currentDir);
@@ -40249,8 +40587,8 @@ var init_detect_drift = __esm({
40249
40587
  },
40250
40588
  async run() {
40251
40589
  const projectRoot = findProjectRoot();
40252
- const isCleoRepo = existsSync10(join12(projectRoot, "packages", "cleo", "src"));
40253
- const cleoSrcRoot = isCleoRepo ? join12(projectRoot, "packages", "cleo", "src") : join12(projectRoot, "src");
40590
+ const isCleoRepo = existsSync11(join13(projectRoot, "packages", "cleo", "src"));
40591
+ const cleoSrcRoot = isCleoRepo ? join13(projectRoot, "packages", "cleo", "src") : join13(projectRoot, "src");
40254
40592
  const safeRead = (filePath) => {
40255
40593
  try {
40256
40594
  return readFileSync11(filePath, "utf-8");
@@ -40264,8 +40602,8 @@ var init_detect_drift = __esm({
40264
40602
  checks: [],
40265
40603
  recommendations: []
40266
40604
  };
40267
- const injPath = join12(projectRoot, CLEO_DIR_NAME, TEMPLATES_SUBDIR, CLEO_INJECTION_MD);
40268
- if (existsSync10(injPath)) {
40605
+ const injPath = join13(projectRoot, CLEO_DIR_NAME, TEMPLATES_SUBDIR, CLEO_INJECTION_MD);
40606
+ if (existsSync11(injPath)) {
40269
40607
  const content = safeRead(injPath);
40270
40608
  userResult.checks.push({
40271
40609
  name: "Agent injection",
@@ -40316,10 +40654,10 @@ var init_detect_drift = __esm({
40316
40654
  }
40317
40655
  };
40318
40656
  try {
40319
- const specPath = join12(projectRoot, "docs", "specs", "CLEO-OPERATION-CONSTITUTION.md");
40320
- const registryPath = join12(cleoSrcRoot, "dispatch", "registry.ts");
40321
- const dispatchDomainsDir = join12(cleoSrcRoot, "dispatch", "domains");
40322
- if (!existsSync10(specPath)) {
40657
+ const specPath = join13(projectRoot, "docs", "specs", "CLEO-OPERATION-CONSTITUTION.md");
40658
+ const registryPath = join13(cleoSrcRoot, "dispatch", "registry.ts");
40659
+ const dispatchDomainsDir = join13(cleoSrcRoot, "dispatch", "domains");
40660
+ if (!existsSync11(specPath)) {
40323
40661
  addCheck("Gateway-to-spec sync", "fail", "CLEO-OPERATION-CONSTITUTION.md missing", [
40324
40662
  {
40325
40663
  severity: "error",
@@ -40329,7 +40667,7 @@ var init_detect_drift = __esm({
40329
40667
  recommendation: "Create docs/specs/CLEO-OPERATION-CONSTITUTION.md with canonical operation definitions"
40330
40668
  }
40331
40669
  ]);
40332
- } else if (!existsSync10(registryPath) || !existsSync10(dispatchDomainsDir)) {
40670
+ } else if (!existsSync11(registryPath) || !existsSync11(dispatchDomainsDir)) {
40333
40671
  addCheck("Gateway-to-spec sync", "fail", "Dispatch registry or domains missing", [
40334
40672
  {
40335
40673
  severity: "error",
@@ -40387,9 +40725,9 @@ var init_detect_drift = __esm({
40387
40725
  ]);
40388
40726
  }
40389
40727
  try {
40390
- const cliDir = join12(cleoSrcRoot, "cli", "commands");
40391
- const coreDir = isCleoRepo ? join12(projectRoot, "packages", "core", "src") : join12(projectRoot, "src", "core");
40392
- if (!existsSync10(cliDir)) {
40728
+ const cliDir = join13(cleoSrcRoot, "cli", "commands");
40729
+ const coreDir = isCleoRepo ? join13(projectRoot, "packages", "core", "src") : join13(projectRoot, "src", "core");
40730
+ if (!existsSync11(cliDir)) {
40393
40731
  addCheck("CLI-to-core sync", "fail", "CLI commands directory missing", [
40394
40732
  {
40395
40733
  severity: "error",
@@ -40398,7 +40736,7 @@ var init_detect_drift = __esm({
40398
40736
  recommendation: "Verify TypeScript source structure is intact"
40399
40737
  }
40400
40738
  ]);
40401
- } else if (!existsSync10(coreDir)) {
40739
+ } else if (!existsSync11(coreDir)) {
40402
40740
  addCheck("CLI-to-core sync", "fail", "Core directory missing", [
40403
40741
  {
40404
40742
  severity: "error",
@@ -40415,8 +40753,8 @@ var init_detect_drift = __esm({
40415
40753
  addCheck("CLI-to-core sync", "fail", `Error: ${getErrorMessage(e)}`);
40416
40754
  }
40417
40755
  try {
40418
- const domainsDir = join12(cleoSrcRoot, "dispatch", "domains");
40419
- if (!existsSync10(domainsDir)) {
40756
+ const domainsDir = join13(cleoSrcRoot, "dispatch", "domains");
40757
+ if (!existsSync11(domainsDir)) {
40420
40758
  addCheck("Domain handler coverage", "fail", "Dispatch domains directory missing", [
40421
40759
  {
40422
40760
  severity: "error",
@@ -40433,8 +40771,8 @@ var init_detect_drift = __esm({
40433
40771
  addCheck("Domain handler coverage", "fail", `Error: ${getErrorMessage(e)}`);
40434
40772
  }
40435
40773
  try {
40436
- const matrixPath = join12(cleoSrcRoot, "dispatch", "lib", "capability-matrix.ts");
40437
- if (!existsSync10(matrixPath)) {
40774
+ const matrixPath = join13(cleoSrcRoot, "dispatch", "lib", "capability-matrix.ts");
40775
+ if (!existsSync11(matrixPath)) {
40438
40776
  addCheck("Capability matrix", "fail", "Capability matrix missing", [
40439
40777
  {
40440
40778
  severity: "error",
@@ -40450,8 +40788,8 @@ var init_detect_drift = __esm({
40450
40788
  addCheck("Capability matrix", "fail", `Error: ${getErrorMessage(e)}`);
40451
40789
  }
40452
40790
  try {
40453
- const schemaPath = join12(projectRoot, "src", "store", "schema.ts");
40454
- if (!existsSync10(schemaPath)) {
40791
+ const schemaPath = join13(projectRoot, "src", "store", "schema.ts");
40792
+ if (!existsSync11(schemaPath)) {
40455
40793
  addCheck("Schema validation", "fail", "Schema definition missing", [
40456
40794
  {
40457
40795
  severity: "error",
@@ -40485,10 +40823,10 @@ var init_detect_drift = __esm({
40485
40823
  addCheck("Schema validation", "fail", `Error: ${getErrorMessage(e)}`);
40486
40824
  }
40487
40825
  try {
40488
- const visionPath = join12(projectRoot, "docs", "concepts", "CLEO-VISION.md");
40489
- const specPath = join12(projectRoot, "docs", "specs", "CLEO-PORTABLE-PROJECT-BRAIN-SPEC.md");
40826
+ const visionPath = join13(projectRoot, "docs", "concepts", "CLEO-VISION.md");
40827
+ const specPath = join13(projectRoot, "docs", "specs", "CLEO-PORTABLE-PROJECT-BRAIN-SPEC.md");
40490
40828
  const issues = [];
40491
- if (!existsSync10(visionPath)) {
40829
+ if (!existsSync11(visionPath)) {
40492
40830
  issues.push({
40493
40831
  severity: "error",
40494
40832
  category: "vision",
@@ -40497,7 +40835,7 @@ var init_detect_drift = __esm({
40497
40835
  recommendation: "Create docs/concepts/CLEO-VISION.md with project vision"
40498
40836
  });
40499
40837
  }
40500
- if (!existsSync10(specPath)) {
40838
+ if (!existsSync11(specPath)) {
40501
40839
  issues.push({
40502
40840
  severity: "error",
40503
40841
  category: "spec",
@@ -40541,8 +40879,8 @@ var init_detect_drift = __esm({
40541
40879
  addCheck("Canonical identity", "fail", `Error: ${getErrorMessage(e)}`);
40542
40880
  }
40543
40881
  try {
40544
- const injectionPath = join12(projectRoot, CLEO_DIR_NAME, TEMPLATES_SUBDIR, CLEO_INJECTION_MD);
40545
- if (!existsSync10(injectionPath)) {
40882
+ const injectionPath = join13(projectRoot, CLEO_DIR_NAME, TEMPLATES_SUBDIR, CLEO_INJECTION_MD);
40883
+ if (!existsSync11(injectionPath)) {
40546
40884
  addCheck("Agent injection", "fail", "Agent injection template missing", [
40547
40885
  {
40548
40886
  severity: "error",
@@ -40571,8 +40909,8 @@ var init_detect_drift = __esm({
40571
40909
  addCheck("Agent injection", "fail", `Error: ${getErrorMessage(e)}`);
40572
40910
  }
40573
40911
  try {
40574
- const exitCodesPath = join12(cleoSrcRoot, "dispatch", "lib", "exit-codes.ts");
40575
- if (!existsSync10(exitCodesPath)) {
40912
+ const exitCodesPath = join13(cleoSrcRoot, "dispatch", "lib", "exit-codes.ts");
40913
+ if (!existsSync11(exitCodesPath)) {
40576
40914
  addCheck("Exit codes", "fail", "Exit codes definition missing", [
40577
40915
  {
40578
40916
  severity: "error",
@@ -40746,7 +41084,7 @@ __export(docs_exports, {
40746
41084
  docsCommand: () => docsCommand
40747
41085
  });
40748
41086
  import { mkdir, readdir, readFile as readFile2, writeFile } from "node:fs/promises";
40749
- import { dirname as dirname7, isAbsolute as isAbsolute2, join as join13, resolve as resolve5 } from "node:path";
41087
+ import { dirname as dirname7, isAbsolute as isAbsolute2, join as join14, resolve as resolve5 } from "node:path";
40750
41088
  import {
40751
41089
  buildDocsGraph,
40752
41090
  CleoError as CleoError3,
@@ -40762,7 +41100,7 @@ import {
40762
41100
  searchDocs as searchDocs2
40763
41101
  } from "@cleocode/core/internal";
40764
41102
  async function getScriptNames(projectRoot) {
40765
- const scriptsDir = join13(projectRoot, "scripts");
41103
+ const scriptsDir = join14(projectRoot, "scripts");
40766
41104
  try {
40767
41105
  const files = await readdir(scriptsDir);
40768
41106
  return files.filter((f) => f.endsWith(".sh")).map((f) => f.replace(".sh", "")).sort();
@@ -40771,7 +41109,7 @@ async function getScriptNames(projectRoot) {
40771
41109
  }
40772
41110
  }
40773
41111
  async function getIndexedCommands(projectRoot) {
40774
- const indexPath = join13(projectRoot, "docs", "commands", "COMMANDS-INDEX.json");
41112
+ const indexPath = join14(projectRoot, "docs", "commands", "COMMANDS-INDEX.json");
40775
41113
  const index = await readJson(indexPath);
40776
41114
  if (!index) return [];
40777
41115
  return index.commands.map((c) => c.name).sort();
@@ -40804,7 +41142,7 @@ async function runGapCheck(_projectRoot, filterId) {
40804
41142
  const reviewFiles = files.filter((f) => f.endsWith(".md"));
40805
41143
  for (const file of reviewFiles) {
40806
41144
  if (filterId && !file.includes(filterId)) continue;
40807
- const filePath = join13(reviewDir, file);
41145
+ const filePath = join14(reviewDir, file);
40808
41146
  const content = await readFile2(filePath, "utf-8");
40809
41147
  const taskMatch = file.match(/^(T\d+)/);
40810
41148
  const taskId = taskMatch ? taskMatch[1] : "UNKNOWN";
@@ -41770,8 +42108,8 @@ __export(migrate_agents_v2_exports, {
41770
42108
  walkAgentsDir: () => walkAgentsDir
41771
42109
  });
41772
42110
  import { createHash as createHash2 } from "node:crypto";
41773
- import { appendFileSync as appendFileSync2, existsSync as existsSync11, mkdirSync as mkdirSync3, readdirSync as readdirSync2, readFileSync as readFileSync12 } from "node:fs";
41774
- import { join as join14 } from "node:path";
42111
+ import { appendFileSync as appendFileSync2, existsSync as existsSync12, mkdirSync as mkdirSync3, readdirSync as readdirSync2, readFileSync as readFileSync12 } from "node:fs";
42112
+ import { join as join15 } from "node:path";
41775
42113
  import { getProjectRoot as getProjectRoot26, installAgentFromCant } from "@cleocode/core/internal";
41776
42114
  import { openCleoDb } from "@cleocode/core/store/open-cleo-db";
41777
42115
  function sha256Hex(bytes) {
@@ -41791,15 +42129,15 @@ function extractAgentName(source) {
41791
42129
  return headerMatch[1] ?? null;
41792
42130
  }
41793
42131
  function appendAuditLog(projectRoot, entry) {
41794
- const auditPath = join14(projectRoot, AUDIT_LOG_RELATIVE);
41795
- const auditDir = join14(auditPath, "..");
41796
- if (!existsSync11(auditDir)) {
42132
+ const auditPath = join15(projectRoot, AUDIT_LOG_RELATIVE);
42133
+ const auditDir = join15(auditPath, "..");
42134
+ if (!existsSync12(auditDir)) {
41797
42135
  mkdirSync3(auditDir, { recursive: true });
41798
42136
  }
41799
42137
  appendFileSync2(auditPath, JSON.stringify(entry) + "\n", "utf8");
41800
42138
  }
41801
42139
  function walkAgentsDir(db, scanDir, projectRoot, summary, verbose) {
41802
- if (!existsSync11(scanDir)) return;
42140
+ if (!existsSync12(scanDir)) return;
41803
42141
  let files;
41804
42142
  try {
41805
42143
  files = readdirSync2(scanDir).filter((f) => f.endsWith(".cant"));
@@ -41810,7 +42148,7 @@ function walkAgentsDir(db, scanDir, projectRoot, summary, verbose) {
41810
42148
  return;
41811
42149
  }
41812
42150
  for (const filename of files) {
41813
- const cantPath = join14(scanDir, filename);
42151
+ const cantPath = join15(scanDir, filename);
41814
42152
  const relPath = cantPath.replace(`${projectRoot}/`, "");
41815
42153
  let sourceBytes;
41816
42154
  let sourceText;
@@ -41907,9 +42245,9 @@ async function runMigrateAgentsV2(projectRoot, verbose = true) {
41907
42245
  const { db: _sdDb } = await openCleoDb("signaldock");
41908
42246
  const db = _sdDb;
41909
42247
  try {
41910
- const canonicalDir = join14(projectRoot, ".cleo", "cant", "agents");
42248
+ const canonicalDir = join15(projectRoot, ".cleo", "cant", "agents");
41911
42249
  walkAgentsDir(db, canonicalDir, projectRoot, summary, verbose);
41912
- const legacyDir = join14(projectRoot, ".cleo", "agents");
42250
+ const legacyDir = join15(projectRoot, ".cleo", "agents");
41913
42251
  walkAgentsDir(db, legacyDir, projectRoot, summary, verbose);
41914
42252
  } finally {
41915
42253
  db.close();
@@ -41917,8 +42255,8 @@ async function runMigrateAgentsV2(projectRoot, verbose = true) {
41917
42255
  return summary;
41918
42256
  }
41919
42257
  function readMigrationConflicts(projectRoot) {
41920
- const auditPath = join14(projectRoot, AUDIT_LOG_RELATIVE);
41921
- if (!existsSync11(auditPath)) return [];
42258
+ const auditPath = join15(projectRoot, AUDIT_LOG_RELATIVE);
42259
+ if (!existsSync12(auditPath)) return [];
41922
42260
  let raw;
41923
42261
  try {
41924
42262
  raw = readFileSync12(auditPath, "utf8");
@@ -42002,10 +42340,14 @@ __export(doctor_exports, {
42002
42340
  doctorCommand: () => doctorCommand2
42003
42341
  });
42004
42342
  import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "node:fs";
42005
- import { join as join15 } from "node:path";
42006
- import { getProjectRoot as getProjectRoot27, quarantineRogueCleoDir, scanRogueCleoDirs } from "@cleocode/core/internal";
42343
+ import { join as join16 } from "node:path";
42344
+ import { getProjectRoot as getProjectRoot27 } from "@cleocode/core";
42345
+ import {
42346
+ quarantineRogueCleoDir,
42347
+ scanRogueCleoDirs
42348
+ } from "@cleocode/core/system/rogue-cleo-detector.js";
42007
42349
  async function scanTestFixturesInProd(projectRoot) {
42008
- const { getDb: getDb3, getNativeDb } = await import("@cleocode/core/internal");
42350
+ const { getDb: getDb3, getNativeDb } = await import("@cleocode/core/store/sqlite.js");
42009
42351
  await getDb3(projectRoot);
42010
42352
  const nativeDb = getNativeDb();
42011
42353
  if (!nativeDb) return [];
@@ -42037,8 +42379,8 @@ async function scanTestFixturesInProd(projectRoot) {
42037
42379
  }
42038
42380
  async function quarantineTestFixtures(projectRoot, matches) {
42039
42381
  if (matches.length === 0) return 0;
42040
- const cleoDir = join15(projectRoot, ".cleo");
42041
- const quarantineDir = join15(
42382
+ const cleoDir = join16(projectRoot, ".cleo");
42383
+ const quarantineDir = join16(
42042
42384
  cleoDir,
42043
42385
  "quarantine",
42044
42386
  `fixture-scan-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`
@@ -42046,10 +42388,10 @@ async function quarantineTestFixtures(projectRoot, matches) {
42046
42388
  mkdirSync4(quarantineDir, { recursive: true });
42047
42389
  const manifest = matches.map((m) => ({ ...m, quarantinedAt: (/* @__PURE__ */ new Date()).toISOString() }));
42048
42390
  writeFileSync4(
42049
- join15(quarantineDir, "manifest.jsonl"),
42391
+ join16(quarantineDir, "manifest.jsonl"),
42050
42392
  manifest.map((m) => JSON.stringify(m)).join("\n") + "\n"
42051
42393
  );
42052
- const { getNativeDb } = await import("@cleocode/core/internal");
42394
+ const { getNativeDb } = await import("@cleocode/core/store/sqlite.js");
42053
42395
  const nativeDb = getNativeDb();
42054
42396
  if (nativeDb) {
42055
42397
  for (const m of matches) {
@@ -42224,7 +42566,7 @@ var init_doctor = __esm({
42224
42566
  progress.start();
42225
42567
  try {
42226
42568
  if (args.brain) {
42227
- const { computeBrainHealthDashboard } = await import("@cleocode/core/internal");
42569
+ const { computeBrainHealthDashboard } = await import("@cleocode/core/memory/brain-health-dashboard.js");
42228
42570
  const projectRoot = getProjectRoot27();
42229
42571
  const dashboard = await computeBrainHealthDashboard(projectRoot);
42230
42572
  cliOutput(dashboard, { command: "doctor", operation: "doctor.brain" });
@@ -42382,8 +42724,8 @@ var init_doctor = __esm({
42382
42724
  }
42383
42725
  } else if (args["scan-stray-nexus-dbs"]) {
42384
42726
  progress.step(0, "Scanning for stray nexus.db files");
42385
- const { detectAndRemoveLegacyGlobalFiles, detectAndRemoveStrayProjectNexus } = await import("@cleocode/core/internal");
42386
- const { getCleoHome: getCleoHome3 } = await import("@cleocode/core/internal");
42727
+ const { detectAndRemoveLegacyGlobalFiles, detectAndRemoveStrayProjectNexus } = await import("@cleocode/core/store/cleanup-legacy.js");
42728
+ const { getCleoHome: getCleoHome3 } = await import("@cleocode/core");
42387
42729
  const cleoHome = getCleoHome3();
42388
42730
  const projectRoot = getProjectRoot27();
42389
42731
  const legacyResult = detectAndRemoveLegacyGlobalFiles(cleoHome);
@@ -42408,7 +42750,7 @@ var init_doctor = __esm({
42408
42750
  cliOutput(report, { command: "doctor", operation: "doctor.scan-stray-nexus-dbs" });
42409
42751
  } else if (args["audit-worktrees"]) {
42410
42752
  progress.step(0, "Auditing orphaned agent worktrees");
42411
- const { auditOrphanWorktrees } = await import("@cleocode/core/internal");
42753
+ const { auditOrphanWorktrees } = await import("@cleocode/core/gc/index.js");
42412
42754
  const checkResult = auditOrphanWorktrees();
42413
42755
  progress.complete(`Worktree audit complete \u2014 ${checkResult.status}`);
42414
42756
  cliOutput(checkResult, { command: "doctor", operation: "doctor.audit-worktrees" });
@@ -42417,7 +42759,7 @@ var init_doctor = __esm({
42417
42759
  }
42418
42760
  } else if (args["audit-temp"]) {
42419
42761
  progress.step(0, "Auditing orphaned CLEO temp directories");
42420
- const { auditOrphanTempDirs } = await import("@cleocode/core/internal");
42762
+ const { auditOrphanTempDirs } = await import("@cleocode/core/gc/index.js");
42421
42763
  const checkResult = await auditOrphanTempDirs();
42422
42764
  progress.complete(`Temp audit complete \u2014 ${checkResult.status}`);
42423
42765
  cliOutput(checkResult, { command: "doctor", operation: "doctor.audit-temp" });
@@ -42499,7 +42841,7 @@ __export(event_exports, {
42499
42841
  orchestratorCommand: () => orchestratorCommand
42500
42842
  });
42501
42843
  import { readdir as readdir2 } from "node:fs/promises";
42502
- import { join as join16 } from "node:path";
42844
+ import { join as join17 } from "node:path";
42503
42845
  import { cwd as processCwd } from "node:process";
42504
42846
  import { appendEvent } from "@cleocode/core/events/event-bus.js";
42505
42847
  function resolveProjectRoot3(arg) {
@@ -42622,7 +42964,7 @@ var init_event = __esm({
42622
42964
  const agentIdFilter = args.agent;
42623
42965
  const showAll = args.all === true;
42624
42966
  const lines = parseInt(args.lines ?? "20", 10);
42625
- const eventsDir = join16(projectRoot, ".cleo", "agent-events");
42967
+ const eventsDir = join17(projectRoot, ".cleo", "agent-events");
42626
42968
  try {
42627
42969
  let files = [];
42628
42970
  try {
@@ -42660,7 +43002,7 @@ var init_event = __esm({
42660
43002
  for (const file of filesToTail) {
42661
43003
  const agentId = file.replace(".jsonl", "");
42662
43004
  const { readFileSync: readFileSync18 } = await import("node:fs");
42663
- const content = readFileSync18(join16(eventsDir, file), "utf-8");
43005
+ const content = readFileSync18(join17(eventsDir, file), "utf-8");
42664
43006
  const eventLines = content.trim().split("\n").filter(Boolean);
42665
43007
  const tail = eventLines.slice(-lines);
42666
43008
  if (jsonMode) {
@@ -42730,7 +43072,7 @@ var init_event = __esm({
42730
43072
  const epicFilter = args.epic;
42731
43073
  const follow = args.follow === true;
42732
43074
  const lines = parseInt(args.lines ?? "50", 10);
42733
- const eventsDir = join16(projectRoot, ".cleo", "agent-events");
43075
+ const eventsDir = join17(projectRoot, ".cleo", "agent-events");
42734
43076
  let files = [];
42735
43077
  try {
42736
43078
  const entries = await readdir2(eventsDir);
@@ -42756,7 +43098,7 @@ var init_event = __esm({
42756
43098
  const agentId = file.replace(".jsonl", "");
42757
43099
  try {
42758
43100
  const { readFileSync: readFileSync18 } = await import("node:fs");
42759
- const content = readFileSync18(join16(eventsDir, file), "utf-8");
43101
+ const content = readFileSync18(join17(eventsDir, file), "utf-8");
42760
43102
  const eventLines = content.trim().split("\n").filter(Boolean);
42761
43103
  const tail = eventLines.slice(-lines);
42762
43104
  if (jsonMode) {
@@ -43130,8 +43472,8 @@ var gc_exports = {};
43130
43472
  __export(gc_exports, {
43131
43473
  gcCommand: () => gcCommand
43132
43474
  });
43133
- import { homedir as homedir5, tmpdir } from "node:os";
43134
- import { join as join17 } from "node:path";
43475
+ import { homedir as homedir6, tmpdir } from "node:os";
43476
+ import { join as join18 } from "node:path";
43135
43477
  import { pruneOrphanTempDirs, pruneOrphanWorktrees } from "@cleocode/core/gc/cleanup.js";
43136
43478
  import { runGC } from "@cleocode/core/gc/runner.js";
43137
43479
  import { readGCState } from "@cleocode/core/gc/state.js";
@@ -43170,7 +43512,7 @@ var init_gc = __esm({
43170
43512
  }
43171
43513
  },
43172
43514
  async run({ args }) {
43173
- const cleoDir = args["cleo-dir"] ?? join17(homedir5(), ".cleo");
43515
+ const cleoDir = args["cleo-dir"] ?? join18(homedir6(), ".cleo");
43174
43516
  const dryRun = args["dry-run"];
43175
43517
  try {
43176
43518
  const gcResult = await runGC({ cleoDir, dryRun });
@@ -43212,8 +43554,8 @@ var init_gc = __esm({
43212
43554
  }
43213
43555
  },
43214
43556
  async run({ args }) {
43215
- const cleoDir = args["cleo-dir"] ?? join17(homedir5(), ".cleo");
43216
- const statePath = join17(cleoDir, "gc-state.json");
43557
+ const cleoDir = args["cleo-dir"] ?? join18(homedir6(), ".cleo");
43558
+ const statePath = join18(cleoDir, "gc-state.json");
43217
43559
  try {
43218
43560
  const state = await readGCState(statePath);
43219
43561
  const diskStr = state.lastDiskUsedPct !== null ? `${state.lastDiskUsedPct.toFixed(1)}%` : "unknown";
@@ -43266,8 +43608,8 @@ var init_gc = __esm({
43266
43608
  }
43267
43609
  },
43268
43610
  async run({ args }) {
43269
- const xdgData = process.env["XDG_DATA_HOME"] ?? join17(homedir5(), ".local", "share");
43270
- const worktreesRoot = args["worktrees-root"] ?? join17(xdgData, "cleo", "worktrees");
43611
+ const xdgData = process.env["XDG_DATA_HOME"] ?? join18(homedir6(), ".local", "share");
43612
+ const worktreesRoot = args["worktrees-root"] ?? join18(xdgData, "cleo", "worktrees");
43271
43613
  const projectHash = args["project-hash"];
43272
43614
  const dryRun = args["dry-run"];
43273
43615
  const preserveRaw = args["preserve-tasks"];
@@ -43377,8 +43719,8 @@ __export(generate_changelog_exports, {
43377
43719
  generateChangelogCommand: () => generateChangelogCommand
43378
43720
  });
43379
43721
  import { execFileSync as execFileSync2 } from "node:child_process";
43380
- import { existsSync as existsSync12, mkdirSync as mkdirSync5, readFileSync as readFileSync13, writeFileSync as writeFileSync5 } from "node:fs";
43381
- import { dirname as dirname8, join as join18 } from "node:path";
43722
+ import { existsSync as existsSync13, mkdirSync as mkdirSync5, readFileSync as readFileSync13, writeFileSync as writeFileSync5 } from "node:fs";
43723
+ import { dirname as dirname8, join as join19 } from "node:path";
43382
43724
  import { CleoError as CleoError4, formatError as formatError6, getConfigPath, getProjectRoot as getProjectRoot28 } from "@cleocode/core";
43383
43725
  function getChangelogSource(cwd) {
43384
43726
  const configPath = getConfigPath(cwd);
@@ -43543,8 +43885,8 @@ var init_generate_changelog = __esm({
43543
43885
  const targetPlatform = args.platform;
43544
43886
  const dryRun = args["dry-run"] === true;
43545
43887
  const sourceFile = getChangelogSource();
43546
- const sourcePath = join18(getProjectRoot28(), sourceFile);
43547
- if (!existsSync12(sourcePath)) {
43888
+ const sourcePath = join19(getProjectRoot28(), sourceFile);
43889
+ if (!existsSync13(sourcePath)) {
43548
43890
  throw new CleoError4(4 /* NOT_FOUND */, `Changelog source not found: ${sourcePath}`);
43549
43891
  }
43550
43892
  const sourceContent = readFileSync13(sourcePath, "utf-8");
@@ -43556,7 +43898,7 @@ var init_generate_changelog = __esm({
43556
43898
  const outputPath = platformConfig?.path ?? getDefaultOutputPath(targetPlatform);
43557
43899
  const content = generateForPlatform(targetPlatform, sourceContent, repoSlug, limit);
43558
43900
  if (!dryRun) {
43559
- const fullPath = join18(getProjectRoot28(), outputPath);
43901
+ const fullPath = join19(getProjectRoot28(), outputPath);
43560
43902
  mkdirSync5(dirname8(fullPath), { recursive: true });
43561
43903
  writeFileSync5(fullPath, content, "utf-8");
43562
43904
  }
@@ -43577,7 +43919,7 @@ var init_generate_changelog = __esm({
43577
43919
  limit
43578
43920
  );
43579
43921
  if (!dryRun) {
43580
- const fullPath = join18(getProjectRoot28(), platformConfig.path);
43922
+ const fullPath = join19(getProjectRoot28(), platformConfig.path);
43581
43923
  mkdirSync5(dirname8(fullPath), { recursive: true });
43582
43924
  writeFileSync5(fullPath, content, "utf-8");
43583
43925
  }
@@ -44717,8 +45059,8 @@ __export(init_exports, {
44717
45059
  getWorkflowTemplatesDir: () => getWorkflowTemplatesDir,
44718
45060
  initCommand: () => initCommand2
44719
45061
  });
44720
- import { existsSync as existsSync13, readFileSync as readFileSync14 } from "node:fs";
44721
- import { dirname as dirname9, join as join19, resolve as resolve6 } from "node:path";
45062
+ import { existsSync as existsSync14, readFileSync as readFileSync14 } from "node:fs";
45063
+ import { dirname as dirname9, join as join20, resolve as resolve6 } from "node:path";
44722
45064
  import { fileURLToPath as fileURLToPath5 } from "node:url";
44723
45065
  import {
44724
45066
  CleoError as CleoError5,
@@ -44729,11 +45071,11 @@ import {
44729
45071
  function getGitignoreTemplate() {
44730
45072
  try {
44731
45073
  const thisFile = fileURLToPath5(import.meta.url);
44732
- const packageRoot = join19(thisFile, "..", "..", "..", "..");
44733
- const localTemplatePath = join19(packageRoot, "templates", "cleo-gitignore");
44734
- const monorepoTemplatePath = join19(packageRoot, "..", "..", "templates", "cleo-gitignore");
44735
- const templatePath = existsSync13(localTemplatePath) ? localTemplatePath : monorepoTemplatePath;
44736
- if (existsSync13(templatePath)) {
45074
+ const packageRoot = join20(thisFile, "..", "..", "..", "..");
45075
+ const localTemplatePath = join20(packageRoot, "templates", "cleo-gitignore");
45076
+ const monorepoTemplatePath = join20(packageRoot, "..", "..", "templates", "cleo-gitignore");
45077
+ const templatePath = existsSync14(localTemplatePath) ? localTemplatePath : monorepoTemplatePath;
45078
+ if (existsSync14(templatePath)) {
44737
45079
  return readFileSync14(templatePath, "utf-8");
44738
45080
  }
44739
45081
  } catch {
@@ -44743,7 +45085,7 @@ function getGitignoreTemplate() {
44743
45085
  function getWorkflowTemplatesDir() {
44744
45086
  const thisFile = fileURLToPath5(import.meta.url);
44745
45087
  const packageRoot = resolve6(dirname9(thisFile), "..", "..", "..", "..");
44746
- return join19(packageRoot, "templates", "workflows");
45088
+ return join20(packageRoot, "templates", "workflows");
44747
45089
  }
44748
45090
  var initCommand2;
44749
45091
  var init_init = __esm({
@@ -47235,17 +47577,19 @@ __export(memory_exports, {
47235
47577
  memoryCommand: () => memoryCommand
47236
47578
  });
47237
47579
  import { createHash as createHash3 } from "node:crypto";
47238
- import { existsSync as existsSync14, mkdirSync as mkdirSync6, readdirSync as readdirSync3, readFileSync as readFileSync15, writeFileSync as writeFileSync6 } from "node:fs";
47239
- import { homedir as homedir6 } from "node:os";
47240
- import { join as join20 } from "node:path";
47580
+ import { existsSync as existsSync15, mkdirSync as mkdirSync6, readdirSync as readdirSync3, readFileSync as readFileSync15, writeFileSync as writeFileSync6 } from "node:fs";
47581
+ import { homedir as homedir7 } from "node:os";
47582
+ import { join as join21 } from "node:path";
47583
+ import { getProjectRoot as getProjectRoot30 } from "@cleocode/core";
47241
47584
  import {
47242
47585
  getBrainDb as getBrainDb2,
47243
- getBrainNativeDb as getBrainNativeDb3,
47244
47586
  getDreamStatus,
47245
- getProjectRoot as getProjectRoot30,
47587
+ getTierStats,
47246
47588
  runConsolidation,
47589
+ scanDuplicateEntries,
47590
+ setEntryTier,
47247
47591
  triggerManualDream
47248
- } from "@cleocode/core/internal";
47592
+ } from "@cleocode/core/memory";
47249
47593
  function parseMemoryFileFrontmatter(raw) {
47250
47594
  const lines = raw.split("\n");
47251
47595
  if (!lines[0]?.trim().startsWith("---")) {
@@ -47278,7 +47622,7 @@ ${body}`).digest("hex").slice(0, 16);
47278
47622
  }
47279
47623
  function loadImportHashes(stateFile) {
47280
47624
  try {
47281
- if (!existsSync14(stateFile)) return /* @__PURE__ */ new Set();
47625
+ if (!existsSync15(stateFile)) return /* @__PURE__ */ new Set();
47282
47626
  const raw = readFileSync15(stateFile, "utf-8");
47283
47627
  const parsed = JSON.parse(raw);
47284
47628
  return new Set(parsed.hashes);
@@ -47288,7 +47632,7 @@ function loadImportHashes(stateFile) {
47288
47632
  }
47289
47633
  function saveImportHashes(stateFile, hashes) {
47290
47634
  const dir = stateFile.slice(0, stateFile.lastIndexOf("/"));
47291
- if (!existsSync14(dir)) mkdirSync6(dir, { recursive: true });
47635
+ if (!existsSync15(dir)) mkdirSync6(dir, { recursive: true });
47292
47636
  writeFileSync6(stateFile, JSON.stringify({ hashes: [...hashes] }, null, 2), "utf-8");
47293
47637
  }
47294
47638
  function makeMemorySubcommand(opts) {
@@ -48266,7 +48610,7 @@ var init_memory3 = __esm({
48266
48610
  async run({ args }) {
48267
48611
  const root = getProjectRoot30();
48268
48612
  try {
48269
- const { runObserver, runReflector } = await import("@cleocode/core/internal");
48613
+ const { runObserver, runReflector } = await import("@cleocode/core/memory");
48270
48614
  const observerResult = await runObserver(root, args.session, {
48271
48615
  thresholdOverride: 1
48272
48616
  });
@@ -48306,65 +48650,13 @@ var init_memory3 = __esm({
48306
48650
  async run({ args }) {
48307
48651
  const root = getProjectRoot30();
48308
48652
  try {
48309
- const { getBrainDb: getBrainDbInner, getBrainNativeDb: getBrainNativeDbInner } = await import("@cleocode/core/internal");
48310
- await getBrainDbInner(root);
48311
- const nativeDb = getBrainNativeDbInner();
48312
- if (!nativeDb) {
48313
- cliError("brain.db is unavailable", "E_INTERNAL", { name: "E_INTERNAL" });
48314
- process.exit(1);
48315
- return;
48316
- }
48317
- const tables = [
48318
- { name: "brain_observations", hashCol: "content_hash", labelCol: "title" },
48319
- { name: "brain_decisions", hashCol: "content_hash", labelCol: "decision" },
48320
- { name: "brain_patterns", hashCol: "content_hash", labelCol: "pattern" },
48321
- { name: "brain_learnings", hashCol: "content_hash", labelCol: "insight" }
48322
- ];
48323
- const groups = [];
48324
- for (const t of tables) {
48325
- let dupRows;
48326
- try {
48327
- dupRows = nativeDb.prepare(
48328
- `SELECT ${t.hashCol} AS hash, COUNT(*) AS cnt
48329
- FROM ${t.name}
48330
- WHERE ${t.hashCol} IS NOT NULL
48331
- AND invalid_at IS NULL
48332
- GROUP BY ${t.hashCol}
48333
- HAVING cnt > 1
48334
- ORDER BY cnt DESC
48335
- LIMIT 20`
48336
- ).all();
48337
- } catch {
48338
- dupRows = [];
48339
- }
48340
- for (const row of dupRows) {
48341
- let sampleRows;
48342
- try {
48343
- sampleRows = nativeDb.prepare(
48344
- `SELECT id, COALESCE(${t.labelCol}, id) AS label
48345
- FROM ${t.name}
48346
- WHERE ${t.hashCol} = ?
48347
- AND invalid_at IS NULL
48348
- LIMIT 3`
48349
- ).all(row.hash);
48350
- } catch {
48351
- sampleRows = [];
48352
- }
48353
- groups.push({
48354
- table: t.name,
48355
- hash: row.hash,
48356
- count: row.cnt,
48357
- samples: sampleRows.map((r) => `${r.id}: ${String(r.label).slice(0, 80)}`)
48358
- });
48359
- }
48360
- }
48361
- const totalDups = groups.reduce((sum, g) => sum + (g.count - 1), 0);
48653
+ await getBrainDb2(root);
48654
+ const { totalDuplicateRows, groups } = await scanDuplicateEntries();
48362
48655
  if (args.apply) {
48363
- const { runConsolidation: runConsolidationInner } = await import("@cleocode/core/internal");
48364
- const result = await runConsolidationInner(root);
48656
+ const result = await runConsolidation(root);
48365
48657
  cliOutput(
48366
48658
  {
48367
- totalDuplicateRows: totalDups,
48659
+ totalDuplicateRows,
48368
48660
  groups,
48369
48661
  applied: true,
48370
48662
  consolidation: { deduplicated: result.deduplicated }
@@ -48373,7 +48665,7 @@ var init_memory3 = __esm({
48373
48665
  );
48374
48666
  } else {
48375
48667
  cliOutput(
48376
- { totalDuplicateRows: totalDups, groups, applied: false },
48668
+ { totalDuplicateRows, groups, applied: false },
48377
48669
  { command: "memory-dedup-scan", operation: "memory.dedup-scan" }
48378
48670
  );
48379
48671
  }
@@ -48400,16 +48692,16 @@ var init_memory3 = __esm({
48400
48692
  }
48401
48693
  },
48402
48694
  async run({ args }) {
48403
- const sourceDir = args.from ?? join20(homedir6(), ".claude", "projects", "-mnt-projects-cleocode", "memory");
48695
+ const sourceDir = args.from ?? join21(homedir7(), ".claude", "projects", "-mnt-projects-cleocode", "memory");
48404
48696
  const isDryRun = !!args["dry-run"];
48405
48697
  const projectRoot = getProjectRoot30();
48406
- const stateFile = join20(projectRoot, CLEO_DIR_NAME, MIGRATE_MEMORY_HASHES_JSON);
48407
- if (!existsSync14(sourceDir)) {
48698
+ const stateFile = join21(projectRoot, CLEO_DIR_NAME, MIGRATE_MEMORY_HASHES_JSON);
48699
+ if (!existsSync15(sourceDir)) {
48408
48700
  cliError(`Source directory not found: ${sourceDir}`, "E_NOT_FOUND", { name: "E_NOT_FOUND" });
48409
48701
  process.exit(1);
48410
48702
  return;
48411
48703
  }
48412
- const files = readdirSync3(sourceDir).filter((f) => f.endsWith(".md") && f !== "MEMORY.md").map((f) => join20(sourceDir, f));
48704
+ const files = readdirSync3(sourceDir).filter((f) => f.endsWith(".md") && f !== "MEMORY.md").map((f) => join21(sourceDir, f));
48413
48705
  const importedHashes = isDryRun ? /* @__PURE__ */ new Set() : loadImportHashes(stateFile);
48414
48706
  const stats = { total: files.length, imported: 0, skipped: 0, errors: 0 };
48415
48707
  const importedEntries = [];
@@ -48618,68 +48910,12 @@ var init_memory3 = __esm({
48618
48910
  const root = getProjectRoot30();
48619
48911
  try {
48620
48912
  await getBrainDb2(root);
48621
- const nativeDb = getBrainNativeDb3();
48622
- if (!nativeDb) {
48623
- cliError("brain.db not available", "E_INTERNAL", { name: "E_INTERNAL" });
48624
- process.exit(1);
48625
- return;
48626
- }
48627
- const tables = ["brain_observations", "brain_learnings", "brain_patterns", "brain_decisions"];
48913
+ const result = await getTierStats(root);
48628
48914
  const distribution = {};
48629
- for (const tbl of tables) {
48630
- try {
48631
- const rows = nativeDb.prepare(
48632
- `SELECT COALESCE(memory_tier, 'short') as tier, COUNT(*) as cnt
48633
- FROM ${tbl}
48634
- WHERE invalid_at IS NULL
48635
- GROUP BY memory_tier`
48636
- ).all();
48637
- distribution[tbl] = { short: 0, medium: 0, long: 0 };
48638
- for (const r of rows) {
48639
- distribution[tbl][r.tier] = r.cnt;
48640
- }
48641
- } catch {
48642
- distribution[tbl] = { short: 0, medium: 0, long: 0 };
48643
- }
48644
- }
48645
- const age7dMs = 7 * 24 * 60 * 60 * 1e3;
48646
- const now = Date.now();
48647
- const countdown = [];
48648
- for (const tbl of tables) {
48649
- const dateCol = tbl === "brain_patterns" ? "extracted_at" : "created_at";
48650
- try {
48651
- const rawRows = nativeDb.prepare(
48652
- `SELECT id, ${dateCol} as created_at, citation_count, verified, quality_score
48653
- FROM ${tbl}
48654
- WHERE memory_tier = 'medium'
48655
- AND invalid_at IS NULL
48656
- AND (citation_count >= 5 OR verified = 1)
48657
- ORDER BY ${dateCol} ASC
48658
- LIMIT 20`
48659
- ).all();
48660
- const rows = rawRows.map((raw) => {
48661
- const r = raw;
48662
- return {
48663
- id: String(r["id"] ?? ""),
48664
- tbl,
48665
- created_at: String(r["created_at"] ?? ""),
48666
- citation_count: Number(r["citation_count"] ?? 0),
48667
- verified: Number(r["verified"] ?? 0),
48668
- quality_score: r["quality_score"] == null ? null : Number(r["quality_score"])
48669
- };
48670
- });
48671
- for (const r of rows) {
48672
- const entryMs = new Date(r.created_at.replace(" ", "T")).getTime();
48673
- const promotionMs = entryMs + age7dMs;
48674
- const daysUntil = Math.max(0, (promotionMs - now) / (24 * 60 * 60 * 1e3));
48675
- const track = r.citation_count >= 5 ? `citation (${r.citation_count})` : "verified";
48676
- countdown.push({ id: r.id, table: tbl, daysUntil, track });
48677
- }
48678
- } catch {
48679
- }
48915
+ for (const t of result.tables) {
48916
+ distribution[t.table] = { short: t.short, medium: t.medium, long: t.long };
48680
48917
  }
48681
- countdown.sort((a, b) => a.daysUntil - b.daysUntil);
48682
- const top10 = countdown.slice(0, 10);
48918
+ const top10 = result.upcomingLongPromotions.slice(0, 10);
48683
48919
  cliOutput(
48684
48920
  { distribution, upcomingLongPromotions: top10 },
48685
48921
  { command: "memory-tier-stats", operation: "memory.tier.stats" }
@@ -48729,64 +48965,26 @@ var init_memory3 = __esm({
48729
48965
  }
48730
48966
  try {
48731
48967
  await getBrainDb2(root);
48732
- const nativeDb = getBrainNativeDb3();
48733
- if (!nativeDb) {
48734
- cliError("brain.db not available", "E_INTERNAL", { name: "E_INTERNAL" });
48735
- process.exit(1);
48736
- return;
48737
- }
48738
- const tables = ["brain_observations", "brain_learnings", "brain_patterns", "brain_decisions"];
48739
- const now = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
48740
- let found = false;
48741
- let fromTier = "";
48742
- let foundTable = "";
48743
- for (const tbl of tables) {
48744
- try {
48745
- const row = nativeDb.prepare(
48746
- `SELECT id, memory_tier FROM ${tbl} WHERE id = ? AND invalid_at IS NULL LIMIT 1`
48747
- ).get(args.id);
48748
- if (row) {
48749
- found = true;
48750
- fromTier = row.memory_tier ?? "short";
48751
- foundTable = tbl;
48752
- if (fromTier === targetTier) {
48753
- cliError(`Entry ${args.id} is already at tier '${targetTier}'`, "E_VALIDATION", {
48754
- name: "E_VALIDATION"
48755
- });
48756
- process.exit(1);
48757
- }
48758
- const tierOrder = { short: 0, medium: 1, long: 2 };
48759
- const fromOrd = tierOrder[fromTier] ?? 0;
48760
- const toOrd = tierOrder[targetTier] ?? 0;
48761
- if (toOrd <= fromOrd) {
48762
- cliError(
48763
- `Cannot promote: '${targetTier}' is not higher than current tier '${fromTier}'. Use 'demote' to lower tiers.`,
48764
- "E_VALIDATION",
48765
- { name: "E_VALIDATION" }
48766
- );
48767
- process.exit(1);
48768
- }
48769
- nativeDb.prepare(`UPDATE ${tbl} SET memory_tier = ?, updated_at = ? WHERE id = ?`).run(targetTier, now, args.id);
48770
- break;
48771
- }
48772
- } catch {
48773
- }
48774
- }
48775
- if (!found) {
48776
- cliError(
48777
- `Entry '${args.id}' not found in any brain table (or is invalidated)`,
48778
- "E_NOT_FOUND",
48779
- { name: "E_NOT_FOUND" }
48780
- );
48781
- process.exit(1);
48782
- }
48968
+ const result = await setEntryTier(args.id, targetTier, "promote");
48783
48969
  cliOutput(
48784
- { id: args.id, table: foundTable, fromTier, toTier: targetTier, reason, promotedAt: now },
48970
+ {
48971
+ id: result.id,
48972
+ table: result.table,
48973
+ fromTier: result.fromTier,
48974
+ toTier: result.toTier,
48975
+ reason,
48976
+ promotedAt: result.updatedAt
48977
+ },
48785
48978
  { command: "memory-tier-promote", operation: "memory.tier.promote" }
48786
48979
  );
48787
48980
  } catch (err) {
48788
48981
  const message = err instanceof Error ? err.message : String(err);
48789
- cliError(`Tier promote failed: ${message}`, "E_INTERNAL", { name: "E_INTERNAL" });
48982
+ const isValidation = message.includes("already at tier") || message.includes("Cannot promote") || message.includes("not found");
48983
+ if (isValidation) {
48984
+ cliError(message, "E_VALIDATION", { name: "E_VALIDATION" });
48985
+ } else {
48986
+ cliError(`Tier promote failed: ${message}`, "E_INTERNAL", { name: "E_INTERNAL" });
48987
+ }
48790
48988
  process.exit(1);
48791
48989
  }
48792
48990
  }
@@ -48833,72 +49031,26 @@ var init_memory3 = __esm({
48833
49031
  }
48834
49032
  try {
48835
49033
  await getBrainDb2(root);
48836
- const nativeDb = getBrainNativeDb3();
48837
- if (!nativeDb) {
48838
- cliError("brain.db not available", "E_INTERNAL", { name: "E_INTERNAL" });
48839
- process.exit(1);
48840
- return;
48841
- }
48842
- const tables = ["brain_observations", "brain_learnings", "brain_patterns", "brain_decisions"];
48843
- const now = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
48844
- let found = false;
48845
- let fromTier = "";
48846
- let foundTable = "";
48847
- for (const tbl of tables) {
48848
- try {
48849
- const row = nativeDb.prepare(
48850
- `SELECT id, memory_tier FROM ${tbl} WHERE id = ? AND invalid_at IS NULL LIMIT 1`
48851
- ).get(args.id);
48852
- if (row) {
48853
- found = true;
48854
- fromTier = row.memory_tier ?? "short";
48855
- foundTable = tbl;
48856
- if (fromTier === "long" && !args.force) {
48857
- cliError(
48858
- `Entry ${args.id} is in long tier. Long-tier entries are permanent. Use --force to override.`,
48859
- "E_VALIDATION",
48860
- { name: "E_VALIDATION" }
48861
- );
48862
- process.exit(1);
48863
- }
48864
- if (fromTier === targetTier) {
48865
- cliError(`Entry ${args.id} is already at tier '${targetTier}'`, "E_VALIDATION", {
48866
- name: "E_VALIDATION"
48867
- });
48868
- process.exit(1);
48869
- }
48870
- const tierOrder = { short: 0, medium: 1, long: 2 };
48871
- const fromOrd = tierOrder[fromTier] ?? 0;
48872
- const toOrd = tierOrder[targetTier] ?? 0;
48873
- if (toOrd >= fromOrd) {
48874
- cliError(
48875
- `Cannot demote: '${targetTier}' is not lower than current tier '${fromTier}'. Use 'promote' to raise tiers.`,
48876
- "E_VALIDATION",
48877
- { name: "E_VALIDATION" }
48878
- );
48879
- process.exit(1);
48880
- }
48881
- nativeDb.prepare(`UPDATE ${tbl} SET memory_tier = ?, updated_at = ? WHERE id = ?`).run(targetTier, now, args.id);
48882
- break;
48883
- }
48884
- } catch {
48885
- }
48886
- }
48887
- if (!found) {
48888
- cliError(
48889
- `Entry '${args.id}' not found in any brain table (or is invalidated)`,
48890
- "E_NOT_FOUND",
48891
- { name: "E_NOT_FOUND" }
48892
- );
48893
- process.exit(1);
48894
- }
49034
+ const result = await setEntryTier(args.id, targetTier, "demote", { force: !!args.force });
48895
49035
  cliOutput(
48896
- { id: args.id, table: foundTable, fromTier, toTier: targetTier, reason, demotedAt: now },
49036
+ {
49037
+ id: result.id,
49038
+ table: result.table,
49039
+ fromTier: result.fromTier,
49040
+ toTier: result.toTier,
49041
+ reason,
49042
+ demotedAt: result.updatedAt
49043
+ },
48897
49044
  { command: "memory-tier-demote", operation: "memory.tier.demote" }
48898
49045
  );
48899
49046
  } catch (err) {
48900
49047
  const message = err instanceof Error ? err.message : String(err);
48901
- cliError(`Tier demote failed: ${message}`, "E_INTERNAL", { name: "E_INTERNAL" });
49048
+ const isValidation = message.includes("already at tier") || message.includes("Cannot demote") || message.includes("not found") || message.includes("long tier") || message.includes("Long-tier");
49049
+ if (isValidation) {
49050
+ cliError(message, "E_VALIDATION", { name: "E_VALIDATION" });
49051
+ } else {
49052
+ cliError(`Tier demote failed: ${message}`, "E_INTERNAL", { name: "E_INTERNAL" });
49053
+ }
48902
49054
  process.exit(1);
48903
49055
  }
48904
49056
  }
@@ -49546,13 +49698,13 @@ __export(nexus_exports, {
49546
49698
  nexusCommand: () => nexusCommand
49547
49699
  });
49548
49700
  import { appendFile, mkdir as mkdir2 } from "node:fs/promises";
49549
- import { homedir as homedir7 } from "node:os";
49701
+ import { homedir as homedir8 } from "node:os";
49550
49702
  import path4 from "node:path";
49551
49703
  import { generateGexf, getSymbolImpact } from "@cleocode/core/nexus";
49552
49704
  async function appendDeprecationTelemetry(op, replacement) {
49553
49705
  try {
49554
49706
  const dateStr = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
49555
- const dir = path4.join(homedir7(), ".local", "state", "cleo", "nexus-deprecation");
49707
+ const dir = path4.join(homedir8(), ".local", "state", "cleo", "nexus-deprecation");
49556
49708
  await mkdir2(dir, { recursive: true });
49557
49709
  const record = JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), op, replacement }) + "\n";
49558
49710
  await appendFile(path4.join(dir, `${dateStr}.jsonl`), record, "utf8");
@@ -49806,9 +49958,9 @@ var init_nexus4 = __esm({
49806
49958
  args: {},
49807
49959
  async run() {
49808
49960
  try {
49809
- const { homedir: homedir9 } = await import("node:os");
49961
+ const { homedir: homedir10 } = await import("node:os");
49810
49962
  const { installNexusAugmentHook } = await import("@cleocode/core/internal");
49811
- const homeDir = homedir9();
49963
+ const homeDir = homedir10();
49812
49964
  installNexusAugmentHook(homeDir);
49813
49965
  cliOutput({ homeDir }, { command: "nexus-setup", operation: "nexus.setup" });
49814
49966
  } catch (err) {
@@ -53781,7 +53933,7 @@ var init_provenance2 = __esm({
53781
53933
  await dispatchFromCli(
53782
53934
  "mutate",
53783
53935
  "provenance",
53784
- "provenance.backfill",
53936
+ "backfill",
53785
53937
  {
53786
53938
  since: args.since,
53787
53939
  forceOverwrite: args["force-overwrite"] === true,
@@ -53821,7 +53973,7 @@ var init_provenance2 = __esm({
53821
53973
  await dispatchFromCli(
53822
53974
  "query",
53823
53975
  "provenance",
53824
- "provenance.verify",
53976
+ "verify",
53825
53977
  {
53826
53978
  ...version ? { version } : {},
53827
53979
  all,
@@ -54458,7 +54610,7 @@ var init_release3 = __esm({
54458
54610
  await dispatchFromCli(
54459
54611
  "mutate",
54460
54612
  "release",
54461
- "release.plan",
54613
+ "plan",
54462
54614
  {
54463
54615
  version: args.version,
54464
54616
  epicId: args.epic,
@@ -54472,7 +54624,7 @@ var init_release3 = __esm({
54472
54624
  await dispatchFromCli(
54473
54625
  "mutate",
54474
54626
  "release",
54475
- "release.open",
54627
+ "open",
54476
54628
  {
54477
54629
  version: args.version
54478
54630
  },
@@ -54680,7 +54832,7 @@ var init_release3 = __esm({
54680
54832
  await dispatchFromCli(
54681
54833
  "mutate",
54682
54834
  "release",
54683
- "release.plan",
54835
+ "plan",
54684
54836
  {
54685
54837
  version: args.version,
54686
54838
  epicId: args.epic,
@@ -54721,7 +54873,7 @@ var init_release3 = __esm({
54721
54873
  await dispatchFromCli(
54722
54874
  "mutate",
54723
54875
  "release",
54724
- "release.open",
54876
+ "open",
54725
54877
  {
54726
54878
  version: args.version,
54727
54879
  workflow: args.workflow,
@@ -55620,8 +55772,7 @@ __export(restore_exports, {
55620
55772
  });
55621
55773
  import fs3 from "node:fs";
55622
55774
  import path5 from "node:path";
55623
- import { CleoError as CleoError8, getTaskAccessor as getTaskAccessor3 } from "@cleocode/core";
55624
- import { getProjectRoot as getProjectRoot33 } from "@cleocode/core/internal";
55775
+ import { CleoError as CleoError8, getProjectRoot as getProjectRoot33, getTaskAccessor as getTaskAccessor3 } from "@cleocode/core";
55625
55776
  function parseMarkdownValue(raw) {
55626
55777
  const trimmed = raw.trim();
55627
55778
  if (trimmed === "_(not present)_" || trimmed === "") return void 0;
@@ -56107,7 +56258,7 @@ __export(revert_exports, {
56107
56258
  revertCommand: () => revertCommand
56108
56259
  });
56109
56260
  import { readFile as readFile3 } from "node:fs/promises";
56110
- import { join as join21 } from "node:path";
56261
+ import { join as join22 } from "node:path";
56111
56262
  import { cwd as processCwd2 } from "node:process";
56112
56263
  import { E_RECEIPT_NOT_FOUND } from "@cleocode/core/sentient/chain-walker.js";
56113
56264
  import { SENTIENT_STATE_FILE } from "@cleocode/core/sentient/daemon.js";
@@ -56160,7 +56311,7 @@ async function loadOwnerAttestation(attestationFilePath) {
56160
56311
  return obj;
56161
56312
  }
56162
56313
  async function loadOwnerPubkeys(projectRoot) {
56163
- const path6 = join21(projectRoot, OWNER_PUBKEYS_FILE);
56314
+ const path6 = join22(projectRoot, OWNER_PUBKEYS_FILE);
56164
56315
  try {
56165
56316
  const raw = await readFile3(path6, "utf-8");
56166
56317
  const parsed = JSON.parse(raw);
@@ -56244,7 +56395,7 @@ var init_revert = __esm({
56244
56395
  if (attestation && allowedPubkeys.size > 0 && !allowedPubkeys.has(attestation.ownerPubkey)) {
56245
56396
  emitFailure2(
56246
56397
  E_OWNER_ATTESTATION_REQUIRED,
56247
- `Attestation pubkey "${attestation.ownerPubkey}" is not in the owner allowlist at ${join21(projectRoot, OWNER_PUBKEYS_FILE)}`,
56398
+ `Attestation pubkey "${attestation.ownerPubkey}" is not in the owner allowlist at ${join22(projectRoot, OWNER_PUBKEYS_FILE)}`,
56248
56399
  jsonMode
56249
56400
  );
56250
56401
  }
@@ -56297,7 +56448,7 @@ ${lines}`
56297
56448
  identity,
56298
56449
  includeHuman
56299
56450
  });
56300
- const statePath = join21(projectRoot, SENTIENT_STATE_FILE);
56451
+ const statePath = join22(projectRoot, SENTIENT_STATE_FILE);
56301
56452
  const state = await readSentientState(statePath);
56302
56453
  emitSuccess(
56303
56454
  {
@@ -56679,7 +56830,7 @@ __export(self_update_exports, {
56679
56830
  });
56680
56831
  import { execFile } from "node:child_process";
56681
56832
  import { readFile as readFile4 } from "node:fs/promises";
56682
- import { join as join22 } from "node:path";
56833
+ import { join as join23 } from "node:path";
56683
56834
  import * as readline2 from "node:readline";
56684
56835
  import { promisify } from "node:util";
56685
56836
  import {
@@ -56694,7 +56845,7 @@ import {
56694
56845
  async function getCurrentVersion() {
56695
56846
  const cleoHome = getCleoHome();
56696
56847
  try {
56697
- const content = await readFile4(join22(cleoHome, "VERSION"), "utf-8");
56848
+ const content = await readFile4(join23(cleoHome, "VERSION"), "utf-8");
56698
56849
  return (content.split("\n")[0] ?? "unknown").trim();
56699
56850
  } catch {
56700
56851
  return "unknown";
@@ -56748,7 +56899,7 @@ async function writeRuntimeVersionMetadata(mode, source, version) {
56748
56899
  ];
56749
56900
  await import("node:fs/promises").then(
56750
56901
  ({ writeFile: writeFile3, mkdir: mkdir4 }) => mkdir4(cleoHome, { recursive: true }).then(
56751
- () => writeFile3(join22(cleoHome, "VERSION"), `${lines.join("\n")}
56902
+ () => writeFile3(join23(cleoHome, "VERSION"), `${lines.join("\n")}
56752
56903
  `, "utf-8")
56753
56904
  )
56754
56905
  );
@@ -57159,7 +57310,7 @@ var sentient_exports = {};
57159
57310
  __export(sentient_exports, {
57160
57311
  sentientCommand: () => sentientCommand
57161
57312
  });
57162
- import { join as join23 } from "node:path";
57313
+ import { join as join24 } from "node:path";
57163
57314
  import { cwd as processCwd3 } from "node:process";
57164
57315
  import {
57165
57316
  getSentientDaemonStatus as getSentientDaemonStatus2,
@@ -57228,7 +57379,7 @@ var init_sentient3 = __esm({
57228
57379
  return;
57229
57380
  }
57230
57381
  if (dryRun) {
57231
- const statePath2 = join23(projectRoot, SENTIENT_STATE_FILE2);
57382
+ const statePath2 = join24(projectRoot, SENTIENT_STATE_FILE2);
57232
57383
  const outcome = await safeRunTick({ projectRoot, statePath: statePath2, dryRun: true });
57233
57384
  emitSuccess2(
57234
57385
  { dryRun: true, outcome },
@@ -57344,7 +57495,7 @@ Logs: ${logPath}`
57344
57495
  const jsonMode = args.json === true;
57345
57496
  const dryRun = args["dry-run"] === true;
57346
57497
  try {
57347
- const statePath = join23(projectRoot, SENTIENT_STATE_FILE2);
57498
+ const statePath = join24(projectRoot, SENTIENT_STATE_FILE2);
57348
57499
  const outcome = await safeRunTick({ projectRoot, statePath, dryRun });
57349
57500
  emitSuccess2(
57350
57501
  { outcome, dryRun },
@@ -57396,7 +57547,7 @@ Logs: ${logPath}`
57396
57547
  const jsonMode = args.json === true;
57397
57548
  const id = args.id;
57398
57549
  try {
57399
- const { getDb: getDb3 } = await import("@cleocode/core/internal");
57550
+ const { getDb: getDb3 } = await import("@cleocode/core/store/sqlite.js");
57400
57551
  const { tasks } = await import("@cleocode/core/store/tasks-schema");
57401
57552
  const { and, eq: eq2, like } = await import("drizzle-orm");
57402
57553
  const db = await getDb3(projectRoot);
@@ -57413,7 +57564,7 @@ Logs: ${logPath}`
57413
57564
  return;
57414
57565
  }
57415
57566
  await db.update(tasks).set({ status: "pending", updatedAt: now }).where(eq2(tasks.id, id)).run();
57416
- const statePath = join23(projectRoot, SENTIENT_STATE_FILE2);
57567
+ const statePath = join24(projectRoot, SENTIENT_STATE_FILE2);
57417
57568
  const state = await readSentientState2(statePath);
57418
57569
  await patchSentientState(statePath, {
57419
57570
  tier2Stats: {
@@ -57448,7 +57599,7 @@ Logs: ${logPath}`
57448
57599
  const id = args.id;
57449
57600
  const reason = args.reason ?? "rejected by owner";
57450
57601
  try {
57451
- const { getDb: getDb3 } = await import("@cleocode/core/internal");
57602
+ const { getDb: getDb3 } = await import("@cleocode/core/store/sqlite.js");
57452
57603
  const { tasks } = await import("@cleocode/core/store/tasks-schema");
57453
57604
  const { and, eq: eq2, like } = await import("drizzle-orm");
57454
57605
  const db = await getDb3(projectRoot);
@@ -57465,7 +57616,7 @@ Logs: ${logPath}`
57465
57616
  return;
57466
57617
  }
57467
57618
  await db.update(tasks).set({ status: "cancelled", cancellationReason: reason, cancelledAt: now, updatedAt: now }).where(eq2(tasks.id, id)).run();
57468
- const statePath = join23(projectRoot, SENTIENT_STATE_FILE2);
57619
+ const statePath = join24(projectRoot, SENTIENT_STATE_FILE2);
57469
57620
  const state = await readSentientState2(statePath);
57470
57621
  await patchSentientState(statePath, {
57471
57622
  tier2Stats: {
@@ -57510,7 +57661,7 @@ Logs: ${logPath}`
57510
57661
  const projectRoot = resolveProjectRoot6(args.project);
57511
57662
  const jsonMode = args.json === true;
57512
57663
  try {
57513
- const statePath = join23(projectRoot, SENTIENT_STATE_FILE2);
57664
+ const statePath = join24(projectRoot, SENTIENT_STATE_FILE2);
57514
57665
  const outcome = await safeRunProposeTick({ projectRoot, statePath });
57515
57666
  emitSuccess2(
57516
57667
  { outcome },
@@ -57530,7 +57681,7 @@ Logs: ${logPath}`
57530
57681
  const projectRoot = resolveProjectRoot6(args.project);
57531
57682
  const jsonMode = args.json === true;
57532
57683
  try {
57533
- const statePath = join23(projectRoot, SENTIENT_STATE_FILE2);
57684
+ const statePath = join24(projectRoot, SENTIENT_STATE_FILE2);
57534
57685
  const updated = await patchSentientState(statePath, { tier2Enabled: true });
57535
57686
  emitSuccess2({ tier2Enabled: updated.tier2Enabled }, jsonMode, "Tier-2 proposals enabled");
57536
57687
  } catch (err) {
@@ -57549,7 +57700,7 @@ Logs: ${logPath}`
57549
57700
  const projectRoot = resolveProjectRoot6(args.project);
57550
57701
  const jsonMode = args.json === true;
57551
57702
  try {
57552
- const statePath = join23(projectRoot, SENTIENT_STATE_FILE2);
57703
+ const statePath = join24(projectRoot, SENTIENT_STATE_FILE2);
57553
57704
  const updated = await patchSentientState(statePath, { tier2Enabled: false });
57554
57705
  emitSuccess2({ tier2Enabled: updated.tier2Enabled }, jsonMode, "Tier-2 proposals disabled");
57555
57706
  } catch (err) {
@@ -57580,7 +57731,7 @@ Logs: ${logPath}`
57580
57731
  const projectRoot = resolveProjectRoot6(args.project);
57581
57732
  const jsonMode = args.json === true;
57582
57733
  try {
57583
- const statePath = join23(projectRoot, SENTIENT_STATE_FILE2);
57734
+ const statePath = join24(projectRoot, SENTIENT_STATE_FILE2);
57584
57735
  const state = await readSentientState2(statePath);
57585
57736
  emitSuccess2(
57586
57737
  {
@@ -58541,12 +58692,48 @@ var init_session4 = __esm({
58541
58692
  // packages/cleo/src/cli/lib/readline-wizard-io.ts
58542
58693
  import { stdin as input, stdout as output } from "node:process";
58543
58694
  import * as readline3 from "node:readline/promises";
58544
- var ReadlineWizardIO;
58695
+ import { WizardFatalError, WizardInterruptError } from "@cleocode/core/setup";
58696
+ function stripBracketedPaste(raw) {
58697
+ return raw.replace(/\x1b\[200~/g, "").replace(/\x1b\[201~/g, "").trim();
58698
+ }
58699
+ var SETUP_STDIN_CLOSED_CODE, StdinClosedError, ReadlineWizardIO;
58545
58700
  var init_readline_wizard_io = __esm({
58546
58701
  "packages/cleo/src/cli/lib/readline-wizard-io.ts"() {
58547
58702
  "use strict";
58703
+ SETUP_STDIN_CLOSED_CODE = "E_SETUP_STDIN_CLOSED";
58704
+ StdinClosedError = class _StdinClosedError extends WizardFatalError {
58705
+ codeName = SETUP_STDIN_CLOSED_CODE;
58706
+ constructor() {
58707
+ super("stdin closed before section completed");
58708
+ this.name = "StdinClosedError";
58709
+ }
58710
+ /**
58711
+ * Type-guard so callers can identify this error without `instanceof`.
58712
+ *
58713
+ * @param err - Value caught from a `catch` block.
58714
+ */
58715
+ static is(err) {
58716
+ return err instanceof _StdinClosedError;
58717
+ }
58718
+ };
58548
58719
  ReadlineWizardIO = class {
58720
+ /**
58721
+ * Underlying readline interface.
58722
+ *
58723
+ * Exposed as `protected` (not `private`) so tests can emit `'SIGINT'` on it
58724
+ * to simulate Ctrl-C without requiring a real TTY. Production code MUST NOT
58725
+ * access this field directly.
58726
+ *
58727
+ * @internal
58728
+ */
58549
58729
  rl;
58730
+ /** AbortController aborted when stdin closes — surfaced as {@link StdinClosedError}. */
58731
+ eofController;
58732
+ /**
58733
+ * Whether a SIGINT was received. Set before throwing so `rethrowEof` does
58734
+ * not mistakenly wrap the AbortError as a `StdinClosedError`.
58735
+ */
58736
+ sigintReceived = false;
58550
58737
  /**
58551
58738
  * Construct a readline interface bound to the supplied streams.
58552
58739
  *
@@ -58554,10 +58741,23 @@ var init_readline_wizard_io = __esm({
58554
58741
  * production use; tests inject in-memory streams.
58555
58742
  *
58556
58743
  * @param inStream - Input stream; defaults to `process.stdin`.
58557
- * @param outStream - Output stream; defaults to `process.stdout`.
58744
+ * @param outStream - Output stream passed to readline for terminal-echo
58745
+ * purposes only; informational output goes to stderr.
58558
58746
  */
58559
58747
  constructor(inStream = input, outStream = output) {
58748
+ this.eofController = new AbortController();
58560
58749
  this.rl = readline3.createInterface({ input: inStream, output: outStream });
58750
+ this.rl.on("close", () => {
58751
+ if (!this.eofController.signal.aborted) {
58752
+ this.eofController.abort(new StdinClosedError());
58753
+ }
58754
+ });
58755
+ this.rl.on("SIGINT", () => {
58756
+ this.sigintReceived = true;
58757
+ if (!this.eofController.signal.aborted) {
58758
+ this.eofController.abort(new WizardInterruptError("interrupted by user"));
58759
+ }
58760
+ });
58561
58761
  }
58562
58762
  /**
58563
58763
  * Release the underlying readline interface.
@@ -58568,13 +58768,45 @@ var init_readline_wizard_io = __esm({
58568
58768
  close() {
58569
58769
  this.rl.close();
58570
58770
  }
58771
+ /**
58772
+ * Wrap an AbortError thrown by `rl.question()` into the appropriate
58773
+ * typed error.
58774
+ *
58775
+ * - SIGINT received → throw {@link WizardInterruptError}
58776
+ * - Stdin EOF → throw {@link StdinClosedError}
58777
+ * - Any other error → re-throw as-is.
58778
+ *
58779
+ * @internal
58780
+ */
58781
+ rethrowEof(err) {
58782
+ if (err instanceof Error && (err.name === "AbortError" || err.name === "AbortSignal") && this.eofController.signal.aborted) {
58783
+ if (this.sigintReceived) {
58784
+ throw new WizardInterruptError("interrupted by user");
58785
+ }
58786
+ throw new StdinClosedError();
58787
+ }
58788
+ throw err;
58789
+ }
58571
58790
  async prompt(question) {
58572
- const answer = await this.rl.question(`${question} `);
58573
- return answer.trim();
58791
+ try {
58792
+ const raw = await this.rl.question(`${question} `, {
58793
+ signal: this.eofController.signal
58794
+ });
58795
+ return stripBracketedPaste(raw);
58796
+ } catch (err) {
58797
+ this.rethrowEof(err);
58798
+ }
58574
58799
  }
58575
58800
  async confirm(question, defaultValue) {
58576
58801
  const hint = defaultValue === void 0 ? "[y/n]" : defaultValue ? "[Y/n]" : "[y/N]";
58577
- const raw = (await this.rl.question(`${question} ${hint} `)).trim().toLowerCase();
58802
+ let raw;
58803
+ try {
58804
+ raw = stripBracketedPaste(
58805
+ await this.rl.question(`${question} ${hint} `, { signal: this.eofController.signal })
58806
+ ).toLowerCase();
58807
+ } catch (err) {
58808
+ this.rethrowEof(err);
58809
+ }
58578
58810
  if (raw === "") {
58579
58811
  if (defaultValue === void 0) {
58580
58812
  return this.confirm(question, defaultValue);
@@ -58589,35 +58821,47 @@ var init_readline_wizard_io = __esm({
58589
58821
  if (options.length === 0) {
58590
58822
  throw new Error(`ReadlineWizardIO.select: option list is empty for '${question}'`);
58591
58823
  }
58592
- process.stdout.write(`${question}
58824
+ process.stderr.write(`${question}
58593
58825
  `);
58594
58826
  options.forEach((opt, idx) => {
58595
- process.stdout.write(` ${idx + 1}) ${opt}
58827
+ process.stderr.write(` ${idx + 1}) ${opt}
58596
58828
  `);
58597
58829
  });
58598
58830
  const MAX_RETRIES = 10;
58599
58831
  for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
58600
- const raw = (await this.rl.question(`Choose [1-${options.length}]: `)).trim();
58832
+ let raw;
58833
+ try {
58834
+ raw = stripBracketedPaste(
58835
+ await this.rl.question(`Choose [1-${options.length}]: `, {
58836
+ signal: this.eofController.signal
58837
+ })
58838
+ );
58839
+ } catch (err) {
58840
+ this.rethrowEof(err);
58841
+ }
58601
58842
  if (/^\d+$/.test(raw)) {
58602
58843
  const idx = Number.parseInt(raw, 10) - 1;
58603
58844
  if (idx >= 0 && idx < options.length) return options[idx];
58604
58845
  }
58605
58846
  if (options.includes(raw)) return raw;
58606
- process.stdout.write(`Invalid choice '${raw}'. Try again.
58847
+ process.stderr.write(`Invalid choice '${raw}'. Try again.
58607
58848
  `);
58608
58849
  }
58609
58850
  throw new Error(
58610
58851
  `ReadlineWizardIO.select: gave up after ${MAX_RETRIES} invalid responses for '${question}'`
58611
58852
  );
58612
58853
  }
58854
+ /** Informational message — goes to stderr, never stdout. */
58613
58855
  info(message) {
58614
- process.stdout.write(`${message}
58856
+ process.stderr.write(`${message}
58615
58857
  `);
58616
58858
  }
58859
+ /** Non-fatal warning — goes to stderr. */
58617
58860
  warn(message) {
58618
58861
  process.stderr.write(`${message}
58619
58862
  `);
58620
58863
  }
58864
+ /** Error message — goes to stderr. */
58621
58865
  error(message) {
58622
58866
  process.stderr.write(`${message}
58623
58867
  `);
@@ -58633,12 +58877,138 @@ __export(setup_exports, {
58633
58877
  runSetup: () => runSetup,
58634
58878
  setupCommand: () => setupCommand2
58635
58879
  });
58636
- import { createDefaultWizardRunner } from "@cleocode/core/setup";
58880
+ import { createDefaultWizardRunner, WizardInterruptError as WizardInterruptError2 } from "@cleocode/core/setup";
58881
+ function mergeConfigJson(parsed, out) {
58882
+ out.configJson = parsed;
58883
+ for (const [sectionId, sectionOpts] of Object.entries(parsed)) {
58884
+ if (!WIZARD_SECTION_IDS.has(sectionId)) continue;
58885
+ if (typeof sectionOpts !== "object" || sectionOpts === null) continue;
58886
+ if ("provider" in sectionOpts && out.provider === void 0) {
58887
+ if (typeof sectionOpts["provider"] === "string" && sectionOpts["provider"] !== "") {
58888
+ out.provider = sectionOpts["provider"];
58889
+ }
58890
+ }
58891
+ if ("apiKey" in sectionOpts && out.apiKey === void 0) {
58892
+ if (typeof sectionOpts["apiKey"] === "string" && sectionOpts["apiKey"] !== "") {
58893
+ out.apiKey = sectionOpts["apiKey"];
58894
+ }
58895
+ }
58896
+ if ("label" in sectionOpts && out.label === void 0) {
58897
+ if (typeof sectionOpts["label"] === "string" && sectionOpts["label"] !== "") {
58898
+ out.label = sectionOpts["label"];
58899
+ }
58900
+ }
58901
+ if ("agentName" in sectionOpts && out.agentName === void 0) {
58902
+ if (typeof sectionOpts["agentName"] === "string" && sectionOpts["agentName"] !== "") {
58903
+ out.agentName = sectionOpts["agentName"];
58904
+ }
58905
+ }
58906
+ if ("soulMdContent" in sectionOpts && out.soulMdContent === void 0) {
58907
+ if (typeof sectionOpts["soulMdContent"] === "string" && sectionOpts["soulMdContent"] !== "") {
58908
+ out.soulMdContent = sectionOpts["soulMdContent"];
58909
+ }
58910
+ }
58911
+ if ("strictness" in sectionOpts && out.strictness === void 0) {
58912
+ const s = sectionOpts["strictness"];
58913
+ if (s === "strict" || s === "standard" || s === "minimal") {
58914
+ out.strictness = s;
58915
+ }
58916
+ }
58917
+ if ("harness" in sectionOpts && out.harness === void 0) {
58918
+ const h = sectionOpts["harness"];
58919
+ if (h === "pi" || h === "claude-code") {
58920
+ out.harness = h;
58921
+ }
58922
+ }
58923
+ if ("brainBridgeMode" in sectionOpts && out.brainBridgeMode === void 0) {
58924
+ const b = sectionOpts["brainBridgeMode"];
58925
+ if (b === "digest" || b === "file" || b === "disabled") {
58926
+ out.brainBridgeMode = b;
58927
+ }
58928
+ }
58929
+ if ("sentientEnabled" in sectionOpts && out.sentientEnabled === void 0) {
58930
+ if (typeof sectionOpts["sentientEnabled"] === "boolean") {
58931
+ out.sentientEnabled = sectionOpts["sentientEnabled"];
58932
+ }
58933
+ }
58934
+ if ("tier2Enabled" in sectionOpts && out.tier2Enabled === void 0) {
58935
+ if (typeof sectionOpts["tier2Enabled"] === "boolean") {
58936
+ out.tier2Enabled = sectionOpts["tier2Enabled"];
58937
+ }
58938
+ }
58939
+ if ("signaldockAutoConnect" in sectionOpts && out.signaldockAutoConnect === void 0) {
58940
+ if (typeof sectionOpts["signaldockAutoConnect"] === "boolean") {
58941
+ out.signaldockAutoConnect = sectionOpts["signaldockAutoConnect"];
58942
+ }
58943
+ }
58944
+ if ("brainRetentionDays" in sectionOpts && out.brainRetentionDays === void 0) {
58945
+ const v = sectionOpts["brainRetentionDays"];
58946
+ if (typeof v === "number" && Number.isInteger(v) && v >= 0) {
58947
+ out.brainRetentionDays = v;
58948
+ }
58949
+ }
58950
+ if ("brainEmbeddingEnabled" in sectionOpts && out.brainEmbeddingEnabled === void 0) {
58951
+ if (typeof sectionOpts["brainEmbeddingEnabled"] === "boolean") {
58952
+ out.brainEmbeddingEnabled = sectionOpts["brainEmbeddingEnabled"];
58953
+ }
58954
+ }
58955
+ if ("signaldockEnabled" in sectionOpts && out.signaldockEnabled === void 0) {
58956
+ if (typeof sectionOpts["signaldockEnabled"] === "boolean") {
58957
+ out.signaldockEnabled = sectionOpts["signaldockEnabled"];
58958
+ }
58959
+ }
58960
+ if ("signaldockEndpoint" in sectionOpts && out.signaldockEndpoint === void 0) {
58961
+ if (typeof sectionOpts["signaldockEndpoint"] === "string" && sectionOpts["signaldockEndpoint"] !== "") {
58962
+ out.signaldockEndpoint = sectionOpts["signaldockEndpoint"];
58963
+ }
58964
+ }
58965
+ if ("studioEnabled" in sectionOpts && out.studioEnabled === void 0) {
58966
+ if (typeof sectionOpts["studioEnabled"] === "boolean") {
58967
+ out.studioEnabled = sectionOpts["studioEnabled"];
58968
+ }
58969
+ }
58970
+ if ("conduitPath" in sectionOpts && out.conduitPath === void 0) {
58971
+ if (typeof sectionOpts["conduitPath"] === "string" && sectionOpts["conduitPath"] !== "") {
58972
+ out.conduitPath = sectionOpts["conduitPath"];
58973
+ }
58974
+ }
58975
+ if ("poolSeedingConsent" in sectionOpts && out.poolSeedingConsent === void 0) {
58976
+ if (typeof sectionOpts["poolSeedingConsent"] === "boolean") {
58977
+ out.poolSeedingConsent = sectionOpts["poolSeedingConsent"];
58978
+ }
58979
+ }
58980
+ if ("acEnforcementMode" in sectionOpts && out.acEnforcementMode === void 0) {
58981
+ const m = sectionOpts["acEnforcementMode"];
58982
+ if (m === "block" || m === "warn" || m === "off") {
58983
+ out.acEnforcementMode = m;
58984
+ }
58985
+ }
58986
+ if ("sessionAutoStart" in sectionOpts && out.sessionAutoStart === void 0) {
58987
+ if (typeof sectionOpts["sessionAutoStart"] === "boolean") {
58988
+ out.sessionAutoStart = sectionOpts["sessionAutoStart"];
58989
+ }
58990
+ }
58991
+ }
58992
+ }
58637
58993
  function buildWizardOptions(args) {
58638
58994
  const out = {};
58995
+ const configJsonRaw = args["config-json"] ?? args["configJson"];
58996
+ if (typeof configJsonRaw === "string" && configJsonRaw !== "") {
58997
+ let parsed;
58998
+ try {
58999
+ parsed = JSON.parse(configJsonRaw);
59000
+ } catch {
59001
+ }
59002
+ if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)) {
59003
+ mergeConfigJson(parsed, out);
59004
+ }
59005
+ }
58639
59006
  if (args["non-interactive"] === true || args["nonInteractive"] === true) {
58640
59007
  out.nonInteractive = true;
58641
59008
  }
59009
+ if (args["reset"] === true) {
59010
+ out.reset = true;
59011
+ }
58642
59012
  if (typeof args["provider"] === "string" && args["provider"] !== "") {
58643
59013
  out.provider = args["provider"];
58644
59014
  }
@@ -58664,12 +59034,65 @@ function buildWizardOptions(args) {
58664
59034
  if (typeof args["project-root"] === "string" && args["project-root"] !== "") {
58665
59035
  out.projectRoot = args["project-root"];
58666
59036
  }
59037
+ if (typeof args["harness"] === "string" && args["harness"] !== "") {
59038
+ const h = args["harness"];
59039
+ if (h === "pi" || h === "claude-code") {
59040
+ out.harness = h;
59041
+ }
59042
+ }
59043
+ if (typeof args["brain-bridge-mode"] === "string" && args["brain-bridge-mode"] !== "") {
59044
+ const b = args["brain-bridge-mode"];
59045
+ if (b === "digest" || b === "file" || b === "disabled") {
59046
+ out.brainBridgeMode = b;
59047
+ }
59048
+ } else if (typeof args["brainBridgeMode"] === "string" && args["brainBridgeMode"] !== "") {
59049
+ const b = args["brainBridgeMode"];
59050
+ if (b === "digest" || b === "file" || b === "disabled") {
59051
+ out.brainBridgeMode = b;
59052
+ }
59053
+ }
59054
+ if (typeof args["retention-days"] === "string" && args["retention-days"] !== "") {
59055
+ const days = Number.parseInt(args["retention-days"], 10);
59056
+ if (!Number.isNaN(days) && days >= 0) {
59057
+ out.brainRetentionDays = days;
59058
+ }
59059
+ } else if (typeof args["retentionDays"] === "number") {
59060
+ const days = args["retentionDays"];
59061
+ if (Number.isInteger(days) && days >= 0) {
59062
+ out.brainRetentionDays = days;
59063
+ }
59064
+ }
59065
+ if (typeof args["sentient"] === "string" && args["sentient"] !== "") {
59066
+ const s = args["sentient"];
59067
+ if (s === "on") out.sentientEnabled = true;
59068
+ else if (s === "off") out.sentientEnabled = false;
59069
+ }
59070
+ if (typeof args["tier2"] === "string" && args["tier2"] !== "") {
59071
+ const t = args["tier2"];
59072
+ if (t === "on") out.tier2Enabled = true;
59073
+ else if (t === "off") out.tier2Enabled = false;
59074
+ }
59075
+ if (args["signaldock-enabled"] === true) {
59076
+ out.signaldockEnabled = true;
59077
+ } else if (args["signaldock-enabled"] === false) {
59078
+ out.signaldockEnabled = false;
59079
+ }
59080
+ if (typeof args["signaldock-endpoint"] === "string" && args["signaldock-endpoint"] !== "") {
59081
+ out.signaldockEndpoint = args["signaldock-endpoint"];
59082
+ }
59083
+ if (args["studio-enabled"] === true) {
59084
+ out.studioEnabled = true;
59085
+ } else if (args["studio-enabled"] === false) {
59086
+ out.studioEnabled = false;
59087
+ }
58667
59088
  return out;
58668
59089
  }
58669
59090
  function wrapSingleSection(name, result) {
58670
59091
  return {
58671
59092
  sectionsRun: [name],
58672
- summary: [`${name}: ${result.summary}`]
59093
+ summary: [`${name}: ${result.summary}`],
59094
+ // Single-section runs never trigger the full first-run completion flow.
59095
+ firstRunComplete: false
58673
59096
  };
58674
59097
  }
58675
59098
  function isOk(result) {
@@ -58696,30 +59119,40 @@ async function runSetup(args, io) {
58696
59119
  ok: isOk(runResult)
58697
59120
  };
58698
59121
  }
58699
- var setupCommand2;
59122
+ var WIZARD_SECTION_IDS, setupCommand2;
58700
59123
  var init_setup = __esm({
58701
59124
  "packages/cleo/src/cli/commands/setup.ts"() {
58702
59125
  "use strict";
58703
59126
  init_dist();
58704
59127
  init_readline_wizard_io();
58705
59128
  init_renderers();
59129
+ WIZARD_SECTION_IDS = /* @__PURE__ */ new Set([
59130
+ "llm",
59131
+ "identity",
59132
+ "harness",
59133
+ "sentient",
59134
+ "project-conventions",
59135
+ "brain",
59136
+ "integrations",
59137
+ "verification"
59138
+ ]);
58706
59139
  setupCommand2 = defineCommand({
58707
59140
  meta: {
58708
59141
  name: "setup",
58709
- description: "Interactive setup wizard \u2014 runs all sections (llm, identity, sentient, project-conventions) in canonical order. Use --section <name> for a single section or --non-interactive with --provider/--api-key to configure LLM without prompts."
59142
+ description: "Interactive setup wizard \u2014 runs all 8 sections in canonical order (identity \u2192 llm \u2192 sentient \u2192 harness \u2192 brain \u2192 project-conventions \u2192 integrations \u2192 verification). Use --section <name> for a single section, --non-interactive with section-specific flags to configure without prompts, --config-json for fully scripted setup, or --reset to reconfigure already-set sections."
58710
59143
  },
58711
59144
  args: {
58712
59145
  section: {
58713
59146
  type: "string",
58714
- description: "Run only one named section. Valid: llm | identity | sentient | project-conventions"
59147
+ description: "Run only one named section. Valid: identity | llm | sentient | harness | brain | project-conventions | integrations | verification"
58715
59148
  },
58716
59149
  "non-interactive": {
58717
59150
  type: "boolean",
58718
- description: "Skip prompts. Sections that need extra data short-circuit silently. Pair with --provider and --api-key to configure LLM."
59151
+ description: "Skip prompts. Requires section-specific flags (e.g. --provider/--api-key for llm, --harness for harness, --brain-bridge-mode for brain, --sentient/--tier2 for sentient, --signaldock-enabled/--signaldock-endpoint/--studio-enabled for integrations). Missing required flags emit E_SETUP_MISSING_FLAG."
58719
59152
  },
58720
59153
  provider: {
58721
59154
  type: "string",
58722
- description: "LLM provider id when --non-interactive (anthropic, openai, gemini, openrouter, \u2026)."
59155
+ description: "LLM provider id when --non-interactive (anthropic, openai, gemini, openrouter, moonshot, deepseek, xai, groq, ollama)."
58723
59156
  },
58724
59157
  "api-key": {
58725
59158
  type: "string",
@@ -58740,6 +59173,46 @@ var init_setup = __esm({
58740
59173
  "project-root": {
58741
59174
  type: "string",
58742
59175
  description: "Override project root path (defaults to process.cwd())."
59176
+ },
59177
+ harness: {
59178
+ type: "string",
59179
+ description: "Active harness for the harness section when --non-interactive: 'pi' | 'claude-code'."
59180
+ },
59181
+ "brain-bridge-mode": {
59182
+ type: "string",
59183
+ description: "BRAIN memory bridge mode for the brain section when --non-interactive: 'digest' | 'file' | 'disabled'."
59184
+ },
59185
+ sentient: {
59186
+ type: "string",
59187
+ description: "Enable or disable the sentient daemon for the sentient section when --non-interactive: 'on' | 'off'."
59188
+ },
59189
+ tier2: {
59190
+ type: "string",
59191
+ description: "Enable or disable Tier-2 proposals for the sentient section when --non-interactive: 'on' | 'off'."
59192
+ },
59193
+ "config-json": {
59194
+ type: "string",
59195
+ description: `JSON bag of per-section options. Keys are section IDs ('identity', 'llm', 'brain', 'sentient', 'harness', 'project-conventions', 'integrations', 'verification'), values are WizardOptions sub-objects. Example: '{"identity":{"agentName":"Atlas"},"llm":{"provider":"anthropic","apiKey":"sk-ant-..."}}'. Explicit CLI flags take precedence over configJson values.`
59196
+ },
59197
+ reset: {
59198
+ type: "boolean",
59199
+ description: "Clear the 'already configured' sentinel before running \u2014 forces all sections to re-run even if they report isConfigured()=true. Does NOT clear the credential pool; use 'cleo llm remove' for that."
59200
+ },
59201
+ "retention-days": {
59202
+ type: "string",
59203
+ description: "BRAIN retention days for the brain section when --non-interactive (0 = retain forever, default 0). Must be a non-negative integer."
59204
+ },
59205
+ "signaldock-enabled": {
59206
+ type: "boolean",
59207
+ description: "Enable (true) or disable (false) the SignalDock transport. Used by the integrations section."
59208
+ },
59209
+ "signaldock-endpoint": {
59210
+ type: "string",
59211
+ description: "SignalDock endpoint URL for the integrations section (e.g. http://localhost:4000). Must be a valid HTTP(S) URL."
59212
+ },
59213
+ "studio-enabled": {
59214
+ type: "boolean",
59215
+ description: "Enable (true) or disable (false) the Studio web UI. Used by the integrations section."
58743
59216
  }
58744
59217
  },
58745
59218
  async run({ args }) {
@@ -58747,6 +59220,24 @@ var init_setup = __esm({
58747
59220
  let result;
58748
59221
  try {
58749
59222
  result = await runSetup(args, io);
59223
+ } catch (err) {
59224
+ io.close();
59225
+ if (err instanceof WizardInterruptError2 || err?.isWizardInterruptError) {
59226
+ process.stderr.write("Setup interrupted. Run 'cleo setup' to continue.\n");
59227
+ process.exit(130);
59228
+ }
59229
+ if (err instanceof WizardInterruptError2) {
59230
+ process.stderr.write("Setup interrupted. Run 'cleo setup' to continue.\n");
59231
+ process.exit(130);
59232
+ }
59233
+ if (StdinClosedError.is(err)) {
59234
+ cliError(err.message, 1, {
59235
+ name: err.codeName,
59236
+ fix: "Run cleo setup interactively (with a TTY) or use --non-interactive flags."
59237
+ });
59238
+ process.exit(1);
59239
+ }
59240
+ throw err;
58750
59241
  } finally {
58751
59242
  io.close();
58752
59243
  }
@@ -60402,8 +60893,8 @@ var transcript_exports = {};
60402
60893
  __export(transcript_exports, {
60403
60894
  transcriptCommand: () => transcriptCommand
60404
60895
  });
60405
- import { homedir as homedir8 } from "node:os";
60406
- import { join as join24 } from "node:path";
60896
+ import { homedir as homedir9 } from "node:os";
60897
+ import { join as join25 } from "node:path";
60407
60898
  import { getProjectRoot as getProjectRoot36 } from "@cleocode/core";
60408
60899
  import {
60409
60900
  parseDurationMs,
@@ -60457,7 +60948,7 @@ var init_transcript = __esm({
60457
60948
  }
60458
60949
  return;
60459
60950
  }
60460
- const projectsDir = args["projects-dir"] ?? join24(homedir8(), ".claude", "projects");
60951
+ const projectsDir = args["projects-dir"] ?? join25(homedir9(), ".claude", "projects");
60461
60952
  try {
60462
60953
  const result = await scanTranscripts(projectsDir);
60463
60954
  cliOutput(
@@ -60763,7 +61254,7 @@ var init_transcript = __esm({
60763
61254
  process.exit(2);
60764
61255
  return;
60765
61256
  }
60766
- const projectsDir = args["projects-dir"] ?? join24(homedir8(), ".claude", "projects");
61257
+ const projectsDir = args["projects-dir"] ?? join25(homedir9(), ".claude", "projects");
60767
61258
  try {
60768
61259
  const pruneResult = await pruneTranscripts({
60769
61260
  olderThanMs,
@@ -61428,15 +61919,15 @@ __export(web_exports, {
61428
61919
  });
61429
61920
  import { execFileSync as execFileSync4, spawn as spawn2 } from "node:child_process";
61430
61921
  import { mkdir as mkdir3, open, readFile as readFile5, rm, stat, writeFile as writeFile2 } from "node:fs/promises";
61431
- import { join as join25 } from "node:path";
61922
+ import { join as join26 } from "node:path";
61432
61923
  import { CleoError as CleoError12, formatError as formatError9, getCleoHome as getCleoHome2 } from "@cleocode/core";
61433
61924
  function getWebPaths() {
61434
61925
  const cleoHome = getCleoHome2();
61435
61926
  return {
61436
- pidFile: join25(cleoHome, "web-server.pid"),
61437
- configFile: join25(cleoHome, "web-server.json"),
61438
- logDir: join25(cleoHome, "logs"),
61439
- logFile: join25(cleoHome, "logs", "web-server.log")
61927
+ pidFile: join26(cleoHome, "web-server.pid"),
61928
+ configFile: join26(cleoHome, "web-server.json"),
61929
+ logDir: join26(cleoHome, "logs"),
61930
+ logFile: join26(cleoHome, "logs", "web-server.log")
61440
61931
  };
61441
61932
  }
61442
61933
  function isProcessRunning(pid) {
@@ -61475,7 +61966,7 @@ async function startWebServer(port, host) {
61475
61966
  throw new CleoError12(1 /* GENERAL_ERROR */, `Server already running (PID: ${status.pid})`);
61476
61967
  }
61477
61968
  const projectRoot = process.env["CLEO_ROOT"] ?? process.cwd();
61478
- const studioDir = process.env["CLEO_STUDIO_DIR"] ?? join25(projectRoot, "packages", "studio", "build");
61969
+ const studioDir = process.env["CLEO_STUDIO_DIR"] ?? join26(projectRoot, "packages", "studio", "build");
61479
61970
  await mkdir3(logDir, { recursive: true });
61480
61971
  await writeFile2(
61481
61972
  configFile,
@@ -61485,7 +61976,7 @@ async function startWebServer(port, host) {
61485
61976
  startedAt: (/* @__PURE__ */ new Date()).toISOString()
61486
61977
  })
61487
61978
  );
61488
- const webIndexPath = join25(studioDir, "index.js");
61979
+ const webIndexPath = join26(studioDir, "index.js");
61489
61980
  try {
61490
61981
  await stat(webIndexPath);
61491
61982
  } catch {
@@ -61986,7 +62477,7 @@ init_dist();
61986
62477
  init_field_context();
61987
62478
  init_format_context();
61988
62479
  import { readFileSync as readFileSync17 } from "node:fs";
61989
- import { dirname as dirname10, join as join27 } from "node:path";
62480
+ import { dirname as dirname10, join as join28 } from "node:path";
61990
62481
  import { fileURLToPath as fileURLToPath6 } from "node:url";
61991
62482
 
61992
62483
  // packages/cleo/src/cli/generated/command-manifest.ts
@@ -62564,7 +63055,7 @@ var COMMAND_MANIFEST = [
62564
63055
  {
62565
63056
  exportName: "releaseCommand",
62566
63057
  name: "release",
62567
- description: "Release lifecycle management",
63058
+ description: "Release lifecycle management \u2014 4-verb pipeline: plan \u2192 open \u2192 reconcile / rollback. ",
62568
63059
  load: async () => (await Promise.resolve().then(() => (init_release3(), release_exports))).releaseCommand
62569
63060
  },
62570
63061
  {
@@ -62780,7 +63271,7 @@ var COMMAND_MANIFEST = [
62780
63271
  {
62781
63272
  exportName: "worktreeCommand",
62782
63273
  name: "worktree",
62783
- description: "Inspect CLEO-managed git worktrees attached to this project. ",
63274
+ description: "Inspect and manage CLEO-attached git worktrees. ",
62784
63275
  load: async () => (await Promise.resolve().then(() => (init_worktree3(), worktree_exports))).worktreeCommand
62785
63276
  }
62786
63277
  ];
@@ -63087,14 +63578,14 @@ function didYouMean(input2, candidates, maxDistance = 2) {
63087
63578
  }
63088
63579
 
63089
63580
  // packages/cleo/src/cli/lib/first-run-detection.ts
63090
- import { existsSync as existsSync15 } from "node:fs";
63091
- import { join as join26 } from "node:path";
63581
+ import { existsSync as existsSync16 } from "node:fs";
63582
+ import { join as join27 } from "node:path";
63092
63583
  async function detectFirstRun() {
63093
63584
  const envKey = process.env["ANTHROPIC_API_KEY"];
63094
63585
  if (typeof envKey === "string" && envKey.length > 0) return false;
63095
63586
  const { getCleoPlatformPaths } = await import("@cleocode/paths");
63096
- const configPath = join26(getCleoPlatformPaths().config, "config.json");
63097
- if (existsSync15(configPath)) return false;
63587
+ const configPath = join27(getCleoPlatformPaths().config, "config.json");
63588
+ if (existsSync16(configPath)) return false;
63098
63589
  try {
63099
63590
  const { getCredentialPool } = await import("@cleocode/core/llm/credential-pool.js");
63100
63591
  const pool = getCredentialPool();
@@ -63182,7 +63673,7 @@ Or via NodeSource: https://github.com/nodesource/distributions
63182
63673
  }
63183
63674
  }
63184
63675
  function getPackageVersion() {
63185
- const pkgPath = join27(dirname10(fileURLToPath6(import.meta.url)), "../../package.json");
63676
+ const pkgPath = join28(dirname10(fileURLToPath6(import.meta.url)), "../../package.json");
63186
63677
  const pkg = JSON.parse(readFileSync17(pkgPath, "utf-8"));
63187
63678
  return pkg.version;
63188
63679
  }