CLEO task management protocol - session, task, and workflow guidance. Use when managing tasks, sessions, or multi-agent workflows with the CLEO CLI protocol.
Resources
2Install
npx skillscat add kryptobaseddev/cleo/ct-cleo Install via the SkillsCat registry.
CLEO Protocol Guide
Trustworthy project knowledge
After confirming the assigned worktree, orient with briefing/focus. Check current
coverage and sourced authority before acting on retrieved guidance. UNKNOWN
impact is incomplete assessment; NONE is no detected impact in assessed static
coverage, never proof of no runtime callers. Resolve ambiguous symbols explicitly.
Preserve historical handoffs and follow sourced corrections separately.
Consume repair findings as a matrix of scope, evidence, responsibility, operation,
prerequisites, verification, and recovery. The calling agent supplies sourced resolutions; no background model is required. Escalate unresolved
owner decisions, reject stale proposals, verify postconditions, and record useful
incident learning with project/revision evidence. A failed diagnostic is not clean.
Provider reference delivery must be verified or embedded self-contained; static
instruction checks do not establish live Codex, Claude, or Kimi behavior.
Asking the owner (HITL ask tool)
Whenever you need the owner to answer, decide, approve or choose ANYTHING, use the ask
tool (AskUserQuestion in Claude Code, or the provider equivalent listed in CAAMP'sPROVIDER_ASK_TOOLS) with 2-4 concrete, selectable options, recommended first, each stating
what happens and its trade-offs. Never ask inside a response or bury a question in prose.
Answer first in every reply: the first line is the result, answer or decision; then only the
evidence the reader needs and what was skipped or unverified. No preamble, recap or routine
status chatter: report only when done or when a decision is needed.
- Subagents never ask the human. Return the question with its options to your
orchestrator (blockedplus{question, options[{label, description}], recommended}
in the manifest); the orchestrator asks via its ask tool. - No ask tool in the harness: emit one LAFS
hitl.requestenvelope{question, options[{label, description}], recommended}and stop.
Project identity and moving between devices
A project is identified by its portable project_id in .cleo/project.json
(tracked, id write-once, plus its name; ADR-096; legacy mirror .cleo/project-id). A path is only a per-device hint, so a moved or
restored checkout keeps its identity. After a new device, restore or migration,
or when a known repo reports "Not inside a CLEO project", registry paths are
unreachable, or nexus hits ENOENT on an old path, run and report:
cleo doctor projects— machine-wide: moved, missing, split and temp rows with
remedies. Dry-run by default;--applyrebinds only on nonce proof and writes a
receipt;--rollback <id>restores.cleo doctor project-identity— legacy, missing, conflicting or uncommitted id, name drift;--resolve --dry-runthen--resolveis the only migration.cleo doctor --all-projects— unreachable registered projects.cleo nexus projects clean --orphans --dry-run— NEVER without--dry-run;
it deletes rows for projects that merely moved.cleo doctor credentials— credentials still keyed by an old path.cleo doctor global-delivery—~/.cleo, the global hub reference and every
harness CLEO skill install must resolve (a~/.cleolink carried by dotfiles from
Linux dangles on macOS and silences all of them).--repairrelinks with a receipt.
Guarded knowledge repair
Use cleo doctor knowledge --dry-run to inspect findings and sourced proposals.
Persist reviewed JSON with cleo doctor knowledge --prepare proposal.json --actor AGENT.
Discover retained jobs with --jobs --actor AGENT; continue with --limit and returned
JSON --cursor. Follow each inspectArgv; never guess the latest job. Partial diagnostics
remain unresolved, and job status alone does not verify current effects.
For job operations, supply the original explicit actor and proposal ID:cleo doctor knowledge --apply JOB --actor AGENT --proposal-id PROPOSAL;
replace --apply with --inspect, --cancel, or --resume for that operation.
Inspection returns original receipts, separate rollback corrections, diagnostic
failures, and a paged append-only ledger; use --limit and --offset until covered.
Never copy a stored actor merely to bypass E_REPAIR_ACTOR.
Each invocation shares one two-second default budget across assessment, preparation,
locks, application and verification (--budget-ms permits an explicit override).
A later explicit apply/resume starts a new bounded attempt; it does not renew an
expired attempt or bypass immutable resource checks. Synchronous SQLite is cooperative,
not timer-preemptible. On failure, retain any prepared job and attemptFailure
including pending finalization. Cancellation requests do not reverse committed effects.
Resume retains failed/cancelled outcomes and uncertain expired-running history;
live owners cannot be stolen and completed effects are not reapplied.
After rollback, apply/resume reject with E_REPAIR_ROLLED_BACK; inspectrecoveryState for the original historical receipt and separate rollback receipt.
Recover via cleo doctor knowledge --rollback RECEIPT --actor AGENT --proposal-id NEW_ID.
Inspect both receipts. Versioned quarantine recovery restores only invalid_at, preserving
validated paired citation-count/timestamp usage; protected edits conflict. Legacy receipts
require exact images. Recovery records actual before/after images, not byte restoration
of old usage. Prepared rollback still guards the full current image; later reads require
fresh preparation. Unrelated changes survive. Stale proposals need reassessment. --resolve FILE
applies reviewed input through the same lifecycle; --fix --actor AGENT handles bounded
confirmed stubs. cleo doctor repair retains its separate database-recovery semantics.
The always-loaded core is ~/.cleo/templates/CLEO-INJECTION.md; reference sections ship in the
package's CLEO-REFERENCE.md (T12580). Emit any section with: cleo briefing inject --section <name>
Core: session-start · work-loop · triggers · session-commands · output-contract
· error-handling · pre-complete-gate · rules · escalation. On demand: task-creation
· task-discovery · task-relationships · memory · memory-jit · data-location · nexus
· orchestration · playbooks · documents · human-render · spawn-tiers · evidence
· projection · knowledge-repair
Task find defaults to lexical query terms. Fuzzy character-subsequence matching requires --fuzzy; inspect per-row match.kind and match.fields before inferring related work. --in restricts the source field. Matching mode and fuzzy field explanations survive scalar/human output on stderr. Semantic retrieval remains separately identified.
Compact SDK list/find records also carry _withheld: omission names and original UTF-8 sizes are recorded before fields are discarded, then retained through later CLI projections. Use full records to inspect those values; absence is not emptiness.
List/find expose data.population with matched and returned counts, truncation, pagination, and archive eligibility. Count output equals emitted rows; use --all or --limit 0 to enumerate all matches, and --include-archive to include archives under the same filters. Scalar/ID/table/summary modes preserve population facts on stderr. Do not treat a page as complete.
Use cleo backup inspect <snapshot> --record-id <id> for read-only historical evidence; scoped absence or unknown provenance is not recovery authority.
Code-graph answers (cleo nexus impact, context, full-context, why, search-code, task-symbols, clusters, flows) carry meta._nexus.freshness: stale file count and sample, whether the queried symbol's own file is stale, and the refresh command with an estimated cost. A query refreshes up to 25 stale files inline within a 60 s budget (nexus.autoRefresh.maxFiles/budgetMs/enabled) and discloses it in freshness.autoRefresh; beyond that it answers from the stale index with W_NEXUS_INDEX_STALE. unknown freshness is never fresh. cleo nexus analyze re-parses only changed files, re-resolves every file, and reports mode, reason and per-phase cost; it falls back to a full parse (and says why) when there is no parse cache, the extractor build changed, or over 30% of files changed. --full forces a rebuild.
Sessions are terminal-bound (T12500)
cleo session start binds the calling agent process (CLAUDE_CODE_SESSION_ID, CODEX_THREAD_ID, …), pane (TMUX_PANE, …), tab (TERM_SESSION_ID, …), CI job (GITHUB_RUN_ID+GITHUB_RUN_ATTEMPT+GITHUB_JOB, CI_JOB_ID) or ssh login tty (SSH_TTY+SSH_CONNECTION).
With no provider key it also walks the process tree (T12864): a known single-agent harness (Kimi, aider, amp, cursor-agent, … — past its per-call bash -c shells) or an interactive / script shell becomes the identity, so session start then cleo start in separate bash -c calls share one session; a harness below a human's tab / pane, an ssh login or a CI job gets its own, more specific key, so it must run cleo session start itself.
Any other host (a node / python orchestrator, an IDE extension host, a daemon, anything under pid 1) identifies nobody and keeps the single-session guard: multi-agent hosts and multi-step scripts must set CLEO_SESSION_ID (or CLEO_AGENT_ID, only in a long-lived host process: under a short-lived one such as make the key changes per call) per agent.
Session mutations from an unbound caller fail with E_SESSION_UNBOUND instead of
guessing the newest session; bind with cleo session start, cleo session resume <id> or CLEO_SESSION_ID=<id>, or name the target with --session <id>. Separate one-shot ssh host 'cleo …' calls are separate callers: export CLEO_SESSION_ID there.
Unattributed mutations warn on stderr; session status / briefing label a guessed session unbound: true.
- A session a human started in a tab is adopted by Claude Code in that tab
(also after a Claude restart). An adopter works in it but cannot end it without--session <id>, and starting its own session never takes over the tab. A
session Claude started can be ended from the tab. - Two Claude instances that each start a session stay isolated; a sibling tmux
pane never sees another pane's session. - Agent-tool subagents inherit the parent's
CLAUDE_CODE_SESSION_IDand act in
the parent's session;cleo orchestrate spawngives workers their own.
Typed decisions (cleo decide, T12491)
decide answers typed questions (yes/no, choice, score) through a swappable Jev-wire provider and falls back to local heuristics when unconfigured or failing. Pick a provider and supply its key: printf %s "$KEY" | cleo decide config --provider layahost --key-stdin (layahost, the default, needs only the key and uses model laya-auto); a custom endpoint is --provider jev --url <u>. --model overrides the model and --clear removes the settings. On a terminal, cleo decide config with no flags runs a setup wizard that reads the key hidden. The key is kept in a 0600 file and never printed. cleo decide status probes reachability and cleo decide ask --state <text> --noul <q> runs one debug question.
Quick Reference
| Need | Command |
|---|---|
| Start session | cleo session status → cleo briefing |
| End session (from another terminal) | cleo session end --session <id> |
| Find work | cleo next → cleo focus <id> |
| Search tasks | cleo find "query" |
| Complete task | cleo verify T### --gate ... --evidence "..." → cleo complete T### |
| Run typed gates (the only command that executes them; writes read the cache) | cleo verify T### --run [--req A,B] |
| Save memory | cleo memory observe "..." --title "..." |
| Spawn subagent | cleo orchestrate spawn <taskId> --tier 2 |
| Create a Saga | cleo saga create --title "..." --acceptance "..." |
| Saga-level ready | cleo orchestrate ready <sagaId> |
| Saga-level waves | cleo orchestrate waves <sagaId> |
| Saga rollup | cleo saga rollup <sagaId> |
| List Saga members | cleo saga members <sagaId> |
| Attach doc to task | cleo docs add T### file.md --type note --slug handle |
| Read a doc | cleo docs fetch <slug> |
| Browse docs | cleo docs list --task T### |
Document projection outcomes
cleo docs add preserves accepted canonical bytes when optional graph or sourced
observation work fails. Read data.projection for captured project identity,
coverage, diagnostics, deadline, and any durable job or verification receipt.pending can mean a write outcome is still unresolved; retain the job reference
and inspect it before explicit resume. Repeating the add is not a recovery step.
The original two-second maintenance budget covers preparation through verification;
timer expiry does not preempt synchronous SQLite work.
Verify storage with cleo docs fetch <slug> and its JSON data.content (text docs,
T13352; binary docs carry data.bytesBase64) plus data.metadata.sha256. Keep
canonical storage success, optional projection verification, and installed-provider workflow verification as separate evidence.
Acceptance input and historical evidence
Add, update, batch, and saga creation share one acceptance-input boundary. Pass
arrays of strings in JSON parameters; --acceptance also accepts a JSON array
string or the documented pipe-delimited form. Array entries keep literal pipes
and quoted unions. Strings are trimmed and blank strings omitted; nonstring
entries and malformed explicit JSON arrays reject the whole mutation. Bracketed
prose and the existing delimiter escaping rules retain their interpretation.
On update, an explicit [] (including an all-blank string array) requests a clear;
omitting acceptance leaves it unchanged. Policy and immutability checks apply to
normalized criteria, and a locked change still requires --reason. Fresh reads
retain an empty acceptance array. Malformed stored criteria produce a diagnostic;
valid historical strings and structured gates are preserved without normalization.
Do not infer historical splits from pipes alone: repairs need original input or
explicit provenance, a snapshot, and a guarded receipt.
Task controls and committed evidence
Explicit critical priority on add/update requires a dependency or a nonempty--depends-waiver; updates check the resulting dependency set. CLI flags, JSON
params, and SDK calls share this policy. Explicit severity changes use the
project's signing identity: a nonempty ownerPubkeys allowlist restricts signers;
an absent or empty list keeps the existing opt-in policy. Unreadable or malformed
authority is an explicit configuration failure. Committed severity,
duplicate-bypass, and dependency-waiver evidence lives in the task transaction
audit. Historical filesystem attestations alone do not prove a task committed.
Dry-run creates no committed attestation; failed writes leave no committed receipt.
Read completeness before editing
Use cleo show <id> --full to inspect task fields before editing them. Compact
records name every omitted field in _withheld, including empty or null values;
the size is UTF-8 content bytes for strings and serialized JSON bytes otherwise. A list/*/field key (acRows/*/id) names a field omitted from every element, summed.
Repeated projection retains earlier omissions. A record without _withheld is
complete at the record projection boundary; an envelope can separately report
omitted records or fields. Never overwrite a field because a compact read omitted it.
Coverage, failure diagnostics, authority corrections, and pending repair facts
survive budgeting before examples. Read operations reject budgets too small for
mandatory facts; request a narrower scope or a larger budget. Internal mutation
budgets that cannot hold the minimum envelope reject before execution. If a
successful mutation's actual receipt exceeds a viable budget, success and the
complete receipt are preserved with _budgetEnforcement.withinBudget: false.
Inspect the receipt before retrying; overflow is not rollback or clean coverage.
This internal budget contract does not add a --token-budget flag to add/update.
Skill-Specific Extensions
Reference files
| File | Load it when you |
|---|---|
references/session-protocol.md |
start, resume or end sessions; pick skills |
references/orchestrator-constraints.md |
spawn subagents from an orchestrator |
references/planning-loop.md |
plan an epic, run its waves, verify its tasks |
references/anti-patterns.md |
check a plan against known mistakes |
references/memory.md |
recall or record BRAIN memory (progressive disclosure) |
references/sticky-notes.md |
capture a thought before it is a task: cleo sticky jot "...", then cleo sticky convert <id> --to-task |
- Task hierarchy, Saga commands, add-batch decomposition, docs policy, and evidence detail live in the on-demand reference; emit
task-creation,documents, andevidencewhen needed. - For add-batch input, The top-level JSON MUST be an array of task objects, not an object wrapper like
{ "tasks": [...] }. - Dry-run count semantics:
/data/countand/data/wouldCreatepredict writes;/data/insertedCountmust be0for dry-run. - Mutation output paths: use
/data/created/0,/data/updated/0, and/data/deleted/0; never parse legacy full records.--output idemits affected IDs once in created/updated/deleted order from these canonical arrays. cleo delete <id>soft-archives the task.--cascadeexplicitly archives descendants;--forcealone orphans and preserves children and permits dependents. Parents with children require one of these controls. Readdeleted[](or--output id) for all archived IDs, including cascade descendants.- Docs path policy and strict preflight: keep docs repo-relative. Do not pass arbitrary external absolute paths. The canonical six-verb docs path is add, update, fetch, list, remove, publish (T10516). Use
cleo docs listfor discovery;cleo docs list-types(ADVANCED) andDocKindRegistryresolve runtime kinds whenlistis insufficient.
Task Relationship Systems — depends, blockedBy, relates
CLEO has three distinct relationship systems with different storage, semantics, and CLI exposure. Do not conflate them.
| System | Storage | Semantics | CLI Exposure |
|---|---|---|---|
depends |
task_dependencies table (task_id, depends_on) |
Blocking dependency — task cannot start until all depends tasks are done |
cleo add --depends T1,T2 / cleo update --depends / --add-depends / --remove-depends |
blockedBy |
tasks.blocked_by column (free-text) |
Human-readable reason why a task is blocked (e.g. "waiting for API key") | cleo update --blocked-by "reason" / --clear-blocked-by |
relates |
task_relations table (task_id, related_to, relation_type, reason) |
Semantic, non-blocking relationships: blocks, related, duplicates, absorbs, fixes, extends, supersedes |
cleo relates add <from> <to> <type> <reason> / cleo relates remove / cleo relates list |
Key distinction
dependscontrols execution order (wave planning,cleo nexteligibility). It is a hard dependency.blockedByis a status annotation — it does NOT link to another task, it just explains why this task isblocked.relatesis informational linkage — it does NOT block execution, but it records that two tasks have a semantic relationship (e.g. "T1001 supersedes T1002" or "T1003 duplicates T1004").
CRITICAL: Do NOT use relates for execution gates
relates is never a blocking dependency. If task B must wait for task A to finish, use --depends:
# CORRECT — execution dependency
cleo add "Implement auth" --depends T1001,T1002
# WRONG — relates does NOT block execution
cleo relates add T1003 T1001 blocks "waiting for auth"Common pitfall: using blockedBy for task IDs
--blocked-by expects a string reason, not task IDs. To express "this task is blocked until that task finishes", use --depends:
# CORRECT
cleo add "Implement auth" --depends T1001
# WRONG — blocked-by is free text, not a task reference
cleo update T1003 --blocked-by T1001cleo relates command reference
# Add a semantic relationship
cleo relates add T1001 T1002 supersedes "T1002 is absorbed into the new auth flow"
# List relations for a task
cleo relates list T1001
# Remove a relation
cleo relates remove T1001 T1002
# Suggest related tasks based on shared attributes
cleo relates suggest T1001 --threshold=50
# Discover related tasks using various methods
cleo relates discover T1001Valid relation types: blocks, related, duplicates, absorbs, fixes, extends, supersedes.
Schema types mismatch note
The DB schema TASK_RELATION_TYPES (related, blocks, duplicates, absorbs, fixes, extends, supersedes) must match the runtime types. The CLI cleo relates add accepts the DB schema types. Always normalize to the DB enum before persisting.
Task Hierarchy (PM-Core V2 — ADR-088)
Canonical source: docs/adr/ADR-088-pm-core-v2-workgraph-relations-completion-criteria.md.
Legacy charter ADR-073 remains authoritative for pre-PM-Core V2 semantics; ADR-088
governs the PM-Core V2 target. The T10638 migration removed legacytask_relations.groups hierarchy reads and the dual-shape label='saga' fallback —
containment is now read exclusively from tasks.parent_id.
| Tier | Prefix | type value | Scope-of-change |
|---|---|---|---|
| Saga | SG- |
saga |
Theme grouping ≥2 Epics across ≥2 releases |
| Epic | E- |
epic |
One releasable slice; ≥1 PR to main |
| Task | T- |
task |
One atomic PR-sized change; single wave |
| Subtask | (none) | subtask |
One commit; ≤2 files; contributes to Task's PR |
Containment (I1): tasks.parent_id is the only containment edge. Direct children,
ancestor/descendant traversal, closure rollups, and default parent completion are all derived
from parent_id. The parent matrix is:
| Child type | Parent type |
|---|---|
subtask |
task |
task |
epic |
epic |
saga or null |
saga |
null |
Storage (I2): All IDs stored as T####; type column discriminates tier (not label).
Prefixes (SG-, E-) are DISPLAY + import-mapping only.
Non-containment (I3): task_relations is for secondary graph semantics ONLY — dependency,
ordering, cross-reference, evidence, supersession, provenance. A task_relations row
MUST NOT satisfy containment, child listing, ancestor/descendant traversal, parent rollup,
parent completion, nesting-budget, or closure semantics. The groups relation type is
retired for hierarchy; do not use task_relations.groups for parent/child semantics.
Typed Completion Criteria (PM-Core V2)
PM-Core V2 introduces typed acceptance criteria — task_acceptance_criteria.kind
is one of:
| Kind | Requires target_task_id |
Purpose |
|---|---|---|
text |
No | Human-authored acceptance criterion |
child_task |
Yes | Deterministic projection from a direct parent_id child |
evidence_bound |
No | Gate-backed criterion (implemented, testsPassed, qaPassed) |
Key rules:
- A parent with children uses
child_taskcriteria by default; these are deterministic
projections fromparent_idcontainment (the T10639 child_task-projection backfill
derives parent completion from child state — mixed-criteria mode is migration-only or
explicit advanced scope). textandevidence_boundcriteria must NOT usetarget_task_id.- Cancelled children do NOT automatically satisfy parent completion; they require waiver
or replacement evidence. - Adding or reopening required child work under a done parent reopens affected ancestors.
Saga Operations (PM-Core V2)
Saga-level orchestration is first-class. Saga membership uses parent_id
containment (NOT task_relations.groups). Use saga IDs directly with orchestrate commands:
# Saga-level ready frontier — parallel-safe tasks across all member epics
cleo orchestrate ready <sagaId>
# Saga-level dependency waves — unified wave plan across all member epics
cleo orchestrate waves <sagaId>
# Saga status rollup — completion %, member counts
cleo saga rollup <sagaId>
# Saga membership listing via parent_id containment
cleo saga members <sagaId>Epic-level fallback: If saga-level orchestrate fails, enumerate member epics fromcleo saga members <sagaId> and call cleo orchestrate ready <epicId> for each member
individually. Do not use task_relations.groups as a fallback for hierarchy — it is
non-containment only per I3.
WorkGraph (PM-Core V2 — T10632/T10633/T10634)
The WorkGraph subsystem provides scaffold validation (T10632), atomic application (T10633),
and planning document generation (T10634):
| Feature | What it does |
|---|---|
| Scaffold Dry-Run Validator | Validates WorkGraph JSON payloads against schema invariants before mutation. Returns wouldCreate/wouldUpdate/wouldDelete without side effects. |
| Scaffold Apply Engine | Atomically applies validated WorkGraph scaffolds to the task database. Creates, updates, and deletes tasks/relations/ACs in a single transaction. Sibling-relation-based (SQLite trigger blocks parent-child relation edges). |
| Planning Doc Generator | generatePlanningDoc() produces structured markdown plans from the WorkGraph. Supports "agent" (compact) and "maintainer" (prose) output modes. |
Example — dry-run a scaffold before applying:
# Validate scaffold payload (read-only)
cleo workgraph validate scaffold.json
# Preview, then apply the validated scaffold atomically
cleo workgraph apply scaffold.json --dry-run
cleo workgraph apply scaffold.jsonTask Context (PM-Core V2 — T10629/T10630/T10631)
Bounded task context with token budgeting for agent ergonomics:
| Feature | What it does |
|---|---|
| Task Context Pack | The tasks.context operation (T10629) backs coreTaskContext (T10630): it returns targeted task information (identity, acceptance criteria, blockers, attached docs, graph edges, recent activity) respecting a configurable token budget (default 1500). Uses TasksContextOmission to track overages and provides expansion hints. |
| Saga Context & Readiness | Saga-level aggregate rollups: completion percentages, ready-frontiers, and blocker enumeration across all member epics via parent_id containment. Grouped readiness report via orchestrate.report (T10631). |
The task-context pack is surfaced for agents via cleo focus <taskId> (compact, for
prompt injection) and cleo orchestrate report <taskId> (full grouped readiness). Do not
confuse this with cleo context, which is the separate context-WINDOW usage monitor
(cleo context status / cleo context check).
Example — get the task-context pack for agent use:
# Full grouped readiness report for a task
cleo orchestrate report <taskId>
# Compact context pack for prompt injection
cleo focus <taskId>BRAIN Decision-Store — Durable Architecture Decisions
Architectural decisions belong in the BRAIN decision-store, not in adrs markdown
blobs or agent-outputs ledgers. Use cleo memory commands to create, find, and
cite decisions by durable BRAIN decision IDs.
| Need | Command |
|---|---|
| Store a decision | cleo memory decision-store --decision "..." --rationale "..." |
| Search decisions | cleo memory decision-find --query <term> |
| Find by type | cleo memory find <term> --type decision |
| Fetch full record | cleo memory fetch <decisionId> |
| Find by epic | cleo memory decision-find "<epicId>" (no epic filter — query text, then verify source_table/source_rowid) |
| Check status | cleo memory fetch <id> → check confirmation_state field |
Why BRAIN decisions over markdown ledgers:
- Decisions are durable, queryable, and have source provenance (
source_table,source_rowid) - Decision IDs disambiguate overloaded D0xx/AGT-* identifiers via provenance tracking
- The decision-store supports lifecycle tracking (pending → accepted → superseded)
- Memory link pattern: cite a BRAIN decision ID in task descriptions, then
cleo memory fetch <id>for full context
Migration rule: When you encounter a decision ONLY in a markdown ledger
(.cleo/adrs/, .cleo/agent-outputs/), store it in the BRAIN withcleo memory decision-store --decision "..." --rationale "..." and cite the
BRAIN ID going forward.
Evidence must prove task criteria
Merged PRs and passing CI are provenance. Implementation requires changed artifacts related to the task; testing and review require their own actual results (ci:<pr> once the PR merged and the project sets evidence.ciSatisfies; else tool:test-affected when testing.affectedCommand is configured, otherwise a targeted test-run:<json> or tool:test; after merge a scoped run carries only while the change's files are byte-identical, or when it is a test-run: recorded on a main HEAD descending from the merge, on the current tree, covering the change (T13673); plan with cleo done <id> --plan, which never plans a whole-suite tool:test itself (T13647); never run the suite by hand and again via tool:test). Run tests, typechecks and builds one at a time through cleo run --wait --class <test|build|full-build> -- <cmd> (exit 75: not admitted yet, wait and retry); never wrap cleo run or cleo verify in another queue or wrapper, and never raise heap or worker counts (NODE_OPTIONS, --maxWorkers). For tasks with canonical criteria, append explicit links such as satisfies:T1234#AC1 to each relevant gate's evidence. Fetch the PR merge commit so artifact hashes can be inspected. A changed criterion invalidates its recorded proof. Completing a child preserves an open parent whose own criteria remain unproven; child waivers never transfer to parent criteria.