Yggdrasil Overlay Architecture — Design Spec
Date: 2026-03-26 Status: Draft Extends: GDD Design
Summary
Yggdrasil becomes a generic meta-workspace — scaffolding around any community's projects. Community-specific configuration (components, identity, build adapters, AI context) moves from hardcoded ecosystem.yaml entries to a separate overlay repo that lives in overlays/. Users interact with ws overlay commands; the underlying complexity is transparent.
The design principle: always functional, progressively richer. A bare project with no overlay works. An overlay makes it better. Per-component adapters make it better still.
The Overlay Concept
What is an overlay?
A small git repo containing community-specific configuration for a Yggdrasil workspace. It declares which components to work on, how to build them, where AI context lives, and what identity to use for contributions.
Why not just put this in ecosystem.yaml?
- Shareability: One person sets up the overlay, everyone clones it. No per-machine config file edits.
- No agentic cruft in target repos: Components stay clean. The overlay provides context externally.
- Multi-community: A user contributing to SiliconSaga and a different community can switch overlays, not maintain two Yggdrasil forks.
- Separation of concerns: Yggdrasil provides methodology and tools. The overlay provides "for what and for whom."
Directory Structure
yggdrasil/
ecosystem.yaml # Upstream defaults (empty/minimal)
ecosystem.local.yaml # Per-developer overrides + optional overlay selector
components/ # Code repos (gitignored, independent git repos)
terasology/
nordri/
...
overlays/ # Config repos (gitignored, independent git repos)
overlay-yggdrasil-live/ # Active community config
overlay-yggdrasil-template/ # Tutorial/example overlay
scripts/
ws # Unified CLI — gains overlay awareness
.agent/ # GDD skills, templates
docs/ # Methodology and getting-started docs
Both components/ and overlays/ are gitignored with a .gitkeep tracked.
Overlay Repo Structure
overlay-yggdrasil-live/ # e.g. SiliconSaga/overlay-yggdrasil-live on GitHub
ecosystem.yaml # Components, defaults, identity
adapters/ # Per-component config (optional)
terasology.yaml
nordri.yaml
vordu.yaml
README.md
ecosystem.yaml (overlay)
defaults:
chartRegistry: oci://ghcr.io/siliconsaga
gitOrg: https://github.com/SiliconSaga
gitea:
internalUrl: "http://gitea-http.gitea.svc.cluster.local:3000/nordri-admin/{repo}.git"
identity:
agent_account: agent-refr
co_authored_by: "Claude Opus 4.6"
# human_account is personal — set in ecosystem.local.yaml
components:
nordri:
tier: 1
chartVersion: "0.0.0"
path: "platform/fundamentals"
namespace: argocd
terasology:
tier: 3
chartVersion: "0.0.0"
chartName: "ts-game"
namespace: terasology
# ... other SiliconSaga components
Adapter files (per-component)
# adapters/terasology.yaml
commands:
build: "./gradlew build"
test: "./gradlew test"
run: "./gradlew run"
clean: "./gradlew clean"
ai_context:
# Freeform pointers for GDD orientation to discover
- path: "CONTRIBUTING.md"
description: "Contribution guidelines and PR conventions"
- path: ".groovy/scripts/"
description: "Groovy utility scripts for content authoring"
- path: "docs/architecture.md"
description: "Module architecture overview"
Adapter files are optional. Components without an adapter file use auto-detection fallbacks.
Overlay Detection and Selection
Naming convention
overlay-yggdrasil-live— the active community overlayoverlay-yggdrasil-template— ships with tutorials, used when no live overlay exists
Lookup order
1. Selector in ecosystem.local.yaml (if set)
2. overlays/overlay-yggdrasil-live (if present)
3. overlays/overlay-yggdrasil-template (if present)
4. None — upstream ecosystem.yaml only
Optional selector
# ecosystem.local.yaml
# overlay: overlay-yggdrasil-live # uncomment to override auto-detection
The selector enables switching between overlays (e.g. live vs test) without moving directories. Auto-detection works for the common case; the selector is there when you need it.
Config Merge
Three-layer merge, applied in order:
ecosystem.yaml (upstream Yggdrasil — empty defaults)
↓ deep merge
overlay/ecosystem.yaml (community config)
↓ deep merge
ecosystem.local.yaml (per-developer overrides)
Merge semantics
- Deep merge using
yq— nested keys are merged recursively. If the overlay setsgitea.internalUrlbut notchartRegistry, the upstreamchartRegistrysurvives. components: overlay completely owns the component list. Upstream ships empty.identity: overlay provides, local can override individual fields.- Unknown top-level keys pass through — overlays can add custom fields.
Implementation: ws_resolve_ecosystem()
A shared shell function that produces a merged temp file. Called once at the
start of any ws command that needs ecosystem config.
ws_resolve_ecosystem() {
local base="$ROOT_DIR/ecosystem.yaml"
local overlay_file=""
local local_file="$ROOT_DIR/ecosystem.local.yaml"
local merged
# Find active overlay
local active_overlay
active_overlay="$(ws_detect_overlay)"
if [[ -n "$active_overlay" ]]; then
overlay_file="$ROOT_DIR/overlays/$active_overlay/ecosystem.yaml"
fi
# Three-layer deep merge via yq
merged="$(mktemp)"
if [[ -n "$overlay_file" && -f "$overlay_file" ]]; then
yq eval-all 'select(fileIndex == 0) * select(fileIndex == 1)' \
"$base" "$overlay_file" > "$merged"
else
cp "$base" "$merged"
fi
if [[ -f "$local_file" ]]; then
local tmp="$(mktemp)"
yq eval-all 'select(fileIndex == 0) * select(fileIndex == 1)' \
"$merged" "$local_file" > "$tmp"
mv "$tmp" "$merged"
fi
echo "$merged"
}
All ws functions that read ecosystem config use the merged file via
ws_resolve_ecosystem(). The temp file is cleaned up at script exit.
Identity and attribution
ws commit reads identity from the merged ecosystem config:
co_authored_by→ used in theCo-Authored-Bygit traileragent_account→ shared, set in the overlayhuman_account→ personal, set inecosystem.local.yaml
Attribution is built at runtime from these fields. When human_account
is unset, attribution omits the human reference. CLAUDE_MODEL env var
overrides co_authored_by when set.
ws pr and ws issue identity integration is planned but not yet
implemented.
ws CLI Changes
New commands
ws overlay init # Clone template repo → overlays/overlay-yggdrasil-template
ws overlay <git-url> # Clone community overlay → overlays/overlay-yggdrasil-live
# Errors if -live exists (only one live overlay)
ws overlay use <name> # Set active overlay in ecosystem.local.yaml
ws overlay list # Show available overlays, mark which is active
ws actions <comp> # List available adapter commands for a component
ws overlay init source: Clones from a known GitHub URL
(e.g. SiliconSaga/overlay-yggdrasil-template). The URL is configured in
upstream ecosystem.yaml under defaults.templateOverlay.
ws overlay <git-url> behavior: Always targets the overlay-yggdrasil-live
directory. If it already exists, error with guidance: "Live overlay already
exists. Remove it first or use ws overlay use to switch." Only one live
overlay at a time.
ws actions <comp> output:
=== terasology ===
Configured (from overlay):
build ./gradlew build
test ./gradlew test
run ./gradlew run
clean ./gradlew clean
Auto-detected:
(none — overlay commands take precedence)
Modified commands
ws list— reads components from merged ecosystem config. If zero components found, shows guidance: "No components declared. Runws overlay initto get started, orws overlay <url>for your community."ws clone --all— same zero-component safety check before cloning.ws clone— resolvesgitOrgfrom merged config defaults.ws test/build/run <comp>(not yet implemented) — will check adapter config before auto-detection. When an adapter defines the requested command, it replaces auto-detection for that invocation. The currentws_testauto-detection logic (Makefile → Go → Python) becomes the fallback, not the primary path.ws actions <comp>already shows what commands are configured vs auto-detected.ws commit/pr/issue(not yet implemented) — will read identity config from merged ecosystem config for attribution templates.
Adapter command resolution (planned)
ws build terasology
↓
1. Read merged ecosystem config (ws_resolve_ecosystem)
2. Active overlay has adapters/terasology.yaml?
3. "build" command defined?
→ Yes: cd components/terasology && execute mapped command
→ No: fall back to auto-detection
Auto-detection fallback (when no adapter defines the command)
The existing ws test detection logic becomes the general fallback:
gradlew present → Gradle (./gradlew <command>)
Makefile present → Make
go.mod present → Go
pyproject.toml present → Python
package.json present → npm/yarn
Nothing recognized → Error with guidance to configure adapter
Adapter commands always take precedence over auto-detection when both exist.
AI Context Discovery (Orientation Integration)
The GDD orientation skill gains overlay awareness during trust verification (Step 6):
When overlay has ai_context pointers
Read the adapter file's ai_context section. Use the pointers to know exactly which files to examine in the component. Apply trust hierarchy as usual (ecosystem = trusted, non-ecosystem = verify).
When no ai_context but component has standard files
Auto-detect:
- AGENTS.md, CLAUDE.md, GEMINI.md
- .agent/skills/*/SKILL.md
- CONTRIBUTING.md
- docs/ARCHITECTURE.md or similar
Bare project
GDD works with workspace-level skills only. The agent may suggest:
"This component has no AI context configured. Want me to explore the codebase, or should we add pointers in the overlay?"
This encourages gradual adoption without requiring it.
The Template Overlay
Ships with upstream Yggdrasil. Cloned by ws overlay init. Contains:
overlay-yggdrasil-template/
ecosystem.yaml # Example components (tutorial-friendly projects)
adapters/
example.yaml # Shows the adapter format
README.md # "Fork or copy this to create your own overlay"
The template's ecosystem.yaml would declare a few simple tutorial components — public repos that anyone can clone and explore without auth setup. The SiliconSaga game repos (terasology, destinationsol) could serve this role since they're public and have visible changes.
User Experience
New user, exploring GDD
git clone https://github.com/SiliconSaga/yggdrasil.git
cd yggdrasil
ws overlay init # gets the template with tutorial components
ws clone --all # clones tutorial components
# Start Claude Code, say hello, ask for Mentoring mode
Three commands to a working GDD session with tutorial content.
Existing community member
git clone https://github.com/SiliconSaga/yggdrasil.git
cd yggdrasil
ws overlay https://github.com/SiliconSaga/overlay-yggdrasil-live.git
ws clone --all # clones components declared in the overlay
Two ws commands after the initial clone.
Creating a new community overlay
The simplest path: fork SiliconSaga/overlay-yggdrasil-template on GitHub,
rename it, edit the ecosystem.yaml and adapter files, then:
ws overlay https://github.com/YourOrg/overlay-yggdrasil-live.git
A future ws overlay new wizard could scaffold this interactively — create
a new git repo in overlays/overlay-yggdrasil-live, copy the template
structure, and prompt for basic config (org URL, components, identity).
User-Facing Complexity Assessment
Areas where users interact with overlay concepts:
| Action | Complexity | Notes |
|---|---|---|
ws overlay init |
Low | One command, gets tutorials |
ws overlay <url> |
Low | One command, community provides the URL |
ws clone --all |
None | Same as today, just reads from overlay |
ws build/test <comp> |
None | Transparent — adapter resolution is invisible |
| Creating an overlay | Medium | Requires understanding the ecosystem.yaml format and adapter files |
| Switching overlays | Low | ws overlay use <name> |
| Writing adapter files | Medium | YAML config, but only needed for custom build systems |
The common path (clone, overlay, work) is 2-3 commands with no config file editing. The medium-complexity actions (creating overlays, writing adapters) are one-time setup tasks done by a community maintainer, not every user.
Migration
Clean cut, no backward compatibility scaffolding:
- Create
overlays/directory structure in upstream Yggdrasil - Create
overlay-yggdrasil-liverepo on SiliconSaga GitHub with current ecosystem.yaml content + adapter files - Create
overlay-yggdrasil-templatewith tutorial content - Implement
ws overlaycommands - Empty upstream
ecosystem.yaml - Update docs and getting-started
- Test on fresh workspace, then pull into existing workspaces
Timing: implement on one machine while the other stays on current setup. Validate, then migrate.
Future Directions
ws overlay newwizard — interactive setup for creating a community overlay from scratch- Overlay inheritance — an overlay could extend another overlay (e.g. a team overlay extends the org overlay). Not needed yet.
- MCP server config in overlays — component-specific MCP servers declared in adapter files, started on demand
- Per-environment overlays —
overlay-yggdrasil-staging,overlay-yggdrasil-prodfor different deployment targets - Overlay marketplace/registry — discover community overlays. Very distant future.