Skip to content

RFC: First-Class Construct Support in Loa #452

@zkSoju

Description

@zkSoju

Intent & Purpose

Loa should support how people actually work — not prescribe how they should work.

Everyone is different. Some people work like a dagger — singular focus, one context window, precise cuts until the problem is solved. Some work like a conductor — steering between perspectives, composing on the fly, mode-switching when the energy shifts. And there are styles we haven't seen yet. The diversity of human cognition means there will always be more ways to work than we can anticipate.

Constructs are expertise packaged as composable building blocks. Loa is the environment where those blocks get assembled into personal workflows. The Operator OS — where a user defines named modes mapped to construct compositions — is one methodology for this, designed by one user for their own ADHD-aware cognitive patterns. It's not universal. It's an example of what becomes possible when the environment supports evolution.

The framework's job is not to build tools for other people. It's to build structure that helps people do deeper work for themselves and better learn how they work. It's just a game. There's many ways to play and no right way to play. We provide an environment where evolution can happen.

This RFC proposes the infrastructure to make that environment real: a construct index for awareness, name resolution for activation, composition pipes for connecting constructs, and ambient presence so the framework is there when you need it and invisible when you don't.


Context

This RFC emerges from a deep DX session examining how constructs should integrate with Loa, grounded in a full bazaar audit of all 24 live constructs and research into progressive disclosure patterns from game design (RuneScape, Dark Souls, BOTW) and developer ecosystems (skills.sh, lazy.nvim, Homebrew).

Companion RFC: loa-constructs#181 covers the network side — install surface, explorer, and schema hygiene sprint.

Origin: Conversation between @janitooor and @zkSoju about better tooling support when not on golden path rails, and first-class support for the constructs network.

Problem Statement

Construct composition already happens in practice. Users manually orchestrate multi-construct workflows — naming agents by construct in TeamCreate, piping dig findings into observer canvases, getting adversarial review from construct-specific perspectives. The pattern is proven. The infrastructure to support it consistently is missing. This RFC makes explicit what's already implicit.

Loa creates awareness of constructs but not to the precision needed for natural use.

The Concrete Failure

When the user says "observer" or "I want to use K-Hole for deep research," the agent doesn't load the persona or activate the construct context without heavy prompting. Constructs are files in directories. They should be entities with presence.

Composition requires explicit manual invocation every time. "These constructs should work together" requires the user to orchestrate each step. "Adversarial review from these standpoints" requires the user to name each agent, specify each persona, describe the composition. The user IS the pipe. The framework should be.

What Loa Knows vs. What It Should Know

Layer Current Needed
Phases plan, build, review, ship No change
Modes Personal cognitive modes (user-defined, e.g. Operator OS) Modes should compose with constructs via an archetype resolver
Protocols beads, QMD, flatline Protocols should run by default and leave ambient evidence — currently they only activate when explicitly named
Constructs Directories in .claude/constructs/packs/ Name resolution, composition runtime, ambient awareness

The framework knows about phases, modes, and protocols. It does not have a construct layer — no name resolution, no composition routing, no ambient awareness of what's installed or how constructs connect.

The Protocol Consistency Gap

Protocols (beads, QMD, phases) don't run unless the user explicitly names them. If the user says "use beads," it happens. If they don't, it doesn't. QMD gets stale because it's never updated. The agent uses grep instead of QMD. Beads don't track work outside explicit sprints.

The result: the user says "let's wrap this up," the agent revisits what it did. But if the user forgets, the work is abandoned. Open threads are lost because nothing was tracking them.

This isn't "protocols run but aren't visible." Protocols don't run at all unless explicitly invoked. The concierge isn't too intrusive — the concierge isn't at the desk.

The Unix Pipe Gap

The user describes constructs as Unix tools: composable, pipeable, adversarial-reviewable. Examples of what should work consistently:

  • "K-Hole's findings should feed Observer" → pipe dig output to observer input
  • "Adversarial review from these standpoints" → spawn agents by construct, each brings its expertise
  • "These constructs should work together for this" → composition activates automatically

Currently this requires explicit, manual orchestration every time. The user is the pipe. The framework should be.

The Off-Rails Gap

The golden path (/plan → /build → /review → /ship) works for structured projects and is relatively simple — most workflows can map to it. But most daily work is off-rails — visual iteration, quick research, freestyle exploration. This space has no structure.

Important insight: activities like deep research and design exploration are often pre-planning activities. They build context that makes /plan better. They're not alternatives to the golden path — they're inputs to it. The golden path assumes you arrive at /plan already knowing what you want. The pre-planning is how you figure out what you want.

Design Principles

The Hotel Experience Paradox

From Octalysis Group (Yu-kai Chou): the more hotels automate personalization, the less personal it feels. "Not special, but watched."

Loa has the same risk. Protocols that run invisibly feel like a broken surveillance system — you know they're supposed to be watching, but you can't tell what they see. The fix isn't more automation — it's the concierge model:

Hotel Drive Loa Equivalent
Earned recognition (remember me because we've MET) Know my constructs because I've USED them, not because you scanned my config
Agency (let me shape the stay) Let me design my own modes, compose my own constructs, pipe them my way
Surprise & discovery (show me something I didn't know existed) Surface compositions I haven't tried, constructs adjacent to what I use
Human connection (the staff, not the system) The persona voice, not the protocol enforcement

The framework should be:

present options → honor the choice → step aside → be there when called

Not:

detect intent → enforce protocol → track compliance → report status

Everyone Works Differently

Loa must support the full spectrum of working styles — not just two, but the unbounded diversity of how people actually think and create:

  • The dagger — one context window, singular focus, precise cuts. Golden path rails are natural. Deep task tracking with beads. One problem until it's solved. The entire context window is used for a singular task. Very little steering needed.
  • The conductor — multiple perspectives, steering between modes, composing on the fly. Agent swarms / TeamCreate is natural. Quick iteration, visual feedback, mode-switching when the energy shifts.
  • Styles we haven't seen yet — every person's cognition is different. Some will be visual-first. Some will be research-first. Some will work in bursts, others in sustained focus. Some will use the golden path for everything. Some will never touch it. We cannot predict the diversity.

The framework doesn't adapt for any single style. It builds the flexibility that supports ALL mental models. The Operator OS (FEEL/ARCH/DIG/SHIP modes) is one user's personal cognitive toolkit — designed for their ADHD-aware mode switching. It's not universal. It's an example of what becomes possible when the environment supports self-composition.

Loa's role: help people discover how they work best, not tell them how to work. The modes emerge from use. The compositions emerge from exploration. The personal OS emerges from the person.

Game Design Progressive Disclosure

Three types of progressive disclosure map to three DX surfaces:

Type Game Reference Loa Surface
Functional (interface reveals one tab at a time) RuneScape Tutorial Island The install CLI — one construct at a time
Spatial (world reveals connections through shortcuts) Dark Souls interconnected world The composition graph — connections discovered through use
Systemic (rules reveal depth through emergent combinations) BOTW's four runes Construct composition — universal pieces that combine in ways the designers didn't predict

The ecosystem should be felt before it's understood. Not explained, not onboarded — felt. The way RuneScape's skill tab works by always being there. The way Dark Souls' world reveals connections only after you've walked the long way.

Proposals

L1: Construct Index (Keystone — Unblocks Everything)

A machine-readable file generated on session start that maps every installed construct to its activation paths:

# .run/construct-index.yaml (generated by sync-packs.sh extension)
constructs:
  k-hole:
    persona: grimoires/personas/STAMETS.md
    quick_start: /dig
    skills: [dig, deep-research, domain-discovery, ...]
    commands: [dig, forge, discover, config, research]
    writes: [grimoires/k-hole/research-output/]
    reads: []
    gates: {}
    composes_with: []
  observer:
    persona: grimoires/personas/KEEPER.md
    quick_start: /observe
    skills: [observing-users, shaping-journeys, ...]
    commands: [observe, ...]
    writes: [grimoires/laboratory/canvases/, grimoires/laboratory/journeys/]
    reads: [grimoires/k-hole/research-output/]
    gates: {}
    composes_with: [crucible, artisan]

Generated, not authored. sync-packs.sh already runs on session start — extend it to produce this index. The CLAUDE.md instruction tells the agent to check this file when a construct name is mentioned.

Blast radius: One file, one script extension. Non-breaking. Falls back gracefully if file doesn't exist.

Dependency: Requires the network-side schema hygiene sprint (loa-constructs#181 P4) to populate workflow.gates, quick_start, and composition_paths across the 24 stalls.

L2: Name Resolution

When the user says "observer", "use observer", "I want K-Hole's perspective":

  1. Look up the name in .run/construct-index.yaml
  2. Load the persona file
  3. Activate the construct's skill set as primary context
  4. Set the construct's read/write paths as active grimoire scope

Implementation: CLAUDE.md instruction addition that references the construct index. No code change needed — the index file does the work.

Note: Command name collisions (/observe = gecko vs observer, /dig = k-hole vs hypha) need to be resolved on the network side first. The index should use construct slugs as the primary identifier, with commands as secondary routing.

L3: Composition as Pipe

When the user says "pipe dig into observe" or "K-Hole's findings should feed Observer":

  1. Check construct index for K-Hole's writes paths
  2. Check Observer's reads paths
  3. Confirm the material chain exists (path overlap)
  4. Execute K-Hole's skill, pass output path to Observer's skill

If no material chain exists, the agent says so honestly: "K-Hole writes to grimoires/k-hole/research-output/. Observer doesn't currently read from there. Want me to connect them?"

For TeamCreate composition: When spawning agents named by construct ("observer", "k-hole", "artisan"), each agent should auto-load its persona from the construct index. The naming convention should trigger persona loading:

Agent(name="observer", team_name="review-council")
# → auto-loads KEEPER.md persona, observer skills, observer read/write paths

This makes construct-named teams the standard pattern for multi-perspective work. The user said: "if you label each of the team members by constructs, it'll be very clear to me that these things are happening."

Feedback routing: When a construct-embodied agent identifies an issue, route it to the construct's repo (if declared in construct.yaml repository field), not to Loa. Gecko should be able to walk stalls and open targeted, high-quality issues on construct repos.

L4: Personal Operator OS Support

The golden path is the main quest. Everything else — daily work, visual iteration, research, exploration — is the open world.

Operator OS is a methodology, not a feature. It's the practice of:

  1. Noticing which cognitive state you're in
  2. Naming it (giving it a mode)
  3. Mapping constructs to that mode
  4. Trusting the isolation between modes
  5. Switching when the energy shifts

One user's implementation: FEEL/ARCH/DIG/SHIP — four modes mapped to constructs (artisan, arcade, k-hole, arcade). Another user might have three modes, or six, or entirely different names. A visual designer might have SKETCH/REFINE/CRITIQUE/SHIP. A security engineer might have SCAN/TRACE/HARDEN/DEPLOY.

What Loa provides:

  • Construct composition — combine any constructs into a working set (the "archetype")
  • Mode definitions — users can define their own modes, each with a name, construct set, and workflow gates
  • Mode switching — when you say a mode name, the archetype activates
  • Isolation guarantees — modes don't bleed into each other

The archetype resolver reads installed constructs' workflow.gates and merges them:

# .run/archetype.yaml (example — user-defined, not prescribed)
active_constructs: [observer, artisan, k-hole]
merged_gates:
  prd: skip
  implement: required
  review: visual
entry_point: /observe

When no archetype is active, Loa operates normally. Users opt in by invoking a construct or mode. Never forced. The framework helps people discover how they work — it doesn't tell them how to work.

What Loa does NOT provide:

  • A prescribed set of modes
  • A "correct" way to compose constructs
  • A required workflow for off-rails work

L5: Ambient Protocol Presence

Protocols should run by default and leave ambient evidence — not as blocking gates, but as the concierge being present at the desk.

Protocol defaults:

  • QMD: kept warm, preferred over grep for codebase search, updated on file changes
  • Beads: lightweight "open threads" mode even outside sprints — tracking discussed items so nothing falls through
  • Session greeting: if constructs are active, surface a brief ambient greeting:
Active: k-hole (v1.2.1), artisan (v1.0.0), observer (v3.0.0)
Compositions: k-hole → observer (research → canvases)
Entry: /dig | /feel | /observe
Beads: 3 open threads from previous sessions

Not a dashboard. A greeting from the concierge. Visible when relevant, silent when not.

Open thread awareness: The agent maintains a lightweight log of discussed-but-not-completed items. On session start, surfaces any stale threads: "3 open threads from previous sessions. Want to review?" This is beads-light — the concierge's notepad.

Sequencing

Network P4 (schema hygiene) → L1 (construct index) → L2 (name resolution) → L3/L4/L5
  1. Network-side schema hygiene — populate workflow.gates, quick_start, composition_paths across 24 stalls
  2. L1 (construct index) — extend sync-packs.sh to generate .run/construct-index.yaml
  3. L2 (name resolution) — CLAUDE.md instruction to check index on construct name mention
  4. L3 (composition pipe) — path-based composition routing
  5. L4 (personal OS support) — archetype resolver reads index + gates
  6. L5 (ambient presence) — session greeting + protocol defaults + open thread tracking

L1 is the keystone. Everything flows from the index.

Out of Scope

  • Network-side changes (install command, explorer, schema hygiene) → loa-constructs#181
  • Construct certification / OSINT verification → separate initiative
  • Prescribing specific workflows or mental models → explicitly excluded
  • Building a specific Operator OS for all users → the framework supports building personal ones

Questions for Discussion

  1. Should the construct index be YAML or JSON? YAML is human-readable, JSON is faster to parse.
  2. Should L2 (name resolution) be a CLAUDE.md instruction or a hook? Instruction is simpler. Hook could auto-inject the index into context.
  3. How should L3 handle composition when the material chain doesn't exist? Suggest connecting? Auto-create the path? Just warn?
  4. Should L5 (ambient greeting) be opt-in or opt-out? The hotel paradox suggests opt-in is safer.
  5. How do we support users building their own Operator OS (personal modes, personal workflows) without the framework becoming too flexible to be useful?
  6. What should protocol defaults look like? QMD warm by default is useful but has compute cost. Beads tracking open threads by default is useful but adds noise. Where's the line?

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions