Skip to content

v0.6.0

Choose a tag to compare

@eris-ths eris-ths released this 16 May 03:17
· 65 commits to main since this release
v0.6.0
828d214

v0.6.0 — multi-executor cut + AI-first / eris-first polish

Scope: 136 commits since v0.5.0 (compare). Three coordinated system landings (swarm, voice plugin, hooks), one breaking removal, and ~30 polish PRs driven by AI-consumer audits.

BREAKING

--executor (singular) and the executor JSON alias removed (#398, closes #239). The multi-executor surface introduced in #230 carried both forms for ~130 commits as a deprecation window.

Before After
gate request --executor miki gate request --executors miki
gate fast-track --executor miki gate fast-track --executors miki (defaults to author when omitted)
gate issues promote X --executor miki gate issues promote X --executors miki
jq .executor jq '.executors[0].name'
Domain: Request.create({ executor }) Request.create({ executors: [...] })
App: CreateRequestInput.executor CreateRequestInput.executors

Hydrate still reads the legacy executor: <string> YAML field (records-outlive-writers per principle 04). Only the input surface is removed. Request.toRenderJSON() also deleted — callers use toJSON() directly.

Swarm coordination

Multi-executor end-to-end:

  • #230 / #237executors: ExecutorRecord[] on the domain aggregate; CLI --executors a,b,c with comma-parser + duplicate rejection
  • #294 / #311 — per-executor slice status (pending / completed / failed); slice-close stamp on the actor's terminal transition
  • #350 — Synergy S4 end-to-end playbook test for multi-executor wave with any-fail-wave-fail cascade derivation

Cross-session stake primitives (closes #226):

  • gate claim <id> --by <actor> (#243) — exclusive stake
  • gate witness <id> --by <actor> (#247) — non-exclusive observer
  • Auto-release on terminal transitions (completed / failed / denied)
  • Optimistic-lock via mutation_seq; concurrent writes throw RequestVersionConflict and retry through the use-case loop

Profile concept (#233 / #231 / #242):

  • profile: standard (default) — warn on self-approve, no worktree enforcement
  • profile: swarm — forbid self-approve, auto-stamp requires_worktree_isolation: true on executors.length > 1, refuse gate execute from same cwd as a peer executing

Cross-wave / per-executor read verbs:

  • gate wave-status <id> (#298) — per-executor in-flight slice status, composes witness notes + claim state + status_log timestamps
  • gate swarm-status (#346 / #392) — cross-wave director or participant view; three alert kinds (stale_executor, overlapping_target, attribution_risk)
  • boot.active_overlapping_targets (#309) — per-actor overlap hint with claim_held marker

Voice plugin system

New in v0.6 (#345 cluster, #377#383). Four sections, each independent:

  • verbs — ornamental narration on write-verb responses; surfaced as _meta.voice on the JSON envelope and ⟶ <text> on stderr in text mode
  • schema — per-verb summary and per-flag description overrides via gate schema --voice <name> overlay (#379)
  • essentials — curated verb list driving gate --help --essentials (#381)
  • read.past_cliffs — re-renders gate boot's past-cliffs section (#382)

Resolution order: CLI flag (--voice <name>) > env (GUILD_VOICE) > config (voice.default) > none. Mode switch via gate voice <name> / gate voice (introspect) / gate voice off (#380).

Scope: gate write verbs only in v0.6. agora / devil / ctx voice extension deferred.

Lifecycle hooks

Phase 1 hook bus (#259) shipped in v0.5 for request lifecycle only. v0.6 extends to every write verb:

  • before: / after: fire points on claim, witness, issues write paths (#290)
  • fast-track (compress flow) fires all three transitions individually so policy hooks aren't bypassed (#279)
  • SessionEvent payload extended for cross-passage hook composition

Veto semantics unchanged: a before: hook returning a non-empty reason aborts the transition; the request stays in its pre-transition state.

AI-first / eris-first polish

~30 audit-driven PRs. Headline correctness fixes:

  • gate decisions mis-attributed slice-fail reasons to the executing row (#402, asteria dogfood finding D1)
  • gate transcript prose rendered slice-close stamps as a second "moved it to executing" sentence (#402, eris touch-feel finding 4.4)
  • gate fail on approved state returned raw Illegal state transition with no recovery hint (#402, finding B1)
  • gate next setup-failure errors bypassed emitErrorEnvelope, leaving JSON consumers with plain text where every other gate verb gave them a structured envelope (#401)

Drift / shape consolidation:

  • Shared parseFormat helper at src/interface/shared/parseFormat.ts replaces 55 inline format-check blocks across gate / agora / devil / ctx (#397, −134 LOC); throws DomainError(field='format') so JSON consumers get the structured envelope automatically
  • bin/_lib/handleMainError.mjs shared catch handler wired into all 5 bin entries (#396)
  • Error prefix unified to error: <msg> across gate verbs; previous gate <verb>: <msg> form removed (#397)
  • Success-path stderr notices (self-approve / executor mismatch / self-review / --comment deprecation / self-thank) suppressed in --format json mode (#400)
  • notice: wrote <path> suppressed in JSON mode for agora new, agora play, devil open (#397)

Ergonomics:

  • gate help accepted as alias for gate --help (#402)
  • gate lore show 11 resolves to 11-ai-first-human-as-projection via unique numeric-prefix match (#402)
  • boot.session_id_source: "unset" enum replaces null (#402)
  • gate schema advertises maxLength on free-form text fields (MAX_TEXT=4096, MAX_STAKE_NOTE=80) (#402)

Extension surface (principle 15)

Principle 15 promoted to lore/principles/15-plugins-as-default-extension.md (#391). Three plugin kinds operational:

  • verb plugins (#258) — .guild/plugins/verbs/*.mjs, registered into the dispatch table
  • hook plugins (#259 + v0.6 extensions above)
  • voice plugins (#377+)

Cross-tree primitive: GUILD_CONFIG=<abs path> env override (#393) skips the cwd walk-up entirely. Used when a SubAgent worktree doesn't share walk-up ancestry with the substrate. Empty string emits a stderr nudge (one-shot per process via the emptyGuildConfigNudgeFired module-private flag).

Claude Code wiring example added at examples/plugins/harness-wirings/claude-code/PostToolUse hook script that throttled-emits gate witness <id> from inheritable env (GUILD_CONFIG / GUILD_WAVE_ID / GUILD_ACTOR).

Dev ergonomics

  • .changelog/next/<category>-<slug>.md fragment system (#387); scripts/changelog-release.mjs <version> collects and folds at release time. Removes textual [Unreleased] block conflicts
  • tests/run.mjs: default TEST_CONCURRENCY 4 → 8 (#387); CI ~513s → ~200s on the same hardware
  • Request.toRenderJSON() removed; render-vs-persistence split collapsed into a single toJSON() since the deprecated alias is gone (#398)
  • writeFormat.ts:parseFormat re-export shim removed; all 9 write handlers import from shared/parseFormat.js directly (#399)

What's next

  • alpha → beta: 3 axis landings + fragment changelog + 330-commit deprecation completion together meet the "API surface stable enough to ship the next release as beta" threshold. Concrete triggers: a second downstream consumer touching the schema, or a Phase-3 federation surface needing 1.x semver
  • Roadmap epic #36: Phase 1 (extension points) and Phase 2 (time-aware verbs) shipped. Phase 3 (federation) and Phase 4 (event fabric / content transforms) are next candidates; dogfood pressure decides ordering
  • Voice plugin → agora / devil / ctx: v0.6 limited the voice extension surface to gate write verbs. Symmetric application to the other three passages is the natural follow-up
  • Hook on:save / on:load: Phase 1 deferred this for lack of concrete need. Index rebuild or derived-field use cases would surface it
  • Director-axis automation: gate swarm-status is read-only in v0.6. Wiring it as a hook trigger / scheduled aggregator is the obvious next step once a concrete consumer needs it

Full changelog: CHANGELOG.md § v0.6.0


Thanks: asteria (real SubAgent dogfood), a parallel eris instance (touch-feel report), and noir (division-protocol review across the cycle). Two friction classes surfaced only by real agent runs — cross-verb attribution drift and error-path inconsistency — would have stayed invisible to simulation-only audit.