Releases: kryptobaseddev/cleo
v2026.5.15
CI has been red since v2026.5.12 due to two test-infrastructure issues finally root-caused and fixed in T1731. After this release: pnpm run test reports 12366 passed, 0 failed across 748 test files (vs ~26 failing before).
T1731 (epic T1730) — fix CI flakes
Root cause #1 — vitest hijacks console.log/console.error (17 nexus-projects-clean failures): Vitest reroutes console.* methods to its own reporter, so test mocks of process.stdout.write / process.stderr.write never see CLI output. cliOutput and cliError in packages/cleo/src/cli/renderers/index.ts were emitting via console.log/console.error. Fix: switched the four emission sites in cliOutput (field-extracted primitive, human-mode rendered text, JSON envelope) and cliError (human stderr line, JSON envelope) to process.stdout.write(s + '\n') / process.stderr.write(s + '\n'). Five other test files that were spying on console.* also updated (cli-output-flags, cli-error-signature, audit-clioutput, nexus-clioutput, restore-finalize).
Root cause #2 — FORCE_COLOR=1 in CI (7 brain-renderers snapshot mismatches): GitHub Actions runners set FORCE_COLOR=1. The colors.ts module determines colorsEnabled at module-load time from FORCE_COLOR/NO_COLOR/stdout.isTTY. With colors enabled, ANSI escape codes leak into rendered output but saved snapshots have no ANSI codes. Fix: added env: { NO_COLOR: '1', FORCE_COLOR: '0' } to the test: block in root vitest.config.ts so renderers always emit deterministic plain text under vitest. (The default GitHub Actions environment is unchanged; only the test runner is fixed.)
Bonus fixes shipped in T1731:
mental-model.test.ts > consolidate > enforces token cap dropping oldest first— fixed by switching from hardcoded April 2026 dates to relative timestamps (the previous absolute dates fell outside the consolidation cutoff window after the calendar advanced).nexus-projects-clean.test.ts—invokeCleannow sets the format context per--jsonflag;error.codeNameexpectations re-aligned with the LAFS envelope shape.nexus-projects-clean-previewrenderer registered inpackages/cleo/src/cli/renderers/index.ts(was missing from the registry).@cleocode/caampadded to vitest aliases.
CI green check
pnpm biome ci .cleanpnpm run typecheckcleanpnpm run buildcleanpnpm run test— 748 test files passed, 0 failed; 12366 tests passed, 21 skipped, 35 todoFORCE_COLOR=1 pnpm vitest run packages/cleo/src/cli/renderers/__tests__/brain-renderers.test.ts— 32/32 (simulates CI)
v2026.5.14
Four parallel followups completed and merged in one orchestrated batch (T1718, T1719, T1728, T1729). All four task branches integrated via git merge --no-ff per ADR-062, preserving original commit SHAs and authorship.
T1728 — biome lint hard-block on raw stdout outside renderers (W4.F followup)
Added lint/suspicious/noConsole as a repo-wide error-level rule to biome.json. The rule blocks console.log in all files scanned by biome. Two exemption layers are in place:
- Renderer allowlist:
packages/cleo/src/cli/renderers/**andpackages/cleo/src/cli/help-renderer.tsare explicitly exempted — these are the approved output sinks for CLI rendering. - Legacy suppression: 8 packages with pre-existing violations (
adapters,caamp,cant,cleo-os,cleo,core,lafs,nexus) andscripts/**havenoConsole: "off"overrides pending full T1729 cleanup. New code added to packages NOT in this list (e.g.brain,mcp-adapter,agents,playbooks) will failpnpm biome ci ..
Note on process.stdout.write: biome has no built-in rule to block raw process.stdout.write. Detection of this pattern requires a custom plugin or manual review until biome adds support. The LAFS-compliance guardrail for process.stdout.write remains a code-review responsibility until then.
T1729 — migrate audit and schema CLI commands to cliOutput (W4.G followup)
Continued W4 LAFS-compliance migration. Two more CLI commands now route through the cliOutput renderer pipeline instead of writing raw stdout:
packages/cleo/src/cli/commands/audit.ts— replaced 2 rawprocess.stdout.writecalls withcliOutput()andcliError(). Both--jsonand human paths now route throughcliOutput('audit-reconstruct', ...).packages/cleo/src/cli/commands/schema.ts— removed inlinerenderSchemaHuman()function and directconsole.logbypass for--format=human. Now callssetFormatContext()then routes throughcliOutput('schema', ...).packages/cleo/src/cli/renderers/system.ts— addedrenderAuditReconstruct()andrenderSchemaCommand()human renderers.packages/cleo/src/cli/renderers/index.ts— registeredaudit-reconstructandschemakeys.packages/cleo/src/cli/help-renderer.ts— annotated--helpconsole.log asSSoT-EXEMPT(help text output is not subject to LAFS envelope requirements per ADR-039).- New tests:
audit-clioutput.test.ts(12 assertions) plus updatedschema.test.ts(16 assertions).
T1719 — reconcile SpawnContext / Wave / LifecycleHistoryEntry shape divergence (W3.E followup)
T1717 had documented legitimate structural divergence between contracts and core for three orchestration types. T1719 reconciles them so @cleocode/contracts is canonical for each:
Wave—packages/contracts/src/operations/orchestrate.tsupdated to match the core shape:wave → waveNumber,taskIds → tasks, droppedcanRunParallel/dependenciesin favor ofstatus. (Commit21de3c3cd.)SpawnContext— core's internal-onlySpawnContextrenamed toOrchestratorSpawnContextto free the canonical name for the cross-package contracts type. (Commit5d957b614.)LifecycleHistoryEntry—packages/contracts/src/operations/lifecycle.tsupdated to match the core shape (richer field set includingbyAgent,evidenceRefs,note). (Commit35a3c8bd6.)
All callers updated. Typecheck + build + test green for the affected paths.
T1718 — fix epic-enforcement and pipeline-stage CI test flakes
Two pre-existing test flakes that had caused multiple wave releases to ship with intermittent red CI. Both root-caused to real production bugs (not just test isolation):
epic-enforcementflake —initLoomForEpic(fire-and-forget call insideaddTask) calledrecordStageProgresswithstage='research', which unconditionally overwrotetasks.pipeline_stagefor the epic — rolling back an epic explicitly created at a later stage (e.g.implementation) toresearch. Fix:recordStageProgressnow only updatestasks.pipeline_stagewhen the new stage order is>=the current stage order (forward-only, never regress).pipeline-stageflake —transaction()inpackages/core/src/store/sqlite-data-accessor.tscaptured_nativeDbviagetNativeTasksDb()BEFOREawait getDb(cwd), opening a window where another async cleanup could close that DB instance and leave a stale closed reference. Fix:await getDb(cwd)first, then capture the native DB reference.- Test isolation hardening —
epic-enforcement.test.tsandpipeline-stage.test.tsnow setprocess.env['CLEO_DIR']inbeforeEachand clear it inafterEach, matching the pattern used by other tests that touchCLEO_DIR.
Verified 10x passes locally on each target test with the full tasks/__tests__ suite running concurrently. Net repo-wide test impact: 17 fewer failing tests vs the v2026.5.13 baseline (regression count: 0).
v2026.5.13
W5 (T1692) — final wave of T-CSL-RESET. 3 atomic children completed bringing the public @cleocode/core SDK surface to parity with the cleo --json CLI output.
W5 children (T1725–T1727)
- T1725 (W5.A) —
unwrap()helper — Addedunwrap<T>(result: EngineResult<T>): Tto@cleocode/core. Public consumers using the SDK can writeconst data = unwrap(await someOp())and get a familiar throw-style API. ThrowsCleoError-shaped error on failure (preservescode/message/exitCode/details/fix/alternatives/problemDetails). Internal code keeps the discriminatedEngineResult<T>union for narrowing. - T1726 (W5.B) — sentient + release ops registered — Added
OperationSpecentries for all sentient subcommands and all release subcommands to the publicOPERATIONSregistry. Audit-E found these were reachable viacleoCLI but invisible to public SDK consumers. - T1727 (W5.C) — release/engine-ops.ts side-effect cleanup — Removed
console.logstep-progress writes frompackages/core/src/release/engine-ops.ts. Routed throughgetLogger('release')with structured fields. Stdout is now clean when consumed via the SDK.
W5 acceptance gates
- ✅ pnpm run typecheck clean (CI parity —
tsc -bstrict project references) - ✅ pnpm biome ci . clean
- ✅ pnpm run build clean (full monorepo)
T-CSL-RESET COMPLETE
This release marks the final wave of T-CSL-RESET (T1685). The 5-wave epic took 10 patch releases (v2026.5.4 → v2026.5.13) and addressed 3 foundational defects identified by the 5 parallel audits on 2026-05-01:
- ✅ W1 (v2026.5.4) — Contracts canonicalization (zero internal conflicts, schema emission, LAFS unified, all 18 domains in barrel)
- ✅ W2 (v2026.5.5–5.7) — EngineResult unification (single canonical shape, RFC 7807
problemDetails, 5 duplicates consolidated, round-trip field-loss fix) - ✅ W3 (v2026.5.10) partial — 4 of 5 type families migrated to contracts SSoT (13 duplications removed). T1719 followup filed for shape divergence.
- ✅ W4 (v2026.5.11–5.12) — 5 highest-impact CLI commands migrated to LAFS-compliant
cliOutput()(~511 raw stdout writes eliminated). T1728 followup filed for biome lint hard-block. T1729 followup filed for remaining 8 commands. - ✅ W5 (v2026.5.13) — SDK surface parity (
unwrap()helper, sentient + release ops in registry, release side-effects removed)
Sandbox baseline: 4/7 → 7/7 PASS across the wave releases. The 3 sandbox-related bugs discovered during validation (pre-commit hook ADR-013 contradiction, T1609 trigger SQLite syntax, scenario read-only filesystem) all fixed in CLEO core.
Followups filed
- T1718 — Pre-existing CI flakes (epic-enforcement.test.ts, pipeline-stage.test.ts)
- T1719 — W3.E shape-divergence reconciliation
- T1728 — W4.F biome lint hard-block rule
- T1729 — W4.G remaining 8 CLI commands
v2026.5.11
W4 (T1691) wave 1: 5 atomic children completed. ~511 raw process.stdout.write / console.log calls migrated to cliOutput() across the 5 highest-impact CLI command files. Every migrated command now produces a LAFS-conformant envelope on --json and routes through the human renderer for --human.
Migrations (T1720–T1724)
- T1720 (W4.A) — nexus.ts — 218 raw writes migrated. 30 new human renderer functions in
packages/cleo/src/cli/renderers/nexus.ts(1039 LOC); 18 snapshot/output tests added. Largest single migration in the wave. - T1721 (W4.B) — memory.ts — 96 raw writes migrated. Snapshot tests added for representative subcommands.
- T1722 (W4.C) — brain.ts — 77 raw writes migrated. 6 new brain renderer functions registered (
brain-maintenance,-backfill,-purge,-plasticity-stats,-quality,-export). - T1723 (W4.D) — transcript.ts — 43 raw writes migrated.
- T1724 (W4.E) — daemon.ts + sentient.ts + gc.ts — remaining raw writes across 3 files migrated.
Wave 4 acceptance gates
- ✅ pnpm run typecheck clean (CI parity —
tsc -bstrict project references) - ✅ pnpm biome ci . clean
- ✅ pnpm run build clean (full monorepo)
- ✅ ~511 raw stdout writes eliminated across 5 CLI command files
Outstanding W4 work (followup)
- biome lint hard-block rule (
no-raw-stdout-outside-renderers) — gates regression at lint time. Filed as W4.F followup. - Remaining 8 CLI commands (
help-renderer,schema.ts,audit.ts, etc.) below the top-5 — filed as W4.G followup.
v2026.5.10
W3 (T1690) wave 1: 4 of 5 atomic children completed. Net effect: 13 type duplications removed across 4 type families. The 5th child (T1717) returned "partial" with legitimate shape divergence — followup tracked at T1719.
Type-family migrations (T1713-T1716)
- T1713 (W3.A) — TaskRole/TaskScope/TaskSeverity — Drizzle schema in
core/store/tasks-schema.tsnow imports from@cleocode/contracts;TASK_ROLES/TASK_SCOPES/TASK_SEVERITIESconst arrays retained for column enum narrowing. 3 type duplications removed. - T1714 (W3.B) — StickyNote types —
core/sticky/types.tsnow re-exportsStickyNoteStatus/StickyNotePriority/StickyNoteColor/StickyConvertResultfrom@cleocode/contracts/operations/sticky. 4 type duplications removed. - T1715 (W3.C) — Brain memory schema types —
core/store/memory-schema.tsnow importsBrainMemoryTier/BrainCognitiveType/BrainSourceConfidencefrom@cleocode/contracts/brain. 3 duplications removed (BrainNodeType found shape-divergent and left for followup). - T1716 (W3.D) — LLM types —
core/llm/types-config.tsandcore/llm/types.tsnow importModelTransport/ModelConfig/PromptCachePolicy/PromptCachePolicyMode/LLMCallResultfrom@cleocode/contracts/operations/llm. 5 duplications removed.
Partial / followup (T1717 → T1719)
T1717 (W3.E) found that SpawnContext, Wave, and LifecycleHistoryEntry have legitimate structural divergence between contracts and core (different field names, different shapes). Direct import-replace would break tests. T1717 cancelled, followup filed as T1719 for proper rename-side reconciliation.
Wave 3 acceptance gates
- ✅ pnpm run typecheck clean (CI parity —
tsc -bstrict project references) - ✅ pnpm biome ci . clean
- ✅ pnpm run build clean (full monorepo)
- ✅ 13 type duplications removed across 4 type families
⚠️ T1717's 3 types deferred to T1719 (shape divergence requires rename, not just dedup)
Followups filed
- T1718 — Pre-existing CI flakes (
epic-enforcement.test.ts,pipeline-stage.test.ts) - T1719 — W3.E shape-divergence reconciliation (SpawnContext / Wave / LifecycleHistoryEntry)
v2026.5.9
Sandbox jumps from 5/7 → 7/7 PASS. Both remaining living-brain-e2e and sentient-anomaly-proof failures traced to a single root cause: the T1609 migration created a SQLite trigger with || string concatenation in RAISE(ABORT, msg). SQLite expects a STRING LITERAL there — the concatenation expression caused malformed database schema errors when ANY tool other than the creating connection (e.g. the sqlite3 CLI used by sandbox assertions) opened the database.
Bug
packages/core/migrations/drizzle-tasks/20260429000000_t1609-handoff-append-only/migration.sql:
CREATE TRIGGER trg_session_handoff_no_update
BEFORE UPDATE ON session_handoff_entries
FOR EACH ROW
BEGIN
SELECT RAISE(
ABORT,
'T1609_HANDOFF_IMMUTABLE: ... '
|| 'session_id=' || OLD.session_id || ').'
);
END;node:sqlite (used by CLEO) accepted the trigger creation but the persisted SQL stored in sqlite_schema couldn't be re-parsed by other SQLite consumers. Sandbox assertions ran sqlite3 .cleo/tasks.db 'SELECT COUNT(*) FROM tasks' and got Error: in prepare, malformed database schema (trg_session_handoff_no_update) - near "||": syntax error (11) → COUNT returned 0 → assertion tasks.db: at least 1 task created failed even though tasks DID exist.
Fix
New migration 20260503000000_t1718-handoff-trigger-syntax-fix: drops the broken trigger and recreates it with a static string literal (no dynamic OLD.session_id interpolation in the abort message). Existing databases self-heal on next cleo init / migration run; new installs get the fixed trigger from the start.
Sandbox impact
- v2026.5.7 baseline: 4/7 PASS
- v2026.5.8 (pre-commit hook fix): 5/7 PASS
- v2026.5.9 (this release, trigger syntax fix): 7/7 PASS expected
v2026.5.8
Sandbox baseline jumped from 4/7 → 6/7 after this release. Two of the three "pre-existing" sandbox failures (harness-e2e, living-brain-e2e) were caused by CLEO's own pre-commit hook contradicting ADR-013 §9.
Bug
ADR-013 §9 (T5158, 2026-04-07) states that tasks.db, brain.db, config.json, and project-info.json MUST NOT be tracked in git — they're regenerated by cleo init and backed up via VACUUM INTO snapshots. Re-tracking them in git re-opens the data-loss vector (SQLite WAL/JSON state desync on branch switch).
The .cleo/.gitignore template correctly ignores all four files. But packages/core/templates/git-hooks/pre-commit had a stale check from before T5158:
PROTECTED_FILES=".cleo/config.json .cleo/.gitignore .cleo/project-info.json .cleo/project-context.json"
# ... fails commit if any PROTECTED_FILES are gitignoredResult: cleo init succeeded, then any git commit exited 1 with "Critical CLEO files are being ignored by .gitignore" — exactly the files T5158 says SHOULD be ignored.
Fix
packages/core/templates/git-hooks/pre-commit: Removedconfig.jsonandproject-info.jsonfromPROTECTED_FILES(they should be ignored per ADR-013 §9)..cleo/.gitignoreandproject-context.jsonretained — those are intended to be tracked.- Added
Section 3to the hook: positively block staging of.cleo/{tasks.db,brain.db,config.json,project-info.json}(the T5158 anti-pattern). This makes the hook align with ADR-013 §9 in both directions: don't require the files to be tracked, but actively reject any attempt to track them.
Sandbox impact
Before v2026.5.8 (on v2026.5.7): 4/7 PASS — corrupted-db-recovery, fresh-install-linux, multi-project-registry, upgrade-from-legacy-dotcleo. Failures: harness-e2e, living-brain-e2e, sentient-anomaly-proof.
After v2026.5.8: 6/7 expected — pre-commit fix unblocks harness-e2e + living-brain-e2e. Remaining sentient-anomaly-proof failure is a scenario-side bug (writes run.log to read-only /sandbox-bin/ instead of $SANDBOX_ARTIFACT_DIR) — fixed in the cleo-sandbox repo, not this release.
v2026.5.7
Hotfix on hotfix. v2026.5.6 closed 12 type errors locally but CI's Type Check job still failed on a pre-existing issue:
packages/contracts/src/lafs.ts:35,142 — Cannot find module '@cleocode/lafs'
W1 (T1706) added a re-export of LAFS types from @cleocode/lafs into packages/contracts/src/lafs.ts, but packages/contracts/tsconfig.json did not declare @cleocode/lafs as a project reference. Locally the dist existed (built by prior pnpm run build); CI's pnpm run typecheck (just tsc -b) on a fresh checkout couldn't resolve it.
Fix
packages/contracts/tsconfig.json: Addedreferences: [{ "path": "../lafs/tsconfig.build.json" }]sotsc -bbuilds@cleocode/lafsbefore contracts.
CI-parity verification
rm -rf packages/*/dist
find packages -name "*.tsbuildinfo" -delete
pnpm run typecheck # exit 0 — no dist, no tsbuildinfo, fresh tsc -b
pnpm run build # exit 0
v2026.5.6
Hotfix for v2026.5.5. Wave 2 closed multiple typecheck regressions that local pnpm run build (esbuild) missed but CI's tsc -b (project-references, strict) caught:
packages/cleo/src/dispatch/engines/_error.ts— localengineErrorwrapper signature missingexitCodeandproblemDetailsoptions. T1708 added the wiring but didn't extend the local wrapper'soptionstype. Fixed: extended options to includeexitCode(carried through) andproblemDetails(forwarded to canonical coreengineError).packages/cleo/src/dispatch/domains/nexus.ts—nexusQueryEnvelopeToResponseandnexusMutateEnvelopeToResponseconstructed inline{ success: env.success, ... }objects withsuccess: boolean(widened literal). T1709's switch to@cleocode/core's discriminatedEngineResult<T>union no longer accepts the widened type. Fixed: route throughenvelopeToEngineResulthelper from_base.ts.packages/cleo/src/dispatch/domains/orchestrate.ts— 7wrapResult(await coreOps.X(p), ...)call sites with widenedsuccess: booleanreturns from inline-literal-returning op functions. Fixed: explicitas EngineResult<unknown>cast at each call site (structurally compatible; cast preserves intent without churning 11 inline-literal patterns).
Hotfix acceptance gates (all green)
- ✅
pnpm run typecheckclean (tsc -bstrict project references — same as CI) - ✅
pnpm biome ci .clean - ✅
pnpm run buildclean (full monorepo)
Lesson (filed in memory)
pnpm run build uses esbuild and skips strict TypeScript project-reference type checks. pnpm run typecheck (tsc -b) is the actual CI gate. ALWAYS run pnpm run typecheck before tagging — not just pnpm run build.
v2026.5.5
Second wave of T-CSL-RESET. Eliminates the parallel-shape divergence between cleo's local EngineResult interface and @cleocode/core's canonical type, activates RFC 7807 problem-details across the error path, consolidates 5 duplicate envelopeToEngineResult copies into one canonical helper, and fixes the silent field-loss bug across the EngineResult ↔ LafsEnvelope ↔ DispatchResponse round-trip.
R1 ACTIVATE — RFC 7807 problem details (T1707, T1708)
- T1707: Added optional
problemDetails?: ProblemDetailsfield to@cleocode/core'sEngineErrorPayload. Reused existing RFC 9457ProblemDetailstype fromerrors.tsrather than duplicating. Foundation task — additive, zero breaking impact. - T1708: Wired
problemDetailsincleoErrorToEngineError()(single-point activation). Every CleoError now carries RFC 7807-compliant fields:type(namespace URI),title(codeName),status(exitCode),detail(message),instance(requestId from meta). 6 new round-trip tests verify full propagation.
Single canonical EngineResult (T1709)
- T1709: DELETED the parallel
interface EngineResult<T>inpackages/cleo/src/dispatch/domains/_base.ts. Now imports from@cleocode/coreand re-exports for backwards compatibility.wrapResult()rewritten to use the canonical discriminated-union type so TypeScript narrowsdata/errorcorrectly. All field shapes from the deleted local interface covered by core'sEngineResult/EngineErrorPayload.
Helper consolidation (T1710, T1711)
- T1710: Extracted canonical
envelopeToEngineResultto_base.ts; removed local copies fromadmin.tsandconduit.ts. - T1711: Removed local copies from
sentient.ts,session.ts, andtasks.ts. Helper supportsLAFSPagefor pagination.
Round-trip field-loss fix (T1712)
- T1712: Canonical
envelopeToEngineResultin_base.tsnow preservesexitCode,details,fix,alternatives, andproblemDetailsacross the LafsEnvelope hop (previously silently dropped).wrapCoreResultintyped.tsupdated to propagate fields onto the LafsError object so they survive the round-trip. Newround-trip-fields.test.tsadds 12 assertions covering the full EngineResult → LafsEnvelope → EngineResult → DispatchResponse pipeline.
Wave 2 acceptance gates (all green)
- ✅ Only one
EngineResult<T>in source (cleo_base.tsinterface DELETED, re-export retained) - ✅ R1 ACTIVATE implemented —
problemDetailspopulated incleoErrorToEngineError() - ✅ 5 duplicate
envelopeToEngineResultcopies consolidated into one canonical helper in_base.ts - ✅ Field-loss bug fixed —
exitCode/details/fix/alternatives/problemDetailspreserved through round-trip - ✅ Round-trip lossless verified by
round-trip-fields.test.ts(12 assertions) - ✅
pnpm biome ci .clean - ✅
pnpm run buildclean (full monorepo) - ✅ Test suite: 12249 passed / 21 skipped / 35 todo (1 pre-existing flake in
pipeline-stage.test.ts"database is not open" — unrelated to W2; W2 doesn't touch tasks/store paths)
Next: Wave 3 (T1690) — Migrate cleo inline types to contracts
Will land as v2026.5.6. 10 cleo dispatch types migrate to contracts; 15+ contracts coverage gaps filled (HealthReport, BackfillResult, retry types, etc.); 88 contracts+core type duplicates removed.