Walkthroughs
Three scenarios, each end-to-end. Read Concepts and Quick start first; this page assumes you know what canonicals and artifacts are. Output below is realistic but synthetic — the shapes are real, the names are illustrative.
Multi-language monorepo
A 250-KLOC engine: a Dart core, a Rust physics module, a couple of Kotlin/Swift bridges, and a fistful of plugins. The interesting bit isn't ae init — it's ae status reading the requires: graph across languages.
$ cd ~/code/ecsly
$ ae init
ae 3.0 init: scanning ecsly
+ dart core_packages/ecs → artifacts/local/dart_ecs
+ dart core_packages/render3d → artifacts/local/dart_render3d
+ rust core_packages/physics → artifacts/local/rust_physics
+ kotlin bridges/android → artifacts/local/kotlin_android_bridge
+ swift bridges/ios → artifacts/local/swift_ios_bridge
+ dart plugins/audio → artifacts/local/dart_audio
... (8 more)
ingested 14 artifacts in 1.1sAuthor the canonicals that matter (ecsly/render_pipeline, ecsly/physics_step, ecsly/schedule), link them from the relevant artifacts, then declare cross-artifact dependencies in each artifact's matrix.yaml:
# .ae_hub/artifacts/local/dart_render3d/matrix.yaml
requires:
- artifact: rust_physics
canonical: ecsly/physics_step
features: [physics.step, physics.spatial_index]
- artifact: dart_ecs
canonical: ecsly/schedule
features: [schedule.fixed_tick, schedule.frame_pacing]Now ae status walks the requires: graph and reports tier-2 upstream blockers sorted by downstream-count:
$ ae status
AE 3.0 — ecsly
Tier 1 INVARIANT VIOLATIONS 4
ecsly/physics_step/physics.step "Step is deterministic for fixed dt"
→ no test asserts this (rust_physics)
...
Tier 2 UPSTREAM BLOCKERS 2 (sorted by downstream count)
rust_physics ecsly/physics_step/physics.spatial_index
impl=missing — blocks 4 downstream artifacts
(dart_render3d, dart_ai, dart_gameplay, swift_ios_bridge)
Tier 3 PARTIAL FEATURES 6
Tier 4 UNREFERENCED CANONICALS 1
ecsly/render_pipeline not linked from any artifact yet
14 artifacts, 3 canonicals.Tier 2 is the working signal in a multi-language repo. Land that one missing feature in rust_physics and four downstream artifacts move forward.
External standard with KHR extensions
glTF + KHR extensions is the canonical example of sibling-canonical decomposition (see Authoring canonicals → Granularity). One canonical for the base format; one per extension you care about.
ae canonical init --concept gltf/core --title "glTF 2.0 (core)"
ae canonical init --concept gltf/extensions/khr_materials_clearcoat \
--title "KHR_materials_clearcoat"
ae canonical init --concept gltf/extensions/khr_lights_punctual \
--title "KHR_lights_punctual"Each canonical lists its own ~10–30 features in matrix.yaml. Now the artifact that loads glTF in your engine declares which of these it implements:
# .ae_hub/artifacts/local/dart_gltf_loader/meta.yaml
references_canonical:
- gltf/core
- gltf/extensions/khr_materials_clearcoat
- gltf/extensions/khr_lights_punctual@v1 # locked to v1 snapshotThe first two are live references — they re-resolve against whatever canonical/gltf/core/ currently holds at ae sync time. The third is locked — it always resolves to canonical/gltf/extensions/khr_lights_punctual/v1/, the frozen snapshot. Use locks when an extension you depend on is moving and you don't want to chase it. See Hub layout for the snapshot directory shape.
ae artifact verify --pack dart_gltf_loader runs a tiered verify against all three referenced canonicals. In CI, add --strict so Tier 1 + Tier 2 gaps fail the build (unless explicitly accepted via drift.yaml).
A new-extension flow (hypothetical 2026)
Imagine the Khronos group ratifies KHR_gaussian_splatting next quarter. Adding it to your project is a five-step loop, no migration tools needed.
# 1. Author the canonical for the new extension.
$ ae canonical init --concept gltf/extensions/khr_gaussian_splatting \
--title "KHR_gaussian_splatting"
created canonical/gltf/extensions/khr_gaussian_splatting/
# Edit matrix.yaml by hand (or distill from a reference impl):
$ ae canonical distill --pack rust_gltf_kgs_ref \
--concept gltf/extensions/khr_gaussian_splatting \
--mode upsert
distillation: dispatched to claude_code subagent
distillation: validated against ae.canonical.draft.v1
merged 11 features into canonical/gltf/extensions/khr_gaussian_splatting/# 2. Link the canonical from your loader artifact.
$ ae artifact link --pack dart_gltf_loader \
--canonical gltf/extensions/khr_gaussian_splatting
linked dart_gltf_loader → gltf/extensions/khr_gaussian_splatting (live)
materialized 11 matrix rows (impl: missing)# 3. Status now flags the new extension as Tier 4 → 3 as you implement.
$ ae status --pack dart_gltf_loader
dart_gltf_loader
Tier 1 0
Tier 2 0
Tier 3 11 gltf/extensions/khr_gaussian_splatting/* (impl=missing)
Tier 4 0# 4. As you write code, ae sync keeps file hashes honest and surfaces drift.
$ ae sync --pack dart_gltf_loader
re-scanned 12 files
drift: 8 files modified since last extract
drift: 1 file added
drift.yaml updated# 5. When tests assert the invariants and impl cells flip to "done",
# the tier counts decrement automatically.
$ ae status --pack dart_gltf_loader
dart_gltf_loader
Tier 1 0
Tier 2 0
Tier 3 3 (8 features now done; 3 still partial)
Tier 4 0That's the loop — for one extension, for a whole engine, or for an external standard with thirty siblings. AE doesn't ship a "migrate to new extension" command because it doesn't need one: canonical-init, link, sync, fill in cells.
Where to next
- CLI reference — every flag used above.
- MCP tools reference — same operations from inside an agent.
- Claude Code plugin — slash commands that wrap the same flow.