Skip to content

Adapter Surfaces & Plugins

An adapter surface is a thin adapter: its only integration with the core is the ea CLI (JSON on stdout + exit codes — cli.md); it holds judgment, never business logic. Two surfaces exist — a Claude Code plugin (plugins/ea-claude/) and a Google Antigravity plugin (plugins/ea-antigravity/) — hosting the same judgment agents. The core is surface-independent: both hosts drive the identical engine, and neither requires any core change to exist.

The boundary rule (non-negotiable)

A plugin never:

  • serializes YAML, computes confirmation tokens, or decides validity — those are core;
  • writes the repository directly — only via guarded ea commands;
  • keeps authoritative state outside the source of truth;
  • holds hardcoded artifact/method/field vocabulary in its prompt — it learns everything at runtime from the core (ea method list, scaffold guidance, ea type show/method show, --list-fields, preset list/pack show).

The raw ea CLI remains the contract's reference interface underlying every surface.

The authoring contract (scaffold + commit)

Authoring one artifact is two complementary guarded writes sharing one addressing (<type> --id <id> + scope + optional --domain):

Step Command Produces
Scaffold ea scaffold <type> --project <id> --id <id> [--domain <d>] [--name <n>] the deterministic skeleton file from the type alone + authoring guidance
Commit ea commit <type> --project <id> --id <id> [--domain <d>] --input - the skeleton filled with judgment (field values, relationship targets, body prose)
  • scaffold creates (refuses if the file exists); commit updates (refuses if absent, hint "run ea scaffold first"). Identity (domain/type/id — the path key) is set once at scaffold and immutable thereafter; commit carries only content.
  • Domain inference: the manifest's domain→types map decides — permitted in exactly one domain → inferred; in more than one → --domain required (usage error naming the candidates); in none → usage error.
  • Scaffold derivation (from the type alone, no templates): envelope from the args; type fields keyed only when required (typed-empty placeholder) or carrying a schema default; optional fields without a default omitted; every relationship id present as [] — never pre-filled with targets (which target a reference points at is judgment, even with one candidate). Body empty. Guidance is returned in the plan data, never written into the file:
{ "plan": { "creates": ["projects/payments/business/capability/billing.md"] },
  "confirmation_token": "sha256:…",
  "stub": { "domain": "business", "type": "capability", "id": "billing", "name": "billing",
            "owner": "", "governed-by": [] },
  "guidance": { "fields": [ { "name": "owner", "description": "Owning team or function." } ],
                "relationships": [ { "name": "governed-by", "target_type": "principle",
                                     "cardinality": "1..*",
                                     "candidates": [ { "scope": "payments", "type": "principle",
                                                       "id": "data-locality", "name": "…" } ] } ],
                "steps": [ { "guide": "State the principle(s) that govern each capability.",
                             "produces": "principle" } ] } }

candidates are the existing artifacts of an allowed target type visible from this scope (own scope + Org), so the agent picks targets from a concrete list. steps are the active methods' steps whose produces matches the type. - Commit stdin payload (the judgment — the core serializes, never the agent):

{ "front_matter": { "name": "Billing", "owner": "finance",
                    "governed-by": [ { "type": "principle", "id": "data-locality" } ] },
  "body": "Billing handles invoicing and dunning.\n" }

front_matter is a patch merged over the skeleton; it MUST NOT restate domain/type/ id (identity is the address — restating it is a usage error). body is stored verbatim. - Commit dry-run returns data.plan, the token, a preview of the assembled artifact, and data.diff — a deterministic unified diff against the file currently on disk (skeleton → filled for a first commit; exactly the delta for a re-commit; "" on a no-op; dry-run only). The update token binds the prior on-disk fingerprint as well as the new content, so a concurrent edit is caught.

Single-artifact validation boundary

commit validates the artifact in isolation — everything decidable from the artifact + active definitions + manifest, with no other artifact loaded:

Check At commit?
Envelope present & path-consistent blocks
type active; (domain, type) permitted blocks
Type field schema blocks
Relationship cardinality + target_type + reference shape blocks
reference_resolves, unique, must_be_referenced, acyclic, layering deferred to ea validate

A self-invalid artifact returns status: invalid (exit 3) with no confirmation token — a broken write cannot be confirmed; the agent revises and re-plans. Cross-artifact rules staying with validate keeps authoring order free (commit billing before data-locality exists; validate flags the dangling reference until it's authored).

Propose → review → confirm

Every write every surface performs is one loop, identical interactive and headless:

  1. Propose. Run the command (dry-run). Parse data.plan + data.confirmation_token (for commit, also preview and diff).
  2. Review. Render the plan to the user: files touched, the preview/diff, any diagnostics. On status: invalid (exit 3, no token), surface the errors and re-plan after revising.
  3. Confirm. On explicit user approval, re-run the identical command with --confirm <token>. On exit 4 (drift), re-plan.

Token ergonomics: derive a fresh token immediately before each confirm — never hold one across another write (every write moves the repo and stales held tokens).

Plugin packages

plugins/ea-claude/
  .claude-plugin/plugin.json        # host manifest (author, keywords)
  commands/ea.md                    # /ea launcher — minimal non-negotiable write rules
  skills/ea-architect/              # the judgment + advisory agent
    SKILL.md                        #   lean spine
    reference/*.md                  #   flow files, loaded on demand
  skills/ea-methodologist/          # the pack-authoring agent (see packs.md)
    SKILL.md + reference/*.md

plugins/ea-antigravity/
  plugin.json                       # host manifest (skills/commands path arrays)
  commands/ea.md                    # byte-identical to ea-claude's
  skills/ea-architect/  …           # same skills, same structure
  skills/ea-methodologist/ …

Host-sync invariant (guarded by tests): all reference/ files are 100% host-agnostic and byte-identical across the two plugins, synced by verbatim copy. The two SKILL.md bodies are identical except a single marked <!-- host: … --> comment under the H1; plugin.json is per-host. commands/ea.md is byte-identical and host-agnostic.

Antigravity packaging notes: a plugin is a directory bundle staged under ~/.gemini/antigravity-cli/plugins/<name>/; plugin.json accepts name, version, description, and path arrays skills/commands/agents/hooks/mcpServers — a thin adapter uses only skills + commands. A skill's front-matter is only name + description (the trigger); a command is sugar for an entry-point skill. There is no always-on rules layer in the installed format, so the boundary lives in the skill + command, loaded on trigger. agy plugin validate is the binding schema check.

The ea-architect skill

The judgment + advisory agent: an EA guide that tailors, authors, promotes, migrates, reads, and advises — entirely over the CLI. One skill, multi-file progressive disclosure (spine < 500 lines; references one level deep; no bundled scripts):

ea-architect/
├── SKILL.md            # lean spine — identity, boundaries, contract + exit-code map,
│                       #   the one write protocol, a flow index, the self-check
└── reference/
    ├── discovery.md        # presets & packs (list/show; discover-and-offer, never default)
    ├── tailoring.md        # Flow A — adopt archetype; manifest domain/relationship/rename verbs
    ├── authoring.md        # Flow B — scaffold → draft → commit (+ read-before-draft,
    │                       #   token ergonomics, showing data.diff at review)
    ├── promotion.md        # Flow C — promote to Org
    ├── migration.md        # ea migrate (archetype + pack@version)
    ├── reading.md          # validate / report / graph + projection
    ├── advising.md         # state synthesis ("where am I") + grounded next-steps
    └── running-methods.md  # guided method run (see below)

Key taught behaviours (all runtime-discovered, nothing hardcoded):

  • Discover-and-offer: asked to tailor, enumerate the real archetypes with ea preset list/preset show and offer the actual choices — never default to a familiar name or shell to ls/find.
  • Read-before-draft: before scaffolding/committing, ea type show <type> — follow its sections to compose a well-structured multi-section body and its field guidance for the front-matter; before working a method, ea method show <id> and learn it from the detail steps.
  • Reading efficiently: project subtractively (--fields), discover the vocabulary at runtime (--list-fields; a wrong guess self-corrects via the enumerated usage error); projection never changes status/exit code, so it is always safe. Headline saver: report coverage --fields summary.
  • Advising: answer "what is the current state?" by composing the read verbs (projected) into a coherent narrative — never a raw envelope dump — and recommend concrete next actions justified by that state. Every fact is the core's; the agent interprets, never computes a verdict.
  • Review narration: render each plan (and data.diff — especially for a re-commit, where the delta is otherwise invisible) and proceed only on explicit confirmation. Explain diagnostics; never decide validity.

Guided method run (reference/running-methods.md)

A method's data is already a script for a walk-through (steps[] with guide/produces/ detail); this flow runs it as a method-agnostic, eliciting session. Triggered by "walk me through the X method" (vs. Flow B's "author a capability"):

  1. Read the method onceea method show <id>.
  2. Ground on live state, never guessreport coverage (--fields summary) + validate; skip steps whose produced types are already satisfied; resume a half-finished method from the first real gap.
  3. Walk each step in dependency order — read guide+detail to the user; elicit the substance from the user first, in their words (at most one or two seed suggestions to react to — never a pre-written set); author that step's artifacts via the Flow B inner loop, each propose → review → confirm; loop within a step for as many artifacts as the user's judgment sets.
  4. Re-ground after each write (fresh token; re-read coverage between steps).
  5. Close with an advisory summary — where the method landed you + the grounded next step.

Named forbidden anti-pattern: pre-drafting the whole architecture and taking one bulk approval. Elicit-first is the rule, not a footnote — the confirm guard covers the write, not the substance, which must be the org's, drawn out one step at a time.

There is deliberately no core cursor/method run verb: coverage already implies "where am I" (a step produces a type; coverage says whether it's satisfied), a persisted cursor can go stale, and the valuable part — the user's intent — is judgment the core can't legitimately hold. Resume is just an advising read that feeds the walk.

The ea-methodologist skill

The inverse of ea-architect: helps a user author a method pack (ideate → model types → build methods → wire rules → review + validate), one linear flow. Full description in packs.md. Same structure (lean spine + reference/), same host-sync invariant; its boundary differs deliberately — it may draft pack YAML directly (a pack is reviewed, versioned source), but ea pack validate is the mandatory gate and it holds no hardcoded schema.

End-to-end example

The canonical task, from an empty directory to a validated architecture:

  1. ea init → repo.
  2. Tailor: ea manifest adopt startup-light (dry-run) → present the domains and the materialized method as deliberate defaults → user accepts → --confirm.
  3. Author a principle (scaffold → draft → commit) and a capability whose governed-by picks the principle from the guidance candidates.
  4. Promote the principle to Org (plan shows: Org artifact created, project copy removed, outbound-reference pre-check clean) → confirm.
  5. Validate: ea validate --allstatus: ok, exit 0.

Every write confirmed before it lands; every default accepted deliberately; the agent held only judgment and drove the unchanged core through the contract.