Skip to content

Roadmap: extension points + time-aware verbs + federation + event fabric #36

Description

@eris-ths

Context

guild-cli started as "a small file-based CLI for a team of agents to file requests, review them, and leave an append-only trail." The 0.3.x stream has closed most of the first-touch friction (see #30, #31, #32, #33, #34, #35): misconfigured-cwd detection, severity/verdict/lense aliases, gate register, message/inbox guild-flow hints, content_root_health.

The core (request / review / issue / message lifecycle with Two-Persona Devil discipline) now has enough dogfood surface to start thinking about the next structural investments — the things that will let the tool grow without losing its local-first, human-readable, git-native shape.

This is a living roadmap. Individual Phases should be split into their own issues as they approach; this meta-issue exists so contributors can reason about each Phase in the context of the whole.

Status (as of 2026-05-09)

Reconciliation against current main. Phases 1 and 2 fully shipped; Phases 3 and 4 deferred per the original spec.

Phase 1 — Extension points ✅ shipped

Outstanding: Content transforms (on:save / on:load around YAML I/O) — sketched in the original Phase 1 plan but not yet shipped. Treated as Phase 4 territory now since the post-#36 dogfood didn't surface a concrete need; spin up a focused sub-issue when index-rebuild / derived-field use cases actually emerge.

Phase 2 — Time-aware verbs ✅ shipped

Phase 3 — Multi-guild / federation 🔒 deferred

Per the spec, deferred until Phases 1 + 2 are stable (now true). No work landed yet. Spin up sub-issues when concrete cross-content_root use cases surface.

Phase 4 — Event fabric 🔒 deferred

Outbound primitive (lifecycle hooks) is now in place via Phase 1. Inbound (gate import, inbound-events/, source: external) and content transforms (deferred from Phase 1) are the two remaining seams. Spin up sub-issues when concrete external integrations are wanted.

Adjacent work that landed alongside

Several feature waves shipped during Phases 1+2 even though they sit outside the original roadmap — capturing them so the roadmap stays a faithful index of the substrate:

Design principles (stable; use these to resolve ambiguity)

  1. 1 file = 1 capability. Members, requests, issues, reviews, doctor plugins — all one YAML/TS file per unit. Extension points should preserve this shape.
  2. Local-first, human-readable, git-native. No DB. No network. The content_root is the whole world. Git gives history.
  3. Append-only semantics. Corrections are new entries, not edits. status_log grows monotonically.
  4. Agent-first ergonomics. JSON output on every verb, suggested_next where meaningful, gate schema introspection, vertical-format errors with onboarding hints (see feat(ux): severity aliases + lense extension hint #31feat(boot): add content_root_health hint + one-command fix path #35 for the pattern).
  5. Stable surface, evolving infrastructure. The domain layer (Member, Request, Review, Verdict, Lense, Issue) is patch-bump stable per docs/POLICY.md. Extensions go through interface/infrastructure, not by mutating domain types.

Phases

Phase 1 — Extension points

Goal: let adopters add verbs, lifecycle reactions, and content transforms without forking.

Three extension surfaces, ordered by impact:

  • Verb plugins (.guild/plugins/verbs/*.mjs): load at CLI startup, register new verb names into the dispatch table in src/interface/gate/index.ts. Each plugin exports { name, category, summary, input, output, run(c, args) } — the same shape VerbSchema already uses for built-in verbs. Must also appear in gate schema output so LLM tool layers discover them.
  • Lifecycle hooks (.guild/plugins/hooks/*.mjs): invoked synchronously around request state transitions (before:approve, after:complete, after:review, etc). Hooks receive the request + transition context, may return { allow: false, reason } to veto (policy enforcement) or emit side-effects (write to inbox, notify external system). Must not block the transition on slow I/O — if a hook needs network, spawn and return.
  • Content transforms (.guild/plugins/transforms/*.mjs): invoked before YAML serialization (on:save) and after deserialization (on:load). Use case: index rebuild, derived field computation. Must be idempotent.

All three reuse the existing doctor plugins loading pattern (see src/application/diagnostic/DiagnosticUseCases.ts) — ES module paths listed in guild.config.yaml under plugins:. Plugin execution is sandboxed only by Node's module system; document the trust model in SECURITY.md.

Acceptance criteria:

  • A minimal example plugin (verb, hook, transform — one of each, under examples/plugins/) that works end-to-end.
  • gate schema surfaces plugin verbs with a source: plugin marker so a consumer can distinguish.
  • gate doctor reports plugin load failures without breaking the CLI.
  • Tests cover: plugin loading order, conflict with built-in verb names (reject), missing plugin file (warn + continue), hook veto propagation.
  • docs/POLICY.md gets a paragraph on plugin stability (additive only, no renaming the hook signature without a minor bump).

Phase 2 — Time-aware verbs

Goal: make the passage of time a first-class record, not an implicit side effect of logging.

Candidate verbs (exact names / semantics TBD in sub-issues):

  • gate rest — boundary record. Not a lifecycle toggle; just "I am putting this down now." Timestamps only; no mandatory wake note (that would turn it into reflect). Rationale: the length of a break is itself information, the way a commit timestamp is information.
  • gate wake — optional pairing verb that says "I am picking things back up." Decoupled from rest so they don't have to be used together.
  • gate farewell — ceremonial close meant to be paired with gate resume at the next session start. Different from rest because it is "until next session," not "until later today."
  • gate resume (exists) — reads the last voice / transition / open loops, composes restoration prose. May gain interaction with rest / wake / farewell records.

Why time-aware verbs at all: agents (human or AI) accumulate fatigue or context drift inside long sessions. Marking the boundaries in-band lets downstream verbs (tail, voices, resume) render the session with the boundaries visible, which changes how the next reader experiences the history.

Interaction with Claude Code's compact + preserved-tail-relinking and with multi-session workflows is an open design question. Spin up a sub-issue when Phase 1 is ready to merge.

Phase 3 — Multi-guild / federation

Goal: let a content_root reference records in another content_root without losing append-only guarantees.

Sketch: gate federate <path> publishes a read-only reference. show / tail / voices can walk cross-root when the reference is resolvable. Actors can belong to multiple guilds; pair-mode (--with) can refer to actors from federated roots.

This is the structural answer to "small pairs would silo themselves" — the tool should let neighboring pairs see each other's work without collapsing into a single content_root.

Defer concrete spec until Phase 1 + 2 are stable; federation affects every reader verb.

Phase 4 — Event fabric (external integrations)

Goal: bidirectional bridges between guild-cli and external systems — MCP, Slack, GitHub, etc — without making those systems authoritative.

  • Outbound: lifecycle hooks (Phase 1) already handle the side. Just add documented conventions for where to send.
  • Inbound: gate import <event> or an inbound-events/ directory that plugins drain. Imported events become first-class records (with source: external in YAML) but are auditable as such.

Authoritative store always stays in content_root/. External systems are views or feeds, never truth.

Out of scope (for this roadmap)

  • Specific persona scaffolding, voice characters, or identity-specific verbs. Those belong in downstream adopters' plugin sets, not in core.
  • Semantic search / embedding-based retrieval. grep + filters is intentionally the search story.
  • Database backend. Not happening.
  • GUI / web UI. Separate project if it appears.

How contributors should proceed

  • Phases 1 + 2 are now shipped; the natural next-frontier work is Phase 3 (federation) or Phase 4 (inbound events / content transforms) when concrete dogfood pain demands them. Both are deferred until that pain emerges.
  • When in doubt about a design choice, resolve toward the five principles above.
  • The existing onboarding-hint pattern (vertical-format errors, hints.* fields on reads, actionable error messages) is how "this feature is discoverable" shows up in this codebase. New surfaces should carry the same pattern.

Pointers

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions