Skip to content

Hatch: multi-agent harness design docs#1

Merged
fioenix merged 60 commits into
mainfrom
claude/agents-control-tower-bo6w3f
Jun 22, 2026
Merged

Hatch: multi-agent harness design docs#1
fioenix merged 60 commits into
mainfrom
claude/agents-control-tower-bo6w3f

Conversation

@fioenix

@fioenix fioenix commented Jun 14, 2026

Copy link
Copy Markdown
Owner

Hatch — bản nâng cấp đa-agent của overclaud

Bộ thiết kế (design docs) cho Hatch: harness điều phối nhiều coding agent (Claude Code, Codex, Kiro, Antigravity) trên cùng một repo, tối ưu token, theo quy trình kiểu Agile. Đây là bản nâng cấp của chính overclaud — overclaud single-agent trở thành compiler backend cho Claude bên trong Hatch. Sản phẩm thuộc hệ sinh thái Finolabs.

Trạng thái: chỉ là docs, chưa implement. Implement theo roadmap sau khi docs được chốt.

Xương sống thiết kế

Mô phỏng một squad Agile người: nhiều tác nhân thông minh, không chung bộ nhớ, phối hợp qua artifact ngoài (board + ledger), bất đồng bộ. Điều phối Hybrid: Conductor (CC) lập kế hoạch & chia ticket; workers tự claim và phối hợp async.

Sáu trụ

  1. Single Source of Truth → compiler sinh CLAUDE.md/AGENTS.md/.kiro/steering/ per-agent (hết drift).
  2. Context phân tầng L0/L1/L2 (tối ưu token).
  3. Role ≠ Agent — gán vai theo điểm mạnh qua registry.yaml.
  4. Coordination qua board + claim/lock (git) + handoff.
  5. Workflow Agile ghép spec-driven (PRD→Design→Tasks).
  6. Governance: ledger append-only + gates + human gate.

Nội dung

  • hatch/README.md — tổng quan
  • hatch/docs/00-08 — vision, architecture, roles, coordination protocol, context+compiler, workflow, governance, orchestrator, roadmap
  • hatch/spec/ — schema registry / ticket / ledger
  • Root README.md — link tới Hatch

Lộ trình (3 phase)

  • Phase 1 Convention + docs (chạy được không cần code)
  • Phase 2 CLI cơ học (hatch compile/status/gate/sync)
  • Phase 3 Full orchestrator (hatch run spawn agent vào worktree riêng — "nở agent")

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ


Generated by Claude Code

claude added 30 commits June 14, 2026 12:39
Hatch is overclaud's multi-agent upgrade — a harness that coordinates
multiple coding agents (Claude Code, Codex, Kiro, Antigravity) on one
repo with role assignment, an Agile-style workflow, token-tiered context,
a single-source-of-truth compiler, file-based async coordination, and an
audit ledger. overclaud's single-agent optimizer becomes the Claude
compiler backend within Hatch.

Adds hatch/ design set: README, docs/00-08 (vision, architecture, roles,
coordination protocol, context+compiler, workflow, governance,
orchestrator, roadmap), and spec/ schemas (registry, ticket, ledger).
Modeled on a human Agile squad; staged Phase 1 (convention) -> 2 (CLI)
-> 3 (full orchestrator). Links Hatch from the root README.
- Knowledge Base (kb/): shared, read+write memory store for all agents,
  distinct from SSOT (config-in) and ledger (events-out). Three-store
  knowledge model; KB->SSOT promotion at retro. New docs/09-knowledge-base.md.
- Roles are per-project user config, not hard-coded: registry.yaml lives in
  each project's .hatch/; standard roles are a starter template.
- Workflow as editable template: lanes/transitions/gates/ceremonies defined
  in workflow.yaml (scrum/kanban/spec-first/lite); redesignable per project.
  New spec/workflow.schema.md.
- Update README, architecture (7 pillars + kb/ + workflow.yaml), roles,
  context-compiler (SSOT vs KB), workflow, vision, roadmap, registry spec, DoD.
Phase 1+2 of the Hatch design, in Go (single binary):

- model + filesystem-as-database store (board, ledger, KB) with markdown
  frontmatter parsing
- `hatch init`: scaffold a .hatch/ workspace from embedded templates with
  4 workflow templates (scrum/kanban/spec-first/lite)
- `hatch compile`: SSOT -> per-agent surfaces (CLAUDE.md, AGENTS.md,
  GEMINI.md, .kiro/steering) with L0/L1/L2 layering + manifest stale
  detection (`--check` for CI). Surface table derived from researched
  agent CLI docs (docs/10-agent-adapters.md)
- workflow engine: transition authorisation, gate evaluation
  (command/checklist/required-field/policy/human), no-self-review,
  dependency gating, append-only ledger
- commands: init, compile, validate, status, standup, gate, ticket
  (new/claim/move/show), kb (add/query/index)
- unit + integration tests, Makefile, GitHub Actions CI

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
The bare `hatch` ignore pattern matched the cmd/hatch source directory,
so main.go was never committed and CI `make build` failed. Anchor the
binary ignore patterns instead.

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
- adapter layer building native headless invocations per agent kind
  (claude -p / codex exec / gemini -p / kiro-cli chat --no-interactive),
  with capability flags from registry sandbox/approval hints; kiro/
  antigravity/manual fall back to handoff when no headless contract
- orchestrator.Run/Execute: spawn agent, stream output, record ledger;
  --dry-run prints the invocation without executing
- git worktree isolation helper for per-ticket runs
- CLI: `hatch run`, `hatch plan`, `hatch watch`, plus `hatch board`
  Bubble Tea TUI dashboard (brand colors)
- adapter unit tests (no real agent needed)

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
- `hatch sync`: reconcile ticket status with lane (--fix), rebuild KB
  index, report compile staleness
- `hatch hook install`: write a pre-commit hook running validate +
  compile --check

Completes the Phase 2 automation backlog.

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
Three views: system architecture, ticket workflow state machine, and a
ticket-lifecycle sequence. Mermaid renders on GitHub; PNGs in docs/assets.

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
- three new workflow templates covering product-development lifecycle
  styles: dual-track (discovery∥delivery), shape-up (pitch→bet→build),
  stage-gate (phased requirements→design→build→test→release). Now 7
  templates total; all validated by a new scaffold test
- architecture-diagram.md: lead with plaintext ASCII (arch + workflow +
  lifecycle), keep Mermaid for GitHub; drop the rendered PNGs
- TUI: replace palette with neutral colors
- docs (05-workflow, workflow schema, README) list all templates

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
Agents now talk to each other directly (more than task-only orchestrators
like Paperclip), always on the record:

- bus: append-only, file-based message store. A conversation file = a
  channel/DM; replies (--reply-to) form threads within it
- @mention: @agent / @ROLE in a message body auto-routes to that
  teammate's inbox (Slack-style tagging)
- inbox = Slack-style notifications (DMs + @mentions + broadcast), with a
  per-agent read cursor; channels are browsed via `hatch channel show`
- synchronous ask/reply: orchestrator relays a question to another agent
  and records the reply
- convene: bounded multi-agent meeting; agents take turns by role, can
  emit DECISION: to converge
- commands: msg, channel (ls/show), inbox, thread, ask, convene
- docs/11-communication.md; reconcile coordination-protocol (dialogue via
  bus vs state via board/ledger)

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
Refine the read model so agents don't process every message:
- subscriptions: `hatch channel join/leave/members` — per-agent channel
  membership (scope, stored in .hatch/bus/.members.json)
- search/recall: `hatch search <query> [--agent --channel --from --type
  --limit --all]` — load only relevant messages into context, newest
  first and capped; defaults to the agent's subscribed channels. This is
  L2 on-demand for conversation, not a firehose
- inbox stays the must-act subset (DM + @mention + broadcast)
- bus.Search + subscription store, with tests; docs/11 read-model section

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
`hatch run` now prepends an agent's unread inbox + a ticket-relevant
conversation recall to its prompt (like a teammate checking Slack before
starting), then marks the inbox read. Token-bounded: recall is scoped to
the agent's subscribed channels, token-matched and capped; --no-catch-up
opts out.

- orchestrator.commContext + Run wiring; RunOptions.SkipComms
- bus.Search upgraded to token (OR) matching ranked by tokens matched,
  so recall works on multi-word queries like a ticket title
- tests for comm context + token search; docs/11 "read the room" section

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
Make Hatch behave like a human squad's rhythm, not just a task queue:

- ceremonies: `hatch ceremony standup` (per-agent ledger digest + blockers,
  posts #standup), `retro` (cycle summary + KB→SSOT promotion candidates,
  --write), `planning` (spawn Conductor). New ledger parser + ceremony pkg
- escalation/on-call: `hatch escalate <ticket>` (ledger + #escalations,
  tags the target) and automatic escalation when a ticket fails a gate >=2
  times; target from registry policy.escalate_to → conductor → human:lead
- decision→ADR: convene turns starting with DECISION: are recorded as
  accepted ADRs in kb/decisions/ (new decide pkg)
- store.KB.NextID extracted; tests for ceremony/decide/escalate; docs/12

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
`hatch pair <ticket> --driver A --navigator B [--rounds N] [--claim]`:
two agents work one ticket like pair programming — the driver implements
a small step each round (seeing the navigator's latest feedback), the
navigator reviews that turn and suggests the next; both turns recorded in
a pair-<ticket> bus thread. Navigator can emit READY to end early.
driver != navigator enforced. --dry-run shows the turn structure.

orchestrator pair prompt builders + tests; docs/12 pairing section.

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
- presence pkg + presence.json: per-agent status (available/busy/paused/
  offline) + note, Slack-style. `hatch presence` shows status+WIP load;
  `hatch presence set <agent> --status --note`
- pickAgent is now capacity-aware: skips paused/offline agents and prefers
  the least-loaded under-WIP candidate, so run/watch route to whoever's
  free — like a lead assigning work
- presence test

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
- `hatch ceremony demo`: showcase work in terminal lanes, posts to #demo
- `hatch ceremony grooming`: flag under-specified backlog tickets (missing
  role/priority/acceptance, leftover TODO); non-zero exit if any need work
- ceremony.Demo/Grooming + tests

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
- `hatch mob <ticket> --agents a,b,c --rounds N`: 3+ agents on one ticket
  with a rotating driver each round, the rest navigate; ends early when a
  majority of navigators signal READY
- convene `--decider <agent>`: if no DECISION is reached after the rounds,
  the decider makes the final call (recorded as an ADR). convene also
  stops as soon as a decision is reached

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
- oncall pkg + oncall.json: `hatch oncall` (show), `oncall set --rotation`,
  `oncall rotate` (announces in #oncall). Escalation now targets the
  current on-call first, then policy.escalate_to → conductor → human:lead
- `incident` workflow template (detected→triage→mitigating→resolved→
  postmortem) with fix-verified + postmortem-written gates; now 8 templates
- docs/12 sections for on-call/incident/presence/mob; tests for oncall +
  on-call-aware escalation target

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
…ence

Brainstorm + design (not yet implemented) for the open operational items,
framed for a Founder/CEO/CTO running the squad:

- docs/13-management.md: metrics derived from the ledger (cycle time,
  throughput, rework, gate pass rate); workload view; performance
  scorecards (with an honest Goodhart caveat); budget & "salary" =
  per-agent budget with cost capture, hard caps and auto-pause that reuses
  presence; stakeholder status report
- docs/14-org-and-cadence.md: org chart + delegation-of-authority in the
  registry (escalation up the reporting line), external/cross-team
  dependencies, heartbeat/cadence via a stateless `hatch tick` for cron/CI,
  plus estimate/spike notes and a suggested implementation order

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
docs/overview.md — one-page big picture with ✓ built vs ◇ designed: the
layered system map, CLI command index by area, an end-to-end "a day in
the squad" flow, and the human-squad analogue table.

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
…sions

- docs/15-obsidian-kb.md: use an Obsidian vault as the primary KB via CLI
  (vault-as-files; wikilinks/tags/frontmatter/MOC/Dataview compatibility;
  graph-aware recall; obsidian:// + optional Local REST API), with native
  MD as fallback. Honest caveat: Obsidian has no official CLI
- docs/16-document-templates.md: doc-type → framework → template system
  (ADR/MADR, RFC, PRD, design, EARS requirements, SRE postmortem, runbook,
  Diátaxis, Keep a Changelog…), `hatch doc new/lint`, user-overridable like
  workflow templates; spec-lint can gate DoD
- docs/17-pre-implementation.md: decisions to settle before building the
  rest (cost capture, secrets/redaction, concurrency, bus parser, mock
  agent for e2e, Obsidian vault location), with a suggested build order

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
Per the settled pre-implementation decisions:
- mock agent: `cmd/hatch-mock` + `kind: mock` adapter — a deterministic
  stand-in agent so execute/relay/pair/convene/run are testable end-to-end
  without a live agent CLI. New e2e test really spawns a process and asserts
  prompt pass-through, output capture and ledger entries. Makefile builds it.
- bus parser robustness: a line is only a message heading when it starts
  with "## <timestamp> · …", so Markdown "## Section" inside a message body
  is no longer mis-split. Regression test added.
- record decisions (mock=yes, vault=both/in-repo default, cost/secrets=
  minimal but secrets env-only) in docs/17.

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
Per the minimal cost decision (track, no enforcement):
- ledger entries carry cost_usd/tokens; orchestrator scrapes usage from
  agent output (provider-agnostic regex; estimates USD from rate_per_mtok
  when only tokens are given). hatch-mock emits fake usage for e2e.
- store.ScanCosts parses the ledger; `hatch cost <ticket>` sums a ticket,
  `hatch budget` shows per-agent + team spend vs budget_usd/team_budget_usd
  (warns at 80%, never blocks)
- registry: agent budget_usd/rate_per_mtok + policy.team_budget_usd
- usage parsing test; verified e2e with the mock agent

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
- metrics pkg: parse ledger into per-agent scorecards (claims, done,
  reviews, gate-fails, escalations, cost/tokens) + team throughput and
  avg cycle time (first claim → done). Nothing tracked separately.
- store.Ledger.Entries(): full ledger parser reused by metrics
- `hatch workload`: presence + WIP + done + idle/overloaded flags
- `hatch perf [agent]`: scorecard, with the Goodhart caveat printed
- metrics test

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
- docs pkg + 5 default templates (adr/MADR, design, postmortem/SRE,
  rfc, prd) shipped via scaffold into .hatch/templates/docs/, user-editable
- `hatch doc types` lists type→framework→required sections
- `hatch doc new <type> --title` scaffolds (substitutes {{title}}, seeds
  required frontmatter: date/status/id)
- `hatch doc lint <file>|--all` checks required sections + frontmatter per
  the document's declared doc-type; non-zero exit on problems (DoD-gate-able)
- docs round-trip test

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
docs/18: two distinct things to observe — squad state (board/ledger/bus,
Hatch renders) vs live per-agent output (a stream). Two non-exclusive
layers: (A) a single-process Bubble Tea mission-control TUI with internal
panes (no deps, works over SSH/remote), and (B) optional tmux/Zellij
driver (`--mux`) giving each spawned agent a real pane. Both build on a
per-run transcript (.hatch/runs/) + `hatch logs --follow`; remote/CI
observes via transcripts + artifacts.

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
- registry `kb:` block (mode native|obsidian, vault path, wikilinks);
  KB store gains a configurable vault Root (in-repo default, external
  vault supported) + wikilink-aware index
- `hatch kb link/backlinks/graph/open`: link notes (related), compute
  backlinks + link graph (from related + [[wikilinks]] in bodies), emit
  obsidian:// URI. Index renders [[wikilinks]] when enabled
- verified e2e: link → backlinks/graph, wikilink index, URI

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
- orchestrator writes raw stdout+stderr of each run to
  .hatch/runs/<ticket>/<ts>-<agent>.log (in addition to terminal + ledger
  summary + cost)
- `hatch logs <ticket>` prints the latest transcript; --follow tails live
  (kubectl-logs style), --all prints every run. This is the substrate the
  TUI's live-output panes read.

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
`hatch board` is now a Bubble Tea dashboard with three panes in one
process: BOARD (selectable tickets per lane), LIVE (tails the selected
ticket's run transcript — live agent output), and ACTIVITY (ledger feed).
Auto-refreshes every second. Keys: tab switches pane, ↑/↓ move/scroll,
f follow a ticket's output, r launch a capacity-aware run on the selected
ticket (control from the TUI), g refresh, q quit. No tmux needed; the
optional tmux/Zellij multi-pane driver remains future work (docs/18).

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
`./scripts/onboard.sh` (or `make onboard`): verifies Go, builds hatch +
hatch-mock, optionally `--install`s them on PATH, and spins up a demo
workspace in .hatch-demo (mock agent wired in) that seeds a ticket, runs
it, and shows board/logs/cost/perf — so you can try Hatch locally with no
real agent CLI. Flags: --install, --no-demo, --demo DIR. README quick-start
updated; .hatch-demo gitignored.

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
- registry roles gain reports_to + authority (can_approve,
  budget_authority_usd, decision_scope); validated (unknown parent +
  reporting cycles). `hatch org` prints the tree + authority matrix.
- escalation climbs the org chart: EscalateTargetForRole resolves on-call
  → manager of the ticket's role → policy → conductor → human:lead
- tickets gain blocked_by_external (what/owner/eta/status); claim is
  blocked while any are open; `hatch ticket extdep <id> --add/--resolve`;
  `hatch status` surfaces them as risk
- org-escalation test

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
claude added 27 commits June 15, 2026 00:48
A second TUI alongside `hatch board`: CHANNELS list + live messages pane
(auto-refresh, scrollable) + compose line (press i, Enter to send;
@mentions auto-tag). Posts as --as identity (default human:operator).
This is the "Slack window" for the squad's bus; docs/11 + overview +
README updated.

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
`hatch board` now shows BOARD + LIVE (run transcript) + ACTIVITY (ledger)
+ CHAT (the communication bus) in one process. Keys: tab switch pane,
↑/↓ move/scroll, f follow ticket, r run, c cycle channel, i compose+send
(@mentions auto-tag), g refresh, q quit. `hatch chat` stays as a focused
chat-only view. Docs/overview/README updated.

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
Security:
- Fix path traversal: paths.SafeSegment sanitizes any string used as a path
  segment; Runs()/run transcripts no longer let `hatch logs ../../x` (or a
  crafted ticket/agent id) escape .hatch. Tests added.
- hatch validate now rejects unsafe ticket ids (chars outside [A-Za-z0-9._-]),
  which also keeps branches/worktrees/transcript paths safe. Test added.
- Document trust boundaries in SECURITY.md: gate commands (sh -c from
  workflow.yaml), agent exec (no shell — args passed directly), credentials
  (env-only, never persisted), transcript capture caveat, path safety.

Open-source standards:
- Add CODE_OF_CONDUCT.md (Contributor Covenant 2.1)
- CONTRIBUTING.md: add a Hatch (Go) dev + PR-standards section
- SECURITY.md: add a Hatch section + reporting channel

Audit notes (no code change needed): agent spawning uses exec without a
shell; no secrets in code/config (grep-clean); credentials read from env at
spawn; ledger appends are mutex-serialized for parallel runs.

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
Invert dependencies at the key infrastructure seams so the use-case core
depends on ports, not concrete infra:

- gate.Runner port + ShellRunner adapter; Evaluator injects it. Command
  execution is now swappable/testable (fake-runner test added). Package-level
  Evaluate/EvaluateAll stay as thin wrappers over the Default evaluator.
- wf engine depends on wf.Board / wf.Ledger interfaces instead of
  *store.Board / *store.Ledger; `internal/wf` no longer imports
  `internal/store`. Escalate takes the board via the port (no internal store
  construction).
- ARCHITECTURE.md documents the layering (domain → use cases → ports →
  adapters → driving adapters), the dependency rule, and the deliberate
  Lean non-ports (filesystem-as-DB is the product).

All 18 packages pass; orchestrator.Adapter (+mock) already realised
ports & adapters at the agent boundary.

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
Central ports package for the use-case layer (Board/Ledger/Bus/OnCall) with
compile-time assertions that store/bus/oncall adapters satisfy them. Bus gains
Notify + CatchUp (read-the-room formatting moved into the adapter). Additive
only; no behavior change yet.

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
wf is now an Engine struct holding port.Board/Ledger/Bus/OnCall; Move and
Escalate are methods. The engine core imports no infrastructure (no store,
bus, or oncall) — only port + model + config + gate. The CLI composition
root (engineFor) wires concrete adapters. Tests use the same wiring.

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
…dary

- orchestrator is now an Orchestrator struct holding port.Ledger + port.Bus;
  Run/Execute are methods. Catch-up formatting moved into the bus adapter
  (port.Bus.CatchUp). The CLI/TUI composition root (orch(ws)) injects adapters.
- metrics.Compute now takes port.Ledger.
- internal/port gains Bus.CatchUp/MarkRead; bus implements them.
- ARCHITECTURE.md: ports now live in internal/port; document the deliberate
  Lean line — command/mutating use cases (wf, orchestrator, gate) go through
  ports; read-only reporting projections (ceremony, report/cost/budget views)
  are composed at the root rather than leaking bus.Message into a port.

All 18 packages pass; wf and orchestrator cores import no infrastructure.

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
- move the messaging value types (Message, SearchOpts, message kinds) into
  the domain (internal/model); bus re-exports them as type aliases so call
  sites are unchanged. Ports can now return domain types with no adapter leak.
- port.Bus gains Search; new port.KB (List). store/bus satisfy them (asserted).
- ceremony is now a Service{port.Board, Ledger, Bus, KB}; metrics already on
  port.Ledger. The entire use-case layer (wf, orchestrator, gate, metrics,
  ceremony) imports only port + model + config — no store/bus.
- composition root gains ceremonyService(ws); ARCHITECTURE.md updated.

All 18 packages pass; onboard e2e green.

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
…onal

- new `agy` adapter (Google Antigravity CLI, successor to Gemini CLI):
  `agy -p … --output-format json [-m] [--approval-mode/--yolo] [--sandbox]`,
  surface GEMINI.md. Now the default in the scaffolded registry; `kind: gemini`
  kept for the legacy Gemini CLI.
- doctor no longer scans credential folders (security). It checks auth by
  running the CLI's own non-mutating command (e.g. `codex login status`) or an
  agent-configured `auth_check`, or honours an env key; otherwise reports "?".
  Agent CLIs are not mandatory — readiness needs only ≥1 present; missing CLIs
  are shown, not failed.
- model.Agent.auth_check; envForKind adds ANTIGRAVITY_API_KEY.
- docs 10/19 updated (agy default, OAuth login, optional CLIs).

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
… docs

Researched each agent CLI's official docs for a non-interactive auth-status
command (doctor runs it; never scans credential files):
- claude → `claude auth status` (exit 0/1, JSON)
- codex  → `codex login status` (exit 0/1)
- kiro   → `kiro-cli whoami` (exit 0 = authed)
- gemini (legacy) → no command; env-only
- agy → no auth-status command and no API-key env (OAuth/keyring only) →
  doctor reports "?" rather than guessing
Correct the agy adapter to the real flags (README/CHANGELOG): `-p`, `-m`,
`--dangerously-skip-permissions` (former --yolo), `--sandbox`; drop the
nonexistent `--output-format json`; note upstream #76 (stdout dropped on
non-TTY). Remove the unconfirmed ANTIGRAVITY_API_KEY. docs/10 + 19 updated.

Verified live: `hatch doctor` actually runs `claude auth status` (exit 0) on
the installed claude CLI → ✓; absent CLIs show ?/✗ correctly.

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
- delete geminiAdapter + its registry/surface/doctor entries and the gemini
  test; agy (Antigravity CLI) is the only supported Google agent. The
  GEMINI.md compile surface stays (agy reads GEMINI.md/AGENTS.md).
- scrub gemini agent-kind references in docs/README/comments → agy.

18 packages pass; agy dry-run = `agy -p <prompt>` (verified).

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
The demo previously rewrote `kind: codex` → `kind: mock`, which made `hatch
doctor` show codex as "mock" and confused real-vs-demo. Now onboard inserts a
dedicated `mock` agent (id: mock) and runs the demo with `--agent mock`,
leaving the real agents (claude/codex/agy/kiro) exactly as scaffolded — so
doctor reflects the real CLIs.

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
…rst)

docs/20: correct the core direction. Hatch was built as an orchestrator that
DRIVES agents and as the entrypoint TUI; the right model is the inverse — the
coding agent is the entrypoint and drives itself; Hatch is the shared
comms+memory it reaches via an MCP server (embedded harness). Chat is both the
communication channel and the backlog (thread = task); `hatch board`/`chat` are
read-only views. Documents what went wrong, what survives (bus/KB/ledger/clean
arch/compile-repurposed), the MCP-vs-skill-vs-plugin analysis (MCP primary,
all four agents support it), a proposed MCP tool surface, and a phased plan
with an open decision on how aggressively to retire the operator features.

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
Introduce `hatch mcp --as <agent>`, a stdio MCP server that exposes the
shared chat bus and knowledge base as tools so any MCP-capable coding
agent (Claude Code, Codex, agy, Kiro) can drive itself against the same
comms + memory. This is the first step of the embedded-harness pivot
(docs/20): the coding agent is the entrypoint; Hatch is the shared layer
it reaches into. Chat doubles as the backlog — a thread is a task.

Tools: whoami, chat_open, chat_post, chat_read, chat_inbox, chat_search,
chat_channels, kb_add, kb_search. Posts are attributed to the --as
identity, so each agent runs its own instance.

Verified in-process via the SDK in-memory transport (round-trip,
cross-agent @mention inbox, KB add/search).

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
Repurpose `hatch compile` for the embedded-harness model (docs/20 step 2).
Instead of operator instructions, each agent's surface now carries the
protocol it self-follows:

- Workflow rendered as prose (stages, who-does-what, gates, ceremonies)
  from workflow.yaml — guidance, not a Go engine.
- Chat protocol: Slack-style etiquette over the Hatch MCP server (open a
  thread per task, brief in-thread, @mention, inbox, search, kb).
- Definition of Done: a self-check derived from workflow command-gates +
  policy (no-self-review / human-merge) the agent runs before reporting.
- Orchestrator block on the lead agent's surface only (the conductor).

And it registers the `hatch mcp --as <agent>` server with each agent:
merges into repo-local `.mcp.json` (Claude) and `.kiro/settings/mcp.json`
(Kiro) preserving existing servers; writes paste-ready snippets under
.hatch/mcp/ for Codex and agy whose configs live outside the repo.

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
Step 3 of the embedded-harness pivot (docs/20): a loadable/installable
Claude Code plugin under hatch/plugin/ that wires Hatch into Claude:

- .mcp.json launches `hatch mcp` (the shared chat + KB tools).
- skills/hatch-chat teaches the squad etiquette (thread = task,
  @mention, recall-before-rederive, DoD self-check).
- /hatch slash command syncs with the squad (inbox + open threads).
- marketplace.json at repo root so `/plugin install hatch@hatch` works.

To make the plugin workspace-agnostic, `hatch mcp` now resolves its
identity when --as is omitted: $HATCH_AGENT, else the first claude-kind
agent in the registry. So the plugin needs no per-project config.

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
Steps 4-5 of the embedded-harness pivot (docs/20). Hatch no longer drives
agents or enforces workflow in code; the coding agent drives itself
through the MCP server, and Hatch is comms + memory + read-only views.

Read-only views:
- Rewrote the board TUI as mission control over THREADS (chat = tasks) +
  CHAT + ACTIVITY (ledger). Dropped the orchestrator LIVE pane, ticket
  lanes, presence, run-control and message composing.
- Made the chat TUI a pure viewer (no compose/post).
- Rewrote `status` to summarize chat threads + roster instead of board
  lanes/tickets.

Archived behind the `hatch_legacy` build tag (recoverable, excluded from
the default binary): run/plan/watch/tick, the orchestrator, the workflow
engine (gate/escalate/ticket), ceremonies, ask/convene, pair/mob,
presence, oncall, cost/budget, workload/perf, report. Default `hatch`
keeps init/compile/validate/status/kb/board/chat/sync/hook/msg/channel/
inbox/thread/search/doc/logs/org/doctor/mcp.

root.go registers the lean set and calls addLegacyCommands, which is a
no-op by default and wires the archived commands under -tags hatch_legacy.
Updated onboard.sh to demo the new flow; split the integration test into
a default (embedded-harness) flow and the legacy one. Both build tags
build, vet and test green.

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
The read-only TUI rewrite removed the last textinput usage, so clipboard
is no longer needed; `go mod tidy` prunes it (fixes the CI tidiness
check). Also mark docs/20 roadmap steps 1-6 complete.

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
Reframe the README away from the pre-pivot orchestrator story: Hatch is
an embedded harness (shared chat = comms + backlog, KB, over MCP) that
agents drive themselves through — not a tool that spawns/drives agents.
Correct the CLI section to the actual default command set, mark the
self-driving operator as archived behind -tags hatch_legacy, and note
that docs 00-19 describe the original design while doc 20 is current.

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
Replace the pre-pivot overview (orchestrator spawning agents, workflow
engine enforcing gates, board as control panel, management dashboard)
with the current model: agents are the entrypoint and self-drive,
reaching the shared chat (= comms + backlog, thread = task) and KB via
the hatch MCP server; compile emits protocol prose + MCP registration;
board/chat/status are read-only; the self-driving operator is archived
behind -tags hatch_legacy. Adds a doc-20-wins banner.

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
- Redraw docs/architecture-diagram.md for the embedded-harness model:
  SSOT → compile → per-agent surfaces (protocol prose) + MCP registration;
  agents are the entrypoint and self-drive, reaching the shared chat
  (= comms + backlog, thread = task) + KB + ledger via the hatch MCP
  server; read-only observe layer; archived-operator note. Replaces the
  old orchestrator-spawn / workflow-engine diagrams. Plaintext-first plus
  refreshed Mermaid. Adds a task-as-thread lifecycle and an inter-agent
  message-round diagram.
- README: add a step-by-step 'Cài đặt & Onboarding (user mới)' section
  (prerequisites → install hatch → init → compile → optional Claude
  plugin → work & observe), with the correct module path and the demo
  fallback for environments without a real agent CLI.

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
Add per-client MCP wiring so any of the four CLIs can be the orchestrator,
not just Claude. `hatch init --client <x>` scaffolds (or reuses) the
workspace, compiles, then registers the hatch MCP server where that client
actually reads it — using the agent's own identity (--as <id> from
registry.yaml):

- cc  → project .mcp.json + prints the /plugin marketplace install steps
- codex → shells out to `codex mcp add hatch -- hatch mcp --as codex`
  (Codex owns ~/.codex/config.toml); falls back to printing the snippet
- agy → merges the HOME-level ~/.gemini/config/mcp_config.json that the
  Antigravity CLI loads, plus a .agents/ workspace copy
- kiro → .kiro/settings/mcp.json

Works in-place on an existing .hatch; --dry-run previews without writing.
/root-level writes happen only on the explicit --client invocation and
merge-preserve other servers. README onboarding updated.

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
Antigravity CLI loads MCP servers ONLY from a HOME-level mcp_config.json
(a separate file, not inline in settings like legacy Gemini CLI). Current
runtime path is ~/.gemini/config/mcp_config.json; older installs use
~/.gemini/antigravity-cli/mcp_config.json (now a symlink). Project-local
.antigravitycli/mcp_config.json is detected but silently ignored
(google-antigravity/antigravity-cli#60).

Fixes for --client agy:
- Write ~/.gemini/config/mcp_config.json (current), and also the legacy
  ~/.gemini/antigravity-cli/mcp_config.json only when that dir already
  exists and isn't a symlink (covers pre-migration installs).
- Drop the bogus .agents/mcp_config.json workspace write (wrong path AND
  ignored by the runtime); print a note that project-local isn't loaded.
- Fix the compile-generated agy snippet that pointed at the legacy
  ~/.gemini/settings.json. README updated.

Verified against issue #60 and Antigravity CLI docs (Arm Learning Paths,
Google Cloud Community).

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
Workspace resolution is now layered: a local .hatch (nearest ancestor of
cwd) overrides the global ~/.hatch, which is the default used in every
repo. `hatch init` creates the global ~/.hatch; `hatch init --local`
creates a project .hatch that overrides it. $HATCH_HOME relocates the
global root (and sandboxes tests).

- paths: GlobalRoot(), FindLocal() (local-only), Find() now falls back to
  the global workspace when there's no local one.
- config.Workspace gains OutputRoot/Out(): compiled surfaces + MCP
  registration always target the working repo (cwd), even when the SSOT
  is the global ~/.hatch — so the repo gets its CLAUDE.md/.mcp.json while
  the repo is NOT polluted with a stray .hatch. compile + --client honor it.
- compile keeps codex/agy snippets with the SSOT (.hatch/mcp/) instead of
  scattering them into the working repo.
- loadWorkspace does the local→global resolution for all commands.

Also rename the onboarding demo dir .hatch-demo → demo-workspace (it was
a throwaway sandbox, confusingly named like .hatch) and make the demo use
--local. Tests cover local-overrides-global and the not-found fallback.

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
A practical bring-up doc: what Hatch is post-pivot, build/test/run (both
build tags), current state, what must be verified locally (real MCP
handshake with claude/codex/agy/kiro, codex mcp add, agy runtime path,
doctor), architecture pointers, known limitations, and git conventions.

https://claude.ai/code/session_01LJ6kqJhxDKCymkFoLTTFqQ
@fioenix fioenix merged commit 401cb18 into main Jun 22, 2026
2 checks passed
fioenix added a commit that referenced this pull request Jun 23, 2026
Addresses the changes-requested review on PR #2:

- [#1] daemon: replace (not merge) the wake-policy Working snapshot each tick, so
  a finished runner stops debouncing future wakes (agents no longer go silent).
- [#2] slack: guard the threadmap with a mutex — the Socket Mode consumer and the
  mirror ticker share it (was an unsynchronised map → data race).
- [#3] slack: config/help/spec now point at .hatch/run/slack/config.json (drifted
  after the runtime-dir move).
- [#4] daemon: persist the processed cursor (.hatch/run/daemon.cursor) so a
  restart resumes instead of replaying the whole backlog.
- [#5] daemon: on a failed Wake, requeue the payload before clearing the working
  flag — a spawn/resume error is retried next tick, not dropped. pending is now
  mutex-guarded for the dispatch goroutines. Added Wait() for graceful drain.
- [#6] slack: persist the mirror cursor in the threadmap, so a bridge restart
  does not re-post history.
- [#7] roster + session: serialize read-modify-write with a package mutex and
  per-pid temp files (concurrent runners no longer clobber/lose updates).
- [#8] slack: optional BossUserID (HATCH_SLACK_BOSS_USER) — when set, only the
  boss's Slack user may drive the squad; empty = single-tenant.

Deferred (documented): per-thread coalescing/dispatch (#9) stays with the
parallelism work. lint + test green; -race clean on daemon/slack/session/roster.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
fioenix added a commit that referenced this pull request Jun 23, 2026
Addresses the changes-requested review on PR #2:

- [#1] daemon: replace (not merge) the wake-policy Working snapshot each tick, so
  a finished runner stops debouncing future wakes (agents no longer go silent).
- [#2] slack: guard the threadmap with a mutex — the Socket Mode consumer and the
  mirror ticker share it (was an unsynchronised map → data race).
- [#3] slack: config/help/spec now point at .hatch/run/slack/config.json (drifted
  after the runtime-dir move).
- [#4] daemon: persist the processed cursor (.hatch/run/daemon.cursor) so a
  restart resumes instead of replaying the whole backlog.
- [#5] daemon: on a failed Wake, requeue the payload before clearing the working
  flag — a spawn/resume error is retried next tick, not dropped. pending is now
  mutex-guarded for the dispatch goroutines. Added Wait() for graceful drain.
- [#6] slack: persist the mirror cursor in the threadmap, so a bridge restart
  does not re-post history.
- [#7] roster + session: serialize read-modify-write with a package mutex and
  per-pid temp files (concurrent runners no longer clobber/lose updates).
- [#8] slack: optional BossUserID (HATCH_SLACK_BOSS_USER) — when set, only the
  boss's Slack user may drive the squad; empty = single-tenant.

Deferred (documented): per-thread coalescing/dispatch (#9) stays with the
parallelism work. lint + test green; -race clean on daemon/slack/session/roster.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants