v0.6.0
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/#237—executors: ExecutorRecord[]on the domain aggregate; CLI--executors a,b,cwith 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 stakegate witness <id> --by <actor>(#247) — non-exclusive observer- Auto-release on terminal transitions (completed / failed / denied)
- Optimistic-lock via
mutation_seq; concurrent writes throwRequestVersionConflictand retry through the use-case loop
Profile concept (#233 / #231 / #242):
profile: standard(default) — warn on self-approve, no worktree enforcementprofile: swarm— forbid self-approve, auto-stamprequires_worktree_isolation: trueonexecutors.length > 1, refusegate executefrom 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 timestampsgate 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 withclaim_heldmarker
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.voiceon the JSON envelope and⟶ <text>on stderr in text modeschema— per-verbsummaryand per-flagdescriptionoverrides viagate schema --voice <name>overlay (#379)essentials— curated verb list drivinggate --help --essentials(#381)read.past_cliffs— re-rendersgate 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 onclaim,witness,issueswrite 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 decisionsmis-attributed slice-fail reasons to theexecutingrow (#402, asteria dogfood finding D1)gate transcriptprose rendered slice-close stamps as a second "moved it to executing" sentence (#402, eris touch-feel finding 4.4)gate failonapprovedstate returned rawIllegal state transitionwith no recovery hint (#402, finding B1)gate nextsetup-failure errors bypassedemitErrorEnvelope, leaving JSON consumers with plain text where every other gate verb gave them a structured envelope (#401)
Drift / shape consolidation:
- Shared
parseFormathelper atsrc/interface/shared/parseFormat.tsreplaces 55 inline format-check blocks across gate / agora / devil / ctx (#397, −134 LOC); throwsDomainError(field='format')so JSON consumers get the structured envelope automatically bin/_lib/handleMainError.mjsshared catch handler wired into all 5 bin entries (#396)- Error prefix unified to
error: <msg>across gate verbs; previousgate <verb>: <msg>form removed (#397) - Success-path stderr notices (self-approve / executor mismatch / self-review /
--commentdeprecation / self-thank) suppressed in--format jsonmode (#400) notice: wrote <path>suppressed in JSON mode foragora new,agora play,devil open(#397)
Ergonomics:
gate helpaccepted as alias forgate --help(#402)gate lore show 11resolves to11-ai-first-human-as-projectionvia unique numeric-prefix match (#402)boot.session_id_source: "unset"enum replacesnull(#402)gate schemaadvertisesmaxLengthon 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>.mdfragment system (#387);scripts/changelog-release.mjs <version>collects and folds at release time. Removes textual[Unreleased]block conflictstests/run.mjs: defaultTEST_CONCURRENCY4 → 8 (#387); CI ~513s → ~200s on the same hardwareRequest.toRenderJSON()removed; render-vs-persistence split collapsed into a singletoJSON()since the deprecated alias is gone (#398)writeFormat.ts:parseFormatre-export shim removed; all 9 write handlers import fromshared/parseFormat.jsdirectly (#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
gatewrite 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-statusis 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.