Kai Ase Siren
Skip to content

Cascade

The cascade turns doctrine sources into each harness's global context when ~/.agent-compose/agent-compose.yaml exists. Missing config is a no-op.

Bare acompose summarizes its roster, outputs, load points, repository plan, skill links, and repaired drift. Bare acompose --reapply recreates outputs and load-point links. acompose --verbose emits each source, override, manifest, and link as source => destination.

person_policy: external-only requires person_source. A bad package aborts before roster or cascade projection can restore the embedded default.

All state lives under ~/.agent-compose: config, outputs, repository plan, roster, and cache. A legacy ~/.config/agent-compose migrates on first use and leaves a compatibility symlink through the cutover tracked in agentic-os#618.

Explicit sources compose first in listed order. Each roots entry then adds sorted AGENTS.COMPOSE.md files. That filename marks always-global doctrine that harness context does not also load.

Selection and rewrites

A machine may declare scopes, and a source declares its own in YAML frontmatter and composes only when the two intersect. Omitting the machine key disables filtering entirely. Under active filtering an untagged source never leaks in. Frontmatter harnesses restricts a source to named harnesses. Composed bodies are rewritten for their new home: frontmatter stripped, ## See also navigation dropped, and relative markdown links absolutized against the source's own directory.

source_delivery: import emits an @path pointer, not a body, so a doubly-delivered source loads once. It reaches named sources, which must resolve; a roots entry inlines and keeps its override.

A sibling AGENTS.<harness>.md beside a source patches it for one harness: sections replace by verbatim heading, new headings append, and an ambiguous heading fails the compose loudly. When harness slices diverge - by selection or by override - output splits into COMPOSED.<harness>.md files. Identical slices share one COMPOSED.md, and obsolete banner-carrying outputs are removed on convergence.

Appendix

appendix composes configured blocks after every source, so they carry the tail of the composed context. Each entry holds exactly one of text (inline markdown) or path (a file), and an entry that carries both or neither fails the config load.

appendix:
  - text: |
      ## Checkin dashboard
      Open these before answering a checkin.
  - path: ~/.config/agent-compose/appendix/deploy.md
    roles: [platform, sysadmin]

A native role bundle carries the appendix apart from the sources, because it rewrites the source body before rendering and a rewrite keyed to headings swallows whatever follows the last one. The block lands at the tail of the bundle's instructions, holding the position it holds on the host load point.

A path entry is rewritten the way a source is: frontmatter stripped, ## See also dropped, relative links absolutized against the file's own directory. Inline text composes verbatim, because nothing about a config string is repo-relative.

An entry with no roles is global and reaches every composed output. An entry naming roles composes only for those roles, which by construction leaves it out of the role-less harness load point: a session-home launch renders its own operating base per role and is the only reader. A repo-scope launch reads the host file, so it sees global blocks alone.

Cascade never loads a person, so roles is checked for slug shape and nothing more. A native launch does resolve one, and warns there for any configured slug the roster does not define, because a block that composes for no one otherwise passes silently. acompose --verbose also lists every block with its destination. A missing path warns and skips on convergence, exactly as a missing source does, and fails under --check.

Outputs

Each configured load point (claude and codex by default, others via load_points, null to opt out) is symlinked at its harness's composed file, backing up any pre-existing regular file to .bak. The strict repository-plan.yaml is emitted beside the composed output. It compiles operating context, global policy, role policy, provider uses, and resident-only pins from trusted KDL with sealed input provenance. See Repository plan.

--dry-run previews only real changes. --check verifies every output against a fresh compose and fails with a diff on drift. Writes happen only on change, so a converged host recomposes silently. agent-compose config validate <path> checks staged host configuration and a linked strict provider document without writes.

Native skill roots

Bare compose can also link authored skill catalogs into harness-native skill directories through skill_load_points.

Native skill linking uses the compiled residency set from repository-plan.yaml. Repositories contribute .agents/skills. The compiled set precedes verified local catalogues. Existing unowned entries win. Missing entries warn and skip, while other inspection failures remain fatal. Agent-compose records links in ~/.agent-compose/skill-mounts.json and removes only stale links that still match that ownership record. Fleet pointer aggregation, conditional category gating, and per-repo capability pulls remain rollout policy outside this substrate operation.

skill_catalog_manifest projects AOS-verified roots without network work. Local skill catalogues define the trust contract.

See also