Commit Graph
4 Commits
Author SHA1 Message Date
Vitor PamplonaandClaude Opus 5 8dcc78056d refactor(buzz): move the Backlog and Workflow boards into the channel overflow
The two new boards were added as top-bar icons, which put a Buzz channel back to
four (Canvas, Backlog, Workflow runs, ⋮) and truncated the title row the bar is
there to show — "nosfabrica.commun…" instead of the full relay. That is the
crowding #3729 had just removed; this branch predates it and the merge stacked
them.

Canvas keeps the only icon: it is the channel's shared document, i.e. content.
Backlog and Workflow runs are two more views of the channel, reached
occasionally, so they join Threads and Share in the overflow — and pick up the
`!isDm` gate the icons never had.

Also gives the job board a string resource; the branch's i18n pass left
"Backlog" hardcoded in JobBoardScreen and in the icon's contentDescription.

Adds cli/tests/buzz/agent-exec.sh, which covers what the two loop harnesses
stub out. job-loop.sh proves the scheduler drives *an* --exec program; nothing
committed exercised the real one — the wrapper that turns a job into a PR. With
a stubbed `gh` and agent (no network, credentials, or Claude Code) it asserts
the happy path end to end (task on stdin → agent → commit → push the job branch
→ PR url on stdout) and, as importantly, the paths that must fail: an agent that
changed nothing becomes a job error, an empty task is rejected before the agent
runs, missing scheduler env is a hard error rather than a silent no-op, an agent
that committed for itself is not double-committed, and the default-branch guard
holds — asserting `main` on the remote is left untouched. 19/19.

Verified on emulator-5554: the bar is Canvas + ⋮ again with the full relay name
visible, the menu reads Threads / Backlog / Workflow runs / Share / Members /
Leave, and Backlog still opens from it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-26 23:37:22 -04:00
Claude 5d32cc8396 feat(cli): drive Buzz workflows from amy (trigger, run, approve/deny)
Switch the agent-support-channel prototype from the speculative agent-job
kinds (43001-43006, reserved with no upstream builder) to Buzz's real,
source-confirmed workflow primitive: 30620 def / 46020 trigger / 46001-46007
lifecycle / 46010 approval gate / 46030-46031 grant-deny (pinned against
buzz-relay's command_executor.rs). This bakes the human-approval gate into
the protocol — anyone in the channel can drive a run, but a human grants
before anything is pushed.

- commons WorkflowRunAggregator folds trigger + lifecycle + grant/deny into
  per-run state (TRIGGERED/RUNNING/AWAITING_APPROVAL/APPROVED/COMPLETED/
  FAILED/DENIED), correlating by run id (= trigger event id = approval token);
  8-case test.
- cli `amy buzz workflow` — trigger/list/show/approve/deny plus the `run`
  runner: per new trigger it does the agent work in a fresh worktree+branch,
  posts the 46010 gate, and on a later poll runs --on-approve (push + PR) and
  emits 46005 completed; a deny discards the worktree (run is DENIED).

On a real Buzz relay the relay executes the workflow YAML; self-hosted on
geode there is no engine, so amy is the runner and emits the lifecycle events
itself (documented divergence). Two store realities, both verified against
geode: decisions are fetched by author (quartz's store serves #d only for
addressable kinds, and 46030/46031 are regular), and the runner is
restart-safe (runs at the gate are rebuilt from the deterministic run id).

Also hardens the exec helper against a broken pipe when --exec doesn't read
stdin, and fixes worktree teardown to run git against the owning repo.

End-to-end headless harness (cli/tests/buzz/workflow-loop.sh) covers the
grant and deny paths through an embedded geode relay: 14/14 green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011mApqAbr8vkLC7gUDjavu6
2026-07-26 16:50:54 +00:00
Claude e0d6febd5b feat(cli): parallel backlog scheduler for the shared Buzz agent channel
Evolve `amy buzz agent serve` from a sequential responder into a scheduler that
manages a shared feature-request backlog by itself — the model where a whole team
drives an AI in one channel, not a 1:1 chat.

- Parallel execution with isolation: `--parallel N` runs up to N jobs at once,
  each in its own `git worktree` + branch (`--worktree REPODIR`, off `--base-ref`,
  named `<branch-prefix><jobid>`) so concurrent autonomous runs never clobber one
  working tree. `--parallel > 1` requires `--worktree`; worktree add/remove is
  mutex-serialized while the agent work runs concurrently. Branch/worktree/base-ref
  are exported to `--exec` (BUZZ_BRANCH/WORKTREE/BASE_REF) so it commits, pushes the
  branch, and opens the PR. Merge stays on GitHub — never here.
- Group-driven priority: BuzzJobAggregator now folds kind-7 upvotes (distinct
  reactors, dislikes excluded) into JobView.upvotes, and `byPriority` orders the
  backlog most-upvoted-first, oldest-first tiebreak. The stack reprioritizes itself
  as the channel reacts. `buzz job list/show` surface upvotes.
- Channel-as-allowlist: `--accept-from-channel` obeys any member of the channel's
  kind-39002 roster ("anyone in the channel can drive"), union with explicit
  `--accept-from` npubs.
- Harness cli/tests/buzz/job-loop.sh gains a parallel case (3 jobs, --parallel 3,
  one branch/worktree each, cleaned up); aggregator gains upvote + priority tests.
  11/11 harness checks + all unit tests green.

Fits entirely inside amy: amy is the scheduler, the coding agent is whatever
`--exec` points at, GitHub owns merge. Plan doc updated with the model + the
"can this live in Amy" architecture note.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011mApqAbr8vkLC7gUDjavu6
2026-07-25 18:19:40 +00:00
Claude 635e785753 feat(cli): buzz agent-job loop — file/track jobs + a driving responder
Prototype the "human drives an AI coding agent to develop Amethyst" support
channel on top of the existing block/buzz integration, all through amy.

- commons: BuzzJobAggregator (BuzzJobs.kt) — a pure, tested folder that
  correlates the Buzz agent-job kinds (43001-43006) by their `e` request
  reference into JobView records with a REQUESTED→ACCEPTED→IN_PROGRESS→
  COMPLETED/FAILED/CANCELLED state machine (newest terminal wins). Shared so a
  future mobile Jobs board reuses one correlation path. 9 unit tests.
- cli: `amy buzz job request|list|show|cancel` (requester side) and
  `amy buzz agent serve --exec CMD` (the responder loop): polls for REQUESTED
  jobs targeting my key, gates intake on `--accept-from` (allowlist) and
  `--channel`, then accepts (43002) → progress (43003) → runs `sh -c CMD`
  (task text on stdin; BUZZ_JOB_ID/REQUESTER/CHANNEL/RELAY/AGENT in env) →
  result (43004) or error (43006). Point `--exec` at a coding agent to drive it.
- cli/tests/buzz/job-loop.sh — self-contained headless harness over an embedded
  `amy serve` relay; asserts the full loop AND the permission gate (an allowlist
  excluding the requester handles nothing).
- Design doc cli/plans/2026-07-25-buzz-agent-support-channel.md: the three-layer
  permission model (Buzz scopes by identity, not capability flags — so
  "can't merge/destroy main" lives in GitHub branch protection + the `--exec`
  credential, not the relay), the MVP architecture, and the prioritized mobile
  app gap list (approvals inbox, jobs board, diff/PR review, …).

Schema caveat: kinds 43001-43006 are reserved in Buzz with no upstream builder;
the tag layout is Quartz's best-effort model, to be reconciled upstream.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011mApqAbr8vkLC7gUDjavu6
2026-07-25 17:18:30 +00:00