@cleocode/cleo 2026.5.59 → 2026.5.61

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
@@ -23340,8 +23340,8 @@ async function loadPlaybookByName(name) {
23340
23340
  return null;
23341
23341
  }
23342
23342
  try {
23343
- const { getProjectRoot: getProjectRoot33 } = await import("@cleocode/core/internal");
23344
- const projectRoot = __playbookRuntimeOverrides.projectRoot ?? getProjectRoot33();
23343
+ const { getProjectRoot: getProjectRoot34 } = await import("@cleocode/core/internal");
23344
+ const projectRoot = __playbookRuntimeOverrides.projectRoot ?? getProjectRoot34();
23345
23345
  const resolved = resolvePlaybook(name, {
23346
23346
  projectRoot,
23347
23347
  globalPlaybooksDir: __playbookRuntimeOverrides.globalPlaybooksDir,
@@ -23385,8 +23385,8 @@ async function acquireDb() {
23385
23385
  async function buildDefaultDispatcher() {
23386
23386
  if (__playbookRuntimeOverrides.dispatcher) return __playbookRuntimeOverrides.dispatcher;
23387
23387
  const { orchestrateSpawnExecute: orchestrateSpawnExecute2 } = await Promise.resolve().then(() => (init_engine(), engine_exports));
23388
- const { getProjectRoot: getProjectRoot33 } = await import("@cleocode/core/internal");
23389
- const projectRoot = getProjectRoot33();
23388
+ const { getProjectRoot: getProjectRoot34 } = await import("@cleocode/core/internal");
23389
+ const projectRoot = getProjectRoot34();
23390
23390
  return {
23391
23391
  async dispatch(input) {
23392
23392
  try {
@@ -23576,8 +23576,8 @@ var init_playbook2 = __esm({
23576
23576
  projectRoot = __playbookRuntimeOverrides.projectRoot;
23577
23577
  } else {
23578
23578
  try {
23579
- const { getProjectRoot: getProjectRoot33 } = await import("@cleocode/core/internal");
23580
- projectRoot = getProjectRoot33();
23579
+ const { getProjectRoot: getProjectRoot34 } = await import("@cleocode/core/internal");
23580
+ projectRoot = getProjectRoot34();
23581
23581
  } catch {
23582
23582
  projectRoot = void 0;
23583
23583
  }
@@ -23641,14 +23641,14 @@ var init_playbook2 = __esm({
23641
23641
  const dispatcher = await buildDefaultDispatcher();
23642
23642
  let result;
23643
23643
  try {
23644
- const { getProjectRoot: getProjectRoot33 } = await import("@cleocode/core/internal");
23644
+ const { getProjectRoot: getProjectRoot34 } = await import("@cleocode/core/internal");
23645
23645
  const opts = {
23646
23646
  db,
23647
23647
  playbook: parsed.definition,
23648
23648
  playbookHash: parsed.sourceHash,
23649
23649
  initialContext,
23650
23650
  dispatcher,
23651
- projectRoot: getProjectRoot33()
23651
+ projectRoot: getProjectRoot34()
23652
23652
  };
23653
23653
  if (__playbookRuntimeOverrides.approvalSecret !== void 0) {
23654
23654
  opts.approvalSecret = __playbookRuntimeOverrides.approvalSecret;
@@ -27163,7 +27163,9 @@ var init_tasks3 = __esm({
27163
27163
  scope: params.scope,
27164
27164
  severity: params.severity,
27165
27165
  // T1633: BRAIN duplicate-bypass flag
27166
- forceDuplicate: params.forceDuplicate
27166
+ forceDuplicate: params.forceDuplicate,
27167
+ // T9218 / ADR-070: mandatory verifier for high-consequence tasks
27168
+ verifier: params.verifier
27167
27169
  }),
27168
27170
  "add"
27169
27171
  );
@@ -28537,11 +28539,11 @@ var init_security = __esm({
28537
28539
  });
28538
28540
 
28539
28541
  // packages/cleo/src/dispatch/middleware/sanitizer.ts
28540
- function createSanitizer(getProjectRoot33) {
28542
+ function createSanitizer(getProjectRoot34) {
28541
28543
  return async (req, next) => {
28542
28544
  if (req.params) {
28543
28545
  try {
28544
- const root = getProjectRoot33 ? getProjectRoot33() : void 0;
28546
+ const root = getProjectRoot34 ? getProjectRoot34() : void 0;
28545
28547
  req.params = sanitizeParams(req.params, root, {
28546
28548
  domain: req.domain,
28547
28549
  operation: req.operation
@@ -29396,6 +29398,19 @@ var init_add = __esm({
29396
29398
  "depends-waiver": {
29397
29399
  type: "string",
29398
29400
  description: "Justification for creating a critical-priority task without --depends (T1856). Records waiver in task metadata."
29401
+ },
29402
+ /**
29403
+ * Path to an existing verifier script (T9218 / ADR-070).
29404
+ *
29405
+ * Required when creating tasks with priority=critical, size=large, or
29406
+ * type=epic. The path must point to an existing .mjs file. Omitting
29407
+ * this on high-consequence tasks causes rejection with E_VERIFIER_REQUIRED.
29408
+ *
29409
+ * Use `cleo verify backfill <taskId>` to generate a stub after creation.
29410
+ */
29411
+ verifier: {
29412
+ type: "string",
29413
+ description: "Path to existing verifier script for this task (required for priority=critical, size=large, type=epic) (T9218 / ADR-070)"
29399
29414
  }
29400
29415
  },
29401
29416
  async run({ args, cmd }) {
@@ -29429,6 +29444,7 @@ var init_add = __esm({
29429
29444
  if (args.scope !== void 0) params["scope"] = args.scope;
29430
29445
  if (args.severity !== void 0) params["severity"] = args.severity;
29431
29446
  if (args["force-duplicate"] !== void 0) params["forceDuplicate"] = args["force-duplicate"];
29447
+ if (args.verifier !== void 0) params["verifier"] = args.verifier;
29432
29448
  if (args.priority === "critical" && !args.depends && args["depends-waiver"] === void 0) {
29433
29449
  cliError(
29434
29450
  'Critical-priority tasks must declare at least one dependency (--depends) or provide a waiver (--depends-waiver "<reason>").',
@@ -33809,9 +33825,9 @@ var init_backup = __esm({
33809
33825
  },
33810
33826
  async run({ args }) {
33811
33827
  const scope = args.scope;
33812
- const { packBundle, getProjectRoot: getProjectRoot33 } = await import("@cleocode/core/internal");
33828
+ const { packBundle, getProjectRoot: getProjectRoot34 } = await import("@cleocode/core/internal");
33813
33829
  const includesProject = scope === "project" || scope === "all";
33814
- const projectRoot = includesProject ? getProjectRoot33() : void 0;
33830
+ const projectRoot = includesProject ? getProjectRoot34() : void 0;
33815
33831
  let passphrase;
33816
33832
  if (args.encrypt === true) {
33817
33833
  passphrase = process.env["CLEO_BACKUP_PASSPHRASE"];
@@ -45315,7 +45331,7 @@ var init_nexus4 = __esm({
45315
45331
  const repoPath = args.path ? path3.resolve(args.path) : process.cwd();
45316
45332
  humanInfo(`[nexus] Analyzing: ${repoPath}${isIncremental ? " (incremental)" : ""}`);
45317
45333
  try {
45318
- const [{ getNexusDb, nexusSchema }, { runPipeline }, { getProjectRoot: getProjectRoot33 }, { eq: eq2 }] = await Promise.all([
45334
+ const [{ getNexusDb, nexusSchema }, { runPipeline }, { getProjectRoot: getProjectRoot34 }, { eq: eq2 }] = await Promise.all([
45319
45335
  import("@cleocode/core/store/nexus-sqlite"),
45320
45336
  import("@cleocode/nexus/pipeline"),
45321
45337
  import("@cleocode/core/internal"),
@@ -45395,7 +45411,7 @@ var init_nexus4 = __esm({
45395
45411
  extensions: { duration_ms: durationMs }
45396
45412
  }
45397
45413
  );
45398
- void getProjectRoot33;
45414
+ void getProjectRoot34;
45399
45415
  } catch (err) {
45400
45416
  const msg = err instanceof Error ? err.message : String(err);
45401
45417
  cliError(
@@ -52829,8 +52845,8 @@ var init_session4 = __esm({
52829
52845
  "audit-scope": { type: "string", description: "Audit log scope (global|local)" }
52830
52846
  },
52831
52847
  async run({ args }) {
52832
- const { detectSessionDrift, getProjectRoot: getProjectRoot33 } = await import("@cleocode/core");
52833
- const projectRoot = await getProjectRoot33();
52848
+ const { detectSessionDrift, getProjectRoot: getProjectRoot34 } = await import("@cleocode/core");
52849
+ const projectRoot = await getProjectRoot34();
52834
52850
  const scope = args["audit-scope"] === "local" ? "local" : "global";
52835
52851
  const report = await detectSessionDrift({ projectRoot, auditScope: scope });
52836
52852
  cliOutput(report, { command: "session drift", operation: "session.drift" });
@@ -55243,11 +55259,13 @@ var init_upgrade = __esm({
55243
55259
  // packages/cleo/src/cli/commands/verify.ts
55244
55260
  var verify_exports = {};
55245
55261
  __export(verify_exports, {
55262
+ backfillCommand: () => backfillCommand3,
55246
55263
  verifyCommand: () => verifyCommand3
55247
55264
  });
55248
55265
  import { spawnSync as spawnSync2 } from "node:child_process";
55249
55266
  import { existsSync as existsSync14 } from "node:fs";
55250
55267
  import { join as join22, resolve as resolve6 } from "node:path";
55268
+ import { generateVerifierStub, getProjectRoot as getProjectRoot33, writeVerifierStub } from "@cleocode/core";
55251
55269
  function resolveVerifierScript2(taskId, projectRoot) {
55252
55270
  const id = taskId.toLowerCase();
55253
55271
  const candidates = [
@@ -55269,12 +55287,173 @@ function runVerifier(verifierPath) {
55269
55287
  stderr: result.stderr ?? ""
55270
55288
  };
55271
55289
  }
55272
- var verifyCommand3;
55290
+ async function backfillSingle(taskId, projectRoot, force) {
55291
+ const response = await dispatchRaw("query", "tasks", "show", { taskId });
55292
+ if (!response.success) {
55293
+ process.stderr.write(
55294
+ `Error: could not fetch task ${taskId}: ${response.error?.message ?? "unknown error"}
55295
+ `
55296
+ );
55297
+ process.exitCode = 1;
55298
+ return;
55299
+ }
55300
+ const task = response.data?.task;
55301
+ if (!task) {
55302
+ process.stderr.write(`Error: task ${taskId} not found.
55303
+ `);
55304
+ process.exitCode = 1;
55305
+ return;
55306
+ }
55307
+ const existing = resolveVerifierScript2(taskId, projectRoot);
55308
+ if (existing && !force) {
55309
+ process.stderr.write(
55310
+ `Error: verifier already exists: ${existing}
55311
+ Use --force to overwrite. (T9218 idempotency guard)
55312
+ `
55313
+ );
55314
+ process.exitCode = 1;
55315
+ return;
55316
+ }
55317
+ try {
55318
+ const source = generateVerifierStub(
55319
+ task
55320
+ );
55321
+ const outPath = writeVerifierStub(taskId, source, projectRoot, force);
55322
+ process.stdout.write(`Generated: ${outPath}
55323
+ `);
55324
+ process.stdout.write(
55325
+ `
55326
+ Next steps:
55327
+ 1. Replace each \`fail('STUB \u2014 ...')\` block with a real check.
55328
+ 2. Verify manually: node ${outPath}
55329
+ 3. When the script exits 0: cleo verify ${taskId} --acceptance-check
55330
+ `
55331
+ );
55332
+ } catch (err) {
55333
+ const msg = err.message ?? String(err);
55334
+ process.stderr.write(`Error generating verifier for ${taskId}: ${msg}
55335
+ `);
55336
+ process.exitCode = 1;
55337
+ }
55338
+ }
55339
+ async function backfillAllPending(projectRoot, force) {
55340
+ const seen = /* @__PURE__ */ new Set();
55341
+ const pending = [];
55342
+ const queries = [
55343
+ dispatchRaw("query", "tasks", "list", { priority: "critical", limit: 200 }),
55344
+ dispatchRaw("query", "tasks", "list", { size: "large", limit: 200 }),
55345
+ dispatchRaw("query", "tasks", "list", { type: "epic", limit: 200 })
55346
+ ];
55347
+ const results = await Promise.all(queries);
55348
+ for (const response of results) {
55349
+ if (!response.success) continue;
55350
+ const tasks = response.data?.tasks ?? [];
55351
+ for (const t of tasks) {
55352
+ const id = String(t.id ?? "");
55353
+ if (!id || seen.has(id)) continue;
55354
+ seen.add(id);
55355
+ pending.push(t);
55356
+ }
55357
+ }
55358
+ const lacking = pending.filter((t) => {
55359
+ const id = String(t.id ?? "");
55360
+ return !resolveVerifierScript2(id, projectRoot);
55361
+ });
55362
+ if (lacking.length === 0) {
55363
+ process.stdout.write(
55364
+ "All critical/large/epic tasks already have verifier scripts. Nothing to do.\n"
55365
+ );
55366
+ return;
55367
+ }
55368
+ process.stdout.write(
55369
+ `Found ${lacking.length} task(s) lacking a verifier script. Generating stubs...
55370
+
55371
+ `
55372
+ );
55373
+ let succeeded = 0;
55374
+ let skipped = 0;
55375
+ let failed = 0;
55376
+ for (const task of lacking) {
55377
+ const id = String(task.id ?? "");
55378
+ try {
55379
+ const source = generateVerifierStub(
55380
+ task
55381
+ );
55382
+ const outPath = writeVerifierStub(id, source, projectRoot, force);
55383
+ process.stdout.write(` [OK] ${id} \u2192 ${outPath}
55384
+ `);
55385
+ succeeded++;
55386
+ } catch (err) {
55387
+ const msg = err.message ?? String(err);
55388
+ if (msg.includes("verifier already exists")) {
55389
+ process.stdout.write(
55390
+ ` [SKIP] ${id}: verifier already exists (use --force to overwrite)
55391
+ `
55392
+ );
55393
+ skipped++;
55394
+ } else {
55395
+ process.stderr.write(` [FAIL] ${id}: ${msg}
55396
+ `);
55397
+ failed++;
55398
+ }
55399
+ }
55400
+ }
55401
+ process.stdout.write(
55402
+ `
55403
+ Done: ${succeeded} generated, ${skipped} skipped (already exist), ${failed} failed.
55404
+ `
55405
+ );
55406
+ process.stdout.write(
55407
+ `
55408
+ Next steps for each generated file:
55409
+ 1. Replace each \`fail('STUB \u2014 ...')\` block with a real check.
55410
+ 2. node scripts/verify-<id>.mjs (must exit 0 before cleo complete)
55411
+ `
55412
+ );
55413
+ if (failed > 0) {
55414
+ process.exitCode = 1;
55415
+ }
55416
+ }
55417
+ var backfillCommand3, verifyCommand3;
55273
55418
  var init_verify = __esm({
55274
55419
  "packages/cleo/src/cli/commands/verify.ts"() {
55275
55420
  "use strict";
55276
55421
  init_dist();
55277
55422
  init_cli();
55423
+ backfillCommand3 = defineCommand({
55424
+ meta: {
55425
+ name: "backfill",
55426
+ description: "Auto-generate a verifier stub from AC text for a task lacking one (T9218 / ADR-070)"
55427
+ },
55428
+ args: {
55429
+ taskId: {
55430
+ type: "positional",
55431
+ description: "Task ID to generate a verifier stub for (e.g. T9213). Omit when using --all-pending.",
55432
+ required: false
55433
+ },
55434
+ "all-pending": {
55435
+ type: "boolean",
55436
+ description: "Process all critical/large/epic tasks that lack a verifier script (T9218)"
55437
+ },
55438
+ force: {
55439
+ type: "boolean",
55440
+ description: "Overwrite an existing verifier without error (idempotency override)"
55441
+ }
55442
+ },
55443
+ async run({ args, cmd }) {
55444
+ const projectRoot = getProjectRoot33();
55445
+ const force = !!args.force;
55446
+ if (args["all-pending"]) {
55447
+ await backfillAllPending(projectRoot, force);
55448
+ return;
55449
+ }
55450
+ if (!args.taskId) {
55451
+ await showUsage(cmd);
55452
+ return;
55453
+ }
55454
+ await backfillSingle(String(args.taskId), projectRoot, force);
55455
+ }
55456
+ });
55278
55457
  verifyCommand3 = defineCommand({
55279
55458
  meta: { name: "verify", description: "View or modify verification gates for a task" },
55280
55459
  args: {
@@ -55327,6 +55506,21 @@ var init_verify = __esm({
55327
55506
  await showUsage(cmd);
55328
55507
  return;
55329
55508
  }
55509
+ if (args.taskId === "backfill") {
55510
+ const remainingArgs = process.argv.slice(process.argv.indexOf("backfill") + 1);
55511
+ const taskIdArg = remainingArgs.find((a) => !a.startsWith("-"));
55512
+ const allPending = remainingArgs.includes("--all-pending");
55513
+ const force = remainingArgs.includes("--force");
55514
+ const projectRoot = getProjectRoot33();
55515
+ if (allPending) {
55516
+ await backfillAllPending(projectRoot, force);
55517
+ } else if (taskIdArg) {
55518
+ await backfillSingle(taskIdArg, projectRoot, force);
55519
+ } else {
55520
+ await showUsage(cmd);
55521
+ }
55522
+ return;
55523
+ }
55330
55524
  const acceptanceCheckRaw = args["acceptance-check"];
55331
55525
  const shouldRunAcceptanceCheck = acceptanceCheckRaw !== void 0 && acceptanceCheckRaw !== false;
55332
55526
  if (shouldRunAcceptanceCheck) {
@@ -56890,7 +57084,7 @@ async function runStartupMaintenance() {
56890
57084
  detectAndRemoveStrayProjectNexus,
56891
57085
  getGlobalSalt,
56892
57086
  getLogger: getLogger17,
56893
- getProjectRoot: getProjectRoot33,
57087
+ getProjectRoot: getProjectRoot34,
56894
57088
  isCleanupMarkerSet,
56895
57089
  migrateSignaldockToConduit,
56896
57090
  needsSignaldockToConduitMigration,
@@ -56899,7 +57093,7 @@ async function runStartupMaintenance() {
56899
57093
  } = await import("@cleocode/core/internal");
56900
57094
  let projectRootForCleanup = "";
56901
57095
  try {
56902
- projectRootForCleanup = getProjectRoot33();
57096
+ projectRootForCleanup = getProjectRoot34();
56903
57097
  } catch {
56904
57098
  }
56905
57099
  if (!isCleanupMarkerSet(CLI_VERSION, projectRootForCleanup)) {
@@ -56919,7 +57113,7 @@ async function runStartupMaintenance() {
56919
57113
  const isInitInvocation = process.argv.slice(2).some((a) => a === "init");
56920
57114
  if (!isInitInvocation) {
56921
57115
  try {
56922
- const _projectRootForMigration = getProjectRoot33();
57116
+ const _projectRootForMigration = getProjectRoot34();
56923
57117
  if (needsSignaldockToConduitMigration(_projectRootForMigration)) {
56924
57118
  const migrationResult = migrateSignaldockToConduit(_projectRootForMigration);
56925
57119
  if (migrationResult.status === "failed") {