Releases: kryptobaseddev/cleo
v2026.4.154
Highlights
Comprehensive overnight orchestration campaign with 4 dispatch waves + 10-teammate domain audit + V1-V5 release validation. Net: 60+ commits across architecture cleanup, governance pumps, audit-driven fixes, and pre-release polish.
Key fixes
- fix(memory): wire
cleo memory sweep --rollbackdispatch routing (T1496/P0-1) - fix(lifecycle): defensive guard for undefined
gateNameinpassGate/failGate+ 7 pipeline.integration tests fixed (T1497/P0-4) - feat(verification): per-session
CLEO_OWNER_OVERRIDEcap +--shared-evidenceflag for batch closes + ADR-059 (T1501+T1502/P0-5+P0-6) - feat(verification): raise default override cap 3→10 + worktree-context exemption (T1504)
- feat(orchestrate): worktree leak auto-cleanup +
cleo orchestrate pruneCLI (T1462) - fix(paths):
getProjectRootrejects.cleocandidates lacking sibling.git(T1463) - feat(tasks): epic closure requires direct evidence or all children verified-done (T1404)
- refactor(dispatch): 6 remaining fat handlers thinned to ≤5 LOC per ADR-058 (T1492 — T-THIN-WRAPPER feature-complete)
- fix(reconciliation):
sync:${providerId}colon broke validateLabels regex — silently swallowed all reconciliation actions (T1530 silent data-corruption fix) - fix(dispatch): migrate docs.ts to TypedDomainHandler per ADR-058 (T1529)
- chore(orphans): scripted re-parent of 39 orphaned tasks (T1503)
- chore(audit): 10-teammate domain audit + master synthesis (T1520)
Pre-release polish (T1562)
- fix(readme): correct invalid scope example
- chore(core): add runtime guard to
./internalbarrel - fix(check): align
config.schema.jsonwith current config structure
Test suite
- Pre-existing failures: 12 → 0
- Test counts: 11507 → 11566 passing (708 test files)
Tooling
- ADR-058 OpsFromCore adoption: 12/18 dispatch domains compliant (8 follow-up tasks filed in T1555)
- Force-bypass governance pumps now LIVE (cap, shared-evidence, epic-closure-evidence)
v2026.4.153
Resolves the resource thrash and apparent memory leak observed when 10+ orchestrator-spawned worker subagents call cleo verify --evidence "tool:<name>" simultaneously across worktrees.
Fixed
- Apparent memory leak under parallel verify load.
validateToolpreviously accumulated the entire child stdout/stderr stream into JS strings on every'data'event. A vitest run emitting 50–200 MB of progress output sat resident per spawn, multiplied by N parallel verifies. NewTailBufferintool-cache.tscaps in-memory capture at 64 KB per stream per spawn. Cached evidence tail unchanged at 512 bytes. (T1534, ADR-061 §3) @cleocode/corepackage-boundary violation.evidence.tshardcoded apnpm/biome/tscTOOL_COMMANDStable, breaking the contract that core MUST be project-type agnostic. Newtool-resolver.tsreads.cleo/project-context.json(testing.command,build.command) with per-primaryTypefallbacks for node, python, rust, go, ruby, java, dotnet, bash, elixir, php, deno, bun. (T1534, ADR-061 §1)coreTestRun(validate.tests.run) hardcoded tonpx vitest run. Now routes through the same resolver —validate.tests.runworks on Python/Rust/Go projects without modification. (T1534)
Added
- Content-addressed result cache. Cache entries at
.cleo/cache/evidence/<key>.json, keyed on(canonical, cmd, args, git HEAD, dirty-tree fingerprint). Sibling verifies against the same state coalesce to one execution. Edits and new commits invalidate automatically; no GC daemon required. (T1534, ADR-061 §2) - Cross-process global per-tool concurrency semaphore. Slot directories at
~/.local/share/cleo/locks/tool-<canonical>/bound the total concurrent runs of a canonical tool across all worktrees and projects on the machine. Defaults:test/build= max(1, cpus/4);lint/typecheck/audit/security-scan= max(2, cpus/2). Override viaCLEO_TOOL_CONCURRENCY_<TOOL>=<n>(set0to disable). Stale-process recovery viaproper-lockfile10-min stale window. (T1534, ADR-061 §4) - Six canonical tool names for
tool:<name>evidence:test,build,lint,typecheck,audit,security-scan. Legacy aliases (pnpm-test,npm-test,cargo-test,pytest,vitest,jest,tsc,mypy,pyright,biome,eslint,prettier,ruff,clippy,pnpm-build,cargo-build,go-test,pnpm-audit,cargo-audit, …) continue to resolve and remain re-validatable. - ADR-061 — Project-Agnostic Evidence Tools + Cross-Process Result Cache.
Real-world load-test results (24-core / 64 GB box)
- 10 worktrees, 2-slot semaphore, 5 MB stdout each: max 2 children, 24 MB heap growth, all tails bounded at 512 bytes.
- 20 worktrees, default 6 slots, 10 MB each (400 MB streamed total): max 6 children, 67 MB heap growth.
- 10 independent Node PIDs sharing
CLEO_HOME: 4 perfect serialised waves of 3 — proves the cross-process bound holds across PIDs, not just in-process. - 20 same-repo parallel verifies: 1 spawn, 19 cache hits.
Backwards compatibility
EvidenceToolwidened from union tostring— strict superset of the old union, no caller breaks.TOOL_COMMANDSretained asObject.freeze({})for any destructure consumers; deprecated, new code MUST callresolveToolCommand.- All stored evidence atoms (including pre-T1534 audit trails) remain re-validatable via the alias map.
Tests
112/112 across 5 new/extended suites (resolver + cache + semaphore + evidence + injection-mvi-tiers); 1997/1997 in @cleocode/cleo downstream suite; full workspace build green; pnpm biome ci . clean.
v2026.4.152
The T-THIN-WRAPPER campaign + T-SDK-PUBLIC follow-up shipped 46 commits across two epics. Goal: turn @cleocode/cleo into a thin transport over @cleocode/core (the SDK) and @cleocode/contracts (canonical wire-format SSoT).
What shipped
T-THIN-WRAPPER (T1467) — 13 subtasks
- Lint script L4 wildcard re-export shortcut fixed (T1469)
- Core index namespace exports for check/session/playbook + sentient/gc/llm (T1470, T1483)
- 17 type duplicates dedup'd from Core/cleo into contracts (T1471)
- Canonical CLI tasks layer with alias normalization (T1472)
- All 9 dispatch domains use
OpsFromCore<typeof coreOps>inference (T1437/T1438/T1439/T1440/T1441/T1442/T1443/T1444/T1445) - Redundant per-op contract type aliases stripped (T1446 — pipeline.ts -244 LOC, tasks.ts -299 LOC)
- ADR-058 dispatch-type-inference authored (T1447)
- biome rule + regression test prevent inline type drift (T1448)
- nexus.ts CLI decomposed (T1473 — 5366 → 4084 LOC, 9 new core/nexus files)
- Engine type duplicates removed (T1482)
- 57 dispatch handlers thinned via wrapCoreResult helper (T1484)
- 79 more dispatch handlers thinned in tasks/playbook/nexus (T1487 — 61-70% body LOC reduction)
- Nexus CLI bypass paths routed through dispatch (T1488)
- Session dispatch param aliases sole-sourced via contracts (T1489)
- add.ts CLI inference moved to Core inferTaskAddParams (T1490)
T-SDK-PUBLIC (T948) — 5 deliverables
- @cleocode/core publish surface hardened (files allowlist excludes 13MB src)
- @cleocode/contracts public type surface README documenting XOps pattern
- @cleocode/core SDK README with runnable quickstart
- TypeScript .d.ts declaration cleanliness verified (zero internal leaks)
- forge-ts @example doctests on 10 public Core fns
Critical bug fixes after validation
build.mjssharedExternals regression (introduced v2026.4.141): added openai/google-genai/anthropic-sdk to externals — fresh npm installs were crashing with "Dynamic require of stream" since v2026.4.148- conduit/ops.ts
declare consttype-only fixed (was crashing CLI at startup) - brain
sleep-consolidationSQLe.observation_id→e.id(matched vec0 schema) - TasksAPI.add() facade gained
acceptance?: string[] - README quickstart corrected (
addTasknottasksAddOp) cleo update --note(singular) alias regression test added
Adapter migrations to public SDK (T948 prereqs)
- MCP adapter (
@cleocode/mcp-adapter) migrated from CLI subprocess to direct@cleocode/core+@cleocode/contracts(T1485) - cleo-os decoupled from
@cleocode/cleobinary dep (T1486)
Quality gates
- pnpm exec tsc -b: exit 0
- pnpm biome ci .: exit 0 (1 pre-existing symlink warning)
- pnpm run build: exit 0
- pnpm run test: 11507 passing / 5 pre-existing failures (brain-stdp + sqlite-warning-suppress, unrelated to campaign)
- node scripts/lint-contracts-core-ssot.mjs --exit-on-fail: exit 0
- Validation matrix: V1 + V2-RERUN + V3 + V4 + V5 + FINAL re-run all GREEN
- Sandbox: 3/7 ubuntu, 4/7 fedora, 0 new regressions vs v2026.4.151
Codex audit progression
v2026.4.151
v2026.4.150 release tag pushed but CI Type Check failed on packages/cleo/src/dispatch/engines/lifecycle-engine.ts:207. The lifecycleStatus(epicId, projectRoot?) engine wrapper passed projectRoot?: string directly to getLifecycleStatus() which now requires projectRoot: string (per ADR-057 D1 in T1455). Fix mirrors the pattern used at line 195 (listRcsdEpics): projectRoot ?? process.cwd().
The release commit e950a57ad itself only touched package.json files and CHANGELOG.md; the type error was pre-existing on 5feda5140 (T1455 lifecycle callers fix-up) and slipped past local pnpm run build because tsc -b is the stricter CI gate.
This release re-ships the T1449 epic content under the v2026.4.151 tag with CI green.
Quality gates
pnpm exec tsc -bexit 0pnpm biome ci .cleanpnpm run buildexit 0pnpm run test11491 passingnode scripts/lint-contracts-core-ssot.mjs --exit-on-failexit 0
v2026.4.150
T1449 epic shipped. 9 dispatch domains (admin, check, conduit, nexus, pipeline, playbook, sentient, session, tasks) refactored so every Core function follows the uniform (projectRoot: string, params: <Op>Params): Promise<<Op>Result> signature per ADR-057 D1. Contract aliases (parentId/parent, kind/role/type, note/notes, focus/startTask) removed; CLI flag aliasing moved to the command layer per D2. Drift is now structurally impossible: changing a contract type breaks the Core signature at compile time, and scripts/lint-contracts-core-ssot.mjs enforces L1 (signature uniformity), L2 (no aliases in contracts), L3 (no dispatch normalization), and L4 (Core fns referenced by dispatch are SDK-public) via pre-commit hook and CI workflow.
Per-domain commits
- T1450 session:
af49ffb18(PROOF — 15 ops normalized) +a40abf979(internal caller fix-up) - T1451 admin: shipped in pre-T1449 batched rollout; 12 Core fns annotated
SSoT-EXEMPT:T1451-followupfor next pass (token-service, snapshot, adrs sync/validate) - T1452 check:
36ad4fc54 - T1453 conduit:
0f032cba5(vitest alias resolution) - T1454 nexus:
ceb30ed47(with backward-compat positional overloads retained; clean removal in follow-up) - T1455 pipeline:
ad6b49a9d+5feda5140(lifecycle caller fix-up) - T1456 playbook:
25b7b6628(SSoT-EXEMPT for db-handle internals) - T1457 sentient:
edfa04977(WIP-recovered, complete) - T1458 tasks:
651d4d199(Part A — Core ops.ts normalization) +8bc7baa15(Part B — parentId/kind/type alias removal) - T1459 ADR + lint gate:
b8b96249a(ADR-057 published) +a901f5c15(3 residual aliases resolved) +0361abdf9(pre-commit + CI workflow wire)
Architectural impact
Core becomes the SDK: external consumers (Studio, future MCP adapters, public SDK) can now import { sessionStart } from '@cleocode/core'; await sessionStart(projectRoot, params); against a uniform, stable surface. CLI becomes a thin transport: command files parse flags, normalize aliases, call Core — no business logic in the CLI layer. The lint gate catches drift at PR time rather than at runtime.
Quality gates
pnpm biome ci .— clean (1 pre-existing broken-symlink warning, not introduced this release)pnpm run build— exit 0pnpm run test— 11491 passing, zero new failures vs v2026.4.149 baselinenode scripts/lint-contracts-core-ssot.mjs --exit-on-fail— exit 0
Known follow-ups
- T1451 admin completion: 12
SSoT-EXEMPT:T1451-followupannotations remain; a dedicated pass will finish normalization of token-service, snapshot, and adrs sync/validate Core fns - T1454 nexus positional overloads: backward-compat positional signatures retained on Core fns; remove after CLI and tests fully use named-params form
- T1454 nexus dispatch form: handler uses
TypedDomainHandler<NexusOps>(T1424 form) rather thanOpsFromCore<typeof coreOps>(ADR-057 D3 form); both are valid per the ADR; migrate in a follow-up for full uniformity
Council verdict (2026-04-25)
5-advisor stress test (Contrarian, First Principles, Expansionist, Outsider, Executor) passed all rigor, evidence, and framing gates. Convergence: Core API uniformity is load-bearing infrastructure; the CI enforcement gate must come after per-domain audit, not before. Q1 (aliases policy) resolved as Option B — canonical SSoT in Contracts. Q2 (sequencing) resolved as normalize-first plus parallel execution across all 9 domains.
v2026.4.148
The v2026.4.147 push-CI failed on parity.test.ts > registry has the expected operation count because adding 3 new conduit topic ops bumped the total from 322 to 325 but the hardcoded assertion (expect(OPERATIONS.length).toBe(322)) still expected the old number. The Release workflow itself passed (npm publish succeeded for v2026.4.147), but the push-CI was red.
This release replaces the hardcoded count assertion with structural assertions that catch real regressions without manual maintenance:
OPERATIONS.length >= 300— catches mass-deletion / truncationqueryCount >= 150— catches gateway corruptionmutateCount >= 100— catches gateway corruptionqueryCount + mutateCount === OPERATIONS.length— no rogue gateway values- count of (gateway !== 'query' && gateway !== 'mutate') === 0
The other tests in parity.test.ts already enforce per-op invariants (valid gateway, non-empty domain/operation, required-param consistency, no duplicates). The hardcoded count was carrying 30+ comment lines tracking historical bumps (Phase 1 / W7a / T535 / T549 / T554 / T624 / T646 / T647 / T781 / T797 / T811 / T798 / T820 / T889 / T935 / T997 / T1006 / T1003 / T1061 / T1013 / T1115 / T1116 / T1117 / T1137 / T1076 / T1262 / T1261 / T1147 / T1386 / T1411). It was friction without value.
Quality gates
pnpm exec tsc -b— 0 errorspnpm biome ci .— 1942 files cleanpnpm run build— greenpnpm --filter @cleocode/cleo test -- --run parity— 1963 pass
v2026.4.147
User smoke-tested v2026.4.146 in production and discovered cleo conduit publish/subscribe/listen returned E_INVALID_OPERATION: Unknown operation: mutate:conduit.publish. The CLI commands were registered (visible in cleo conduit --help) and the dispatch handler implemented the methods at packages/cleo/src/dispatch/domains/conduit.ts:94,184,204, but the OPERATIONS_REGISTRY in packages/cleo/src/dispatch/registry.ts was missing the three corresponding entries. The CQRS validator rejected them as unknown ops before reaching the handler.
This hotfix adds the missing conduit.publish (mutate), conduit.subscribe (mutate), and conduit.listen (query) entries with their canonical param schemas. Verified end-to-end against a live publish→subscribe→listen flow:
$ cleo conduit publish --topic test-fix --payload '{"hello":"world"}'
{"success":true,"data":{"messageId":"278ed11b-...","from":"cleo-prime","topicName":"test-fix","transport":"local","publishedAt":"..."}}
$ cleo conduit listen --topic test-fix --agent cleo-prime --max 5
{"success":true,"data":{"topicName":"test-fix","messages":[{"id":"278ed11b-...","from":"cleo-prime","content":"{\"hello\":\"world\"}","conversationId":"test-fix","timestamp":"..."}],"listenedForMs":11}}
All three round-trip cleanly. The conduit-schema split (T1407-followup commit 7300e3eed) and migration-runner unification from v2026.4.145 are independently verified — only the dispatch routing was missing.
Quality gates (verified before release)
pnpm exec tsc -b— 0 errorspnpm biome ci .— 1942 files, 2 pre-existing warnings, 1 info; no errorspnpm run build— green- Live conduit topic publish/subscribe/listen flow against
.cleo/conduit.db— green
v2026.4.146
Lands the registry-driven cleo reconcile release post-release invariants gate. ADR-056 (D5) promoted T1411's scope from a single-purpose archiveReason hook to a generic post-release invariant registry where archiveReason reconciliation is customer #1 — Council Expansionist's sharpest single point. The same mechanism retires the entire class of drift bugs that ADR-054's six migration-manager patches paid for ad-hoc.
Closed in this release
- T1411 registry-driven
cleo reconcile releasepost-release invariants gate (PROMOTED scope per ADR-056 D5).
What changed
packages/core/src/release/invariants/registry.ts(NEW, 209 LOC):RegisteredInvarianttype,registerInvariant(spec),getInvariants(), andrunInvariants(tag, options)— the registry API. Side-effect import of./archive-reason-invariant.jsfrom./index.tsregisters the first customer at module load.packages/core/src/release/invariants/archive-reason-invariant.ts(NEW, 399 LOC): the first customer. Parses the tag annotation (git tag <tag> -l --format='%(contents)') plus every commit between the previous tag and the target tag forT\d+task IDs (subject + body). For each foundTxxx:- Pending task with
verification_jsonpopulated and gates passing → stampsstatus=done,archive_reason=verified,release=<tag>in one transaction. - Pending task with
verification_json=null→ createsT-RECONCILE-FOLLOWUP-<tag>-<idx>child task linked to the unreconciled task ID. - Tombstone safety: NEVER writes
completed-unverified(only the T1408 backfill migration may produce that value); attempting to do so throwsArchiveReasonTombstoneError.
- Pending task with
packages/core/src/release/invariants/index.ts(NEW, 46 LOC): barrel export + side-effect registration.packages/core/src/release/invariants/__tests__/archive-reason-invariant.test.ts(NEW, 447 LOC): 7 cases covering all-verified, mixed, no-T-IDs, dry-run, audit-log idempotency, tombstone rejection, and multi-tag delta parsing.packages/cleo/src/cli/commands/reconcile.ts(NEW, 106 LOC):cleo reconcile release --tag <tag> [--dry-run]CLI subcommand. Emits LAFS-envelope output. Exit 0 on clean reconcile, 1 on errors, 2 on unreconciled tasks remaining (operator decides follow-up).packages/cleo/src/cli/commands/__tests__/reconcile.test.ts(NEW, 228 LOC): integration tests against fixture repo with 3 tag scenarios (all-verified, mixed, all-unverified).scripts/hooks/post-tag.sh(NEW, 56 LOC): git post-tag hook that invokes the CLI for every annotated tag push. Idempotent on re-run.packages/core/src/release/index.ts: barrel updated to re-export the invariant registry surface.packages/cleo/src/cli/index.ts:reconcilecommand registered.CONTRIBUTING.md: post-tag hook installation instructions added alongside the T1410 commit-msg hook.- Audit log: every mutation appends one JSONL row to
.cleo/audit/reconcile.jsonlas{tag, taskId, action, reason, timestamp}. Reconciliation is fully auditable.
Self-test artifact (pre-release)
The implementing worker dry-ran the reconciler against the previously-shipped v2026.4.145 tag: 20 task IDs found in the tag delta, 13 already-closed (no action), 7 unreconciled (would create follow-up tasks in non-dry-run mode). This is exactly the invariant gate's intended behavior — surfacing the unreconciled cohort instead of letting it silently drift.
Quality gates (verified before release)
pnpm exec tsc -b— exit 0 (zero TypeScript errors)pnpm biome ci .— exit 0 (1942 files checked, 2 pre-existing warnings, 1 info; no errors)pnpm run build— exit 0 (full dependency graph)pnpm run test— 690 test files, 11482 tests pass, 17 skipped, 33 todo, ZERO failures
Cross-references
- ADR-056 (this session): DB SSoT, naming convention, release-completion invariant — the canonical decision record for D1–D6.
- T1407 (parent epic): self-enforcing release-completion invariant.
- T1408: archive_reason TEXT → 6-value enum + CHECK constraint (DB layer).
- T1409: ArchiveReason z.enum + tombstone subsystem in
@cleocode/contracts(contract layer). - T1410: commit-msg lint requiring T-IDs in release commits (upstream convention this hook depends on).
- Council 2026-04-24 verdict:
.cleo/council-runs/20260425T033945Z-57a941ca/verdict.md— the canonical mandate this release closes out.
v2026.4.145
Closes the v2026.4.144 release-CI failure (104 TypeScript errors at the Type Check step) and integrates parallel-agent T1408/T1409 archive-reason work that landed mid-flight, restoring the full quality gate (pnpm exec tsc -b, pnpm biome ci, pnpm run build, pnpm exec vitest run) to green.
Closed in this release
- T1434 Eliminate 104 TS errors + ship v2026.4.145 fully green (parent task — this release).
TypeScript error breakdown (104 → 0)
Per-domain dispatch handler error counts at start of session:
packages/cleo/src/dispatch/domains/nexus.ts: 44 errors — missing exports forNexusOpsand 39NexusXxxParams/Resulttypes.packages/cleo/src/dispatch/domains/check.ts: 23 errors — missingCheckOpsexport, 19ValidateXxxParamstypes, 1_projectRootunused, 2DispatchResponseshape mismatches, 1 missing'test.coverage'op.packages/cleo/src/dispatch/domains/conduit.ts: 19 errors — 9 missingConduitXxxParams/Opsexports, 2 envelope-shape mismatches withLafsEnvelope, 7'this' implicitly any(straythis.resolveCredentialcalls in standalone async functions), 1 unused_resolveCredential.packages/cleo/src/dispatch/domains/sentient.ts: 13 errors — 11 missingSentientOps/AllowlistXxxParams/ProposeXxxParamsexports, 2LafsEnvelopegeneric mismatches.packages/cleo/src/dispatch/domains/memory.ts: 2 errors —Record<string, SQLOutputValue>[]toEdgeRow[]ts2352 casts.packages/cleo/src/dispatch/domains/admin.ts: 2 errors — missingAdminRuntimeParamsimport andLafsEnvelopediscriminated-union narrowing.packages/cleo/src/dispatch/engines/release-engine.ts: 1 error —idnot onTaskQueryFilters.
What changed
packages/contracts/src/index.ts: re-exported 162+ operation types at top-level so dispatch handlers canimportthem from@cleocode/contractswithout theops.*namespace hop. Includes ALL ofConduitOps/NexusOps/SentientOps/CheckOps, everyNexusXxxParams/Result, everyValidateXxxParams/Result, everyAllowlist*/Propose*shape, plusAdminRuntimeParams/Result.packages/contracts/src/operations/nexus-user-profile.ts: extendedNexusProfileViewParamswithincludeSuperseded?: booleanto match the engine signature.packages/cleo/src/dispatch/engines/nexus-engine.ts(nexusProfileUpsert): accept the dispatch wire-formatPick<UserProfileTrait, ...>and fill in engine-managed fields (firstObservedAt,lastReinforcedAt,reinforcementCount,supersededBy).packages/cleo/src/dispatch/engines/release-engine.ts(releaseIvtrAutoSuggest): switched fromqueryTasks({ id })(noidfilter onTaskQueryFilters) toloadTasks([taskId])— the accessor's by-id loader.packages/cleo/src/dispatch/domains/admin.ts: importedAdminRuntimeParams; narrowedLafsEnvelopediscriminated union viaenvelope.successbefore readingenvelope.data(line 1278 — the adr.sync mode).packages/cleo/src/dispatch/domains/conduit.ts: replaced 7 straythis.resolveCredential(agentId)calls (which would have crashed at runtime) with_resolveCredential(agentId); widenedenvelopeToEngineResultto accept LAFScode: string | numberand stringify on the boundary.packages/cleo/src/dispatch/domains/sentient.ts: same envelope shape fix as conduit.packages/cleo/src/dispatch/domains/check.ts: dropped unused_projectRootinchain.validate; added'test.coverage'typed op (CheckOps declares it; legacytestop routed byparams.formatis preserved); usedoperation as keyof CheckOps & stringinstead ofas any; normalized LAFS error code to DispatchError code.packages/cleo/src/dispatch/domains/memory.ts: replaced ad-hocas EdgeRow[]casts with the canonicaltypedAll<T>helper from@cleocode/core/store/typed-query.ts. Re-exportedtypedAll/typedGetfrom@cleocode/core/internal.
T1408/T1409 archive-reason follow-through
Parallel-agent work landed mid-session: T1408 added a 6-value CHECK constraint to tasks.archive_reason ('verified'|'reconciled'|'superseded'|'shadowed'|'cancelled'|'completed-unverified'), and T1409 promoted the values into a typed Zod enum at the contracts layer (packages/contracts/src/tasks/archive.ts). T1408 didn't update runtime call-sites or test fixtures, breaking 14 tests. This release closes the gap:
- Runtime:
tasks-sqlite.ts archiveTasknormalizes legacy reasons;migration-sqlite.tsreplaces'migrated'fallback with'completed-unverified';delete.tsmaps deletes to'cancelled';archive.ts deriveArchiveReasonmaps verified-done to'verified';transfer.tscross-project transfers map source tasks to'superseded'. - Tests: 5 fixture files updated to use enum values (
'completed'/'deleted'/'Manual cleanup'→ enum).archive.test.tsexpectation updated. - Contracts portability fix:
isArchiveTombstoneAllowed()incontracts/tasks/archive.tsuses(globalThis as any)?.process?.envinstead of bareprocessso the zero-runtime-deps contracts package remains portable across Node, browser, Deno, and edge runtimes.
Test deflakes
sqlite-warning-suppress.test.ts: bumpedspawnSynctimeout 5s → 30s. CLI cold bootstrap takes ~6s on Node 24+ which raced the prior timeout under parallel-test load and produced empty stdout (T1431 carve-out, now robust under parallel run).performance-safety.test.ts: bumped bulk-50-creates threshold 20s → 45s. Observed runtime under parallel-test load (4+ vitest workers + post-T1408 CHECK eval per row) is ~26s; 45s leaves headroom while still catching real regressions.backup-pack.test.ts(cleanup): added settle-grace + persistent-only assertion. Sibling vitest workers runningpackBundleconcurrently can transiently leavecleo-pack-*dirs inos.tmpdir()between pre-snapshot and post-snapshot; we now re-scan after a 50ms grace and only fail on staging dirs that persist past their owner's call boundary.reconstruct.test.ts: documentedRECONSTRUCT_TIMEOUT_MSrationale (git log over full history takes ~40s baseline; under parallel test load, the 60s defaulttestTimeoutcan race).
Lesson
Type Check is a hard CI gate — missing contract exports MUST be re-exported at the top level of @cleocode/contracts (not just under the ops.* namespace) when dispatch handlers depend on them. Future typed-narrowing waves (Wave D-style migrations) MUST run pnpm exec tsc -b --pretty false and pnpm biome ci . against the full repo before tagging — pre-tag verification at the per-package level misses cross-package symbol resolution.
v2026.4.144
Re-ships v2026.4.143 scope as a properly-tagged release. The v2026.4.143 tag was created on commit 6b66e7f14 before the CHANGELOG section landed, so the Release workflow's Verify CHANGELOG section step rejected it (CI failed at tag-push time). The fix-forward CHANGELOG commit (ff286f5e1) and the typed-narrowing TS error reduction (51ff74664) landed afterwards, and a manual workflow_dispatch Release on ff286f5e1 succeeded — but the v2026.4.143 git tag was never moved. Per project rule "Never reuse tags", v2026.4.144 supersedes v2026.4.143 with a tag that points at a fully-green commit.
Same scope as v2026.4.143
All closures listed under v2026.4.143 below are inherited by this release. No new functional changes; only a clean tag pointing at a green-CI commit.