Files
executus/CLAUDE.md
T
steve ca243a2d50
executus CI / test (push) Failing after 24s
P0: stand up executus harness module above majordomo
Batteries-included agent-harness base, extracted from mort's agent layer.
This first cut establishes the module + the zero-coupling core primitives:

- lane, dispatchguard, pendingattach, run/progress.go: moved verbatim from mort
- config: host config Source seam + env-var default (nil-safe helpers)
- deliver: output-egress seam + Discard/Stdout defaults
- identity: AdminPolicy + MemberResolver seams (nil-safe)
- fanout: programmatic N×M swarm (bounded global + per-key concurrency)
- README/CLAUDE.md with the vibe-coded banner; CI with Go gates +
  the "core stays majordomo+stdlib only" invariant

Core builds with stdlib only today; majordomo enters at P1 (model/structured).
go build/vet/test -race all green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 19:18:37 -04:00

4.7 KiB
Raw Blame History

executus — developer & agent guide

⚠️ This project is vibe-coded (AI-authored, human-steered). See README.md.

executus is a batteries-included base for LLM agent harnesses, layered strictly above majordomo. majordomo is the lean substrate (agent loop, llm types, providers, media, parse/failover/tiering). executus is the opinionated layer majordomo deliberately omits. executus requires no majordomo changes — it decorates llm.Model and wraps majordomo/agent.Agent.

North star

A brand-new project imports executus, does a little setup, and is most of the way to agentic capabilities. The mechanism is one shipped default per seam: executus.New() (once the runtime lands) is agentic with zero host wiring; the same builder lets a serious host swap each default for its own implementation and register its own tools.

Two consumers define the envelope:

  • mort (heavy) — Discord, mortbux, media, MySQL/GORM, DB-backed convar config, saved skills, audit, scheduling, run-critic.
  • gadfly (light) — a CI PR-reviewer Docker image, env-var configured, running an N-models × M-lenses structured-output swarm. Needs model fleet, lanes, bounded runs, structured output, fan-out, a few read tools — and none of the batteries.

That spread is why executus is tiered: a light host imports core only; a heavy host opts into batteries.

Module & layering

One module gitea.stevedudenhoeffer.com/steve/executus, go.mod = majordomo + stdlib only (no gorm/redis/discordgo/cgo). A second nested module contrib/store carries the SQLite dependency so the core never inherits it.

CORE (majordomo + stdlib):
  config/   ConfigSource seam (+ env default)            [P0 ✓]
  lane/     bounded fair-share worker pool               [P0 ✓]
  fanout/   programmatic N×M swarm                       [P0 ✓]
  deliver/  output egress seam (+ Discard/Stdout)        [P0 ✓]
  identity/ caller identity seams                        [P0 ✓]
  run/      progress bridge now; the executor kernel +   [P0 partial]
            nil-safe Ports + RunnableAgent later         [P2]
  dispatchguard/  loop/depth/fan-out caps                [P0 ✓]
  pendingattach/  attachment dedupe                      [P0 ✓]
  tool/     registry + 3-stage permissions + ssrf/llmmeta [P1]
  model/    config-driven tier resolution over majordomo [P1]
  compact/  context compactor (WithCompactor hook)       [P2]
  tools/{web,net,store,compose,meta,comms}  generic tools [P3]
  structured/  Generate[T] convenience over majordomo    [P1]

BATTERIES (opt-in siblings, each nil-safe + a default):
  persona/   Agent noun + AgentStore seam + yml loader   [P4]
  skill/     rich Skill + SkillStore seam + toml loader  [P4]
  audit/     run-trace Sink (+ Noop/Slog)                [P4]
  critic/    two-tier timeout state machine + Escalator  [P4]
  schedule/  cron runner cores                           [P4]
  checkpoint/ durable resume seam                        [P4]
  budget/    rolling-window tracker (+ NoOp)             [P4]

contrib/store/   SECOND module (+ modernc.org/sqlite):   [P4]
  in-memory + pure-Go SQLite impls of every *Store seam

The one architectural move

The kernel must import no battery. In mort today, agentexec imports agents, agentcritic, and skillaudit directly — those three up-pointing edges get inverted into nil-safe run.Ports interfaces (PaletteSource, Critic, Audit) plus a RunnableAgent DTO. Everything else is wide-but-shallow repackaging.

Invariants (enforced in CI)

  • The core module builds with majordomo + stdlib only. go.sum must not contain gorm/redis/discordgo/sqlite/gin.
  • No core/* package imports a battery/* package.
  • Standard Go gates: go build, go vet, go test -race, go mod tidy clean.

Extraction roadmap

P0 module + zero-coupling moves + core seams (this) → P1 tool registry + model → P2 run kernel + Ports inversion → P3 generic tools + defaults → P4 persona/skill redesign + batteries + SQLite store → P5 gadfly on core (light-tier canary) → P6 rewire mort + tag v0.1.0. The mort-side rewrite reuses mort's existing mort_*_adapters.go wall as the host adapter layer.

Conventions

  • Mirror majordomo's house style: gofmt; check errors immediately and wrap with fmt.Errorf("...: %w", err); // Why: comments where rationale isn't obvious; hermetic tests (majordomo's fake provider; no network in the default suite).
  • Every seam is an interface with a nil-safe accessor and a shipped default.
  • Keep the core seam surface small and stable — push churn into tools and host adapters, not core interfaces.