feat(flows): forge.* + agent.* nodes + mutation budget (NF-3) #350

Closed
code-lead wants to merge 1 commit from boss/324 into main
Collaborator

Registers 21 forge.* wrappers (one per ForgePort method) and 3 agent.* primitives (dispatch / cancel / raise_cap), backed by a per-run RateLimitBudget threaded through NodeHandlerCtx — spec-mandated 20 mutations / run default, overridable via execute(…, { mutationBudget }). agent.dispatch subscribes to task completion through a new in-process TaskEventBus and publishes task.completed / task.failed / task.cost_capped triggers back via an injected TriggerPublisher.

Test plan

  • 72 new tests across forge-nodes.test.ts (36), agent-nodes.test.ts (22), task-events.test.ts (8), plus 6 new budget / registry tests on the NF-2 files — full flow suite now 125 pass
  • Every ForgePort method has a corresponding forge.* node (spec § Operation catalog); mutating subset = 11 nodes charges the budget
  • Input schemas validate at handler entry; wrong-typed / missing ports reject before any adapter call lands
  • agent.dispatch enqueues through injected dispatch(type, params), subscribes to TaskEventBus.once(taskId), and publishes the correct terminal trigger (successtask.completed, failuretask.failed, cost_cappedtask.cost_capped)
  • Default mutation budget (20) allows 20 parallel mutations; a 21st trips the cap without dispatching to the adapter
  • withForgeAndAgentNodes({ forge, agent }) composes NF-2 built-ins + forge.* + agent.* (34 types)
  • just qa clean: typecheck + Biome check + Biome format + full server suite (1548 pass)

Closes #324

Registers 21 `forge.*` wrappers (one per `ForgePort` method) and 3 `agent.*` primitives (dispatch / cancel / raise_cap), backed by a per-run `RateLimitBudget` threaded through `NodeHandlerCtx` — spec-mandated 20 mutations / run default, overridable via `execute(…, { mutationBudget })`. `agent.dispatch` subscribes to task completion through a new in-process `TaskEventBus` and publishes `task.completed` / `task.failed` / `task.cost_capped` triggers back via an injected `TriggerPublisher`. ## Test plan - [x] 72 new tests across `forge-nodes.test.ts` (36), `agent-nodes.test.ts` (22), `task-events.test.ts` (8), plus 6 new budget / registry tests on the NF-2 files — full flow suite now 125 pass - [x] Every `ForgePort` method has a corresponding `forge.*` node (spec § Operation catalog); mutating subset = 11 nodes charges the budget - [x] Input schemas validate at handler entry; wrong-typed / missing ports reject before any adapter call lands - [x] `agent.dispatch` enqueues through injected `dispatch(type, params)`, subscribes to `TaskEventBus.once(taskId)`, and publishes the correct terminal trigger (`success` → `task.completed`, `failure` → `task.failed`, `cost_capped` → `task.cost_capped`) - [x] Default mutation budget (20) allows 20 parallel mutations; a 21st trips the cap without dispatching to the adapter - [x] `withForgeAndAgentNodes({ forge, agent })` composes NF-2 built-ins + `forge.*` + `agent.*` (34 types) - [x] `just qa` clean: typecheck + Biome check + Biome format + full server suite (1548 pass) Closes #324
feat(flows): forge.* + agent.* nodes with mutation budget (NF-3)
All checks were successful
qa / qa (pull_request) Successful in 4m42s
qa / dockerfile (pull_request) Successful in 12s
26889725ab
Extends the node registry with 21 `forge.*` wrappers (one per public
ForgePort method) and three `agent.*` primitives (dispatch / cancel /
raise_cap). Adds a per-run RateLimitBudget threaded through
NodeHandlerCtx — mutating handlers charge once on entry; queries are
free. Default ceiling is the spec-mandated 20 mutations / run, overridable
via `execute(…, { mutationBudget })`.

`agent.dispatch` subscribes to task completion via an in-process
TaskEventBus and publishes `task.completed` / `task.failed` /
`task.cost_capped` triggers back through an injected TriggerPublisher,
so follow-up flows see the task lifecycle as typed events.

Input schemas validate at handler entry (descriptor ports + repo parse
catch mis-wired edges at graph-load time); invalid shapes short-circuit
before any adapter / worker call lands. Every external surface
(adapter factory, dispatcher, raise-cap primitive, task subscriber,
trigger publisher) is injected so tests exercise the node set without
main.ts wiring.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Author
Collaborator

Rebase aborted — NF-3 already landed on main via #349 (commit bdd183b). Both PRs create the same files (forge-nodes.ts, agent-nodes.ts, plus tests) as add/add conflicts, with divergent implementations (#349: 1866 insertions, rate-limit.ts; this PR: 2551 insertions, task-events.ts + executor.ts/types.ts edits). Resolving the four add/add conflicts would mean rewriting one implementation on top of the other — outside the scope of a rebase.

Closing recommended. If any of this PR's additions (TaskEventBus / TriggerPublisher wiring, 21-wrapper forge catalog, executor/types threading) are worth keeping over what shipped in #349, they should be extracted into a follow-up against the current main.

Rebase aborted — NF-3 already landed on `main` via #349 (commit `bdd183b`). Both PRs create the same files (`forge-nodes.ts`, `agent-nodes.ts`, plus tests) as `add/add` conflicts, with divergent implementations (#349: 1866 insertions, `rate-limit.ts`; this PR: 2551 insertions, `task-events.ts` + `executor.ts`/`types.ts` edits). Resolving the four `add/add` conflicts would mean rewriting one implementation on top of the other — outside the scope of a rebase. Closing recommended. If any of this PR's additions (TaskEventBus / TriggerPublisher wiring, 21-wrapper forge catalog, executor/types threading) are worth keeping over what shipped in #349, they should be extracted into a follow-up against the current `main`.
Author
Collaborator

Rebase aborted — design invalidated by bdd183b (#349), which merged a parallel NF-3 implementation covering the same scope (forge.* + agent.* nodes + mutation budget).

Conflicts: add/add on agent-nodes.{ts,test.ts}, forge-nodes.{ts,test.ts}; content on executor.ts, types.ts. Resolving would require choosing one implementation wholesale (this PR uses a TaskEventBus + RateLimitBudget threaded via NodeHandlerCtx; #349 uses a standalone rate-limit.ts) — not a mechanical rebase.

Suggest closing this PR. If the TaskEventBus / ctx-threaded budget is worth salvaging, that's a follow-up issue against the merged NF-3 code.

Rebase aborted — design invalidated by `bdd183b` (#349), which merged a parallel NF-3 implementation covering the same scope (`forge.*` + `agent.*` nodes + mutation budget). Conflicts: add/add on `agent-nodes.{ts,test.ts}`, `forge-nodes.{ts,test.ts}`; content on `executor.ts`, `types.ts`. Resolving would require choosing one implementation wholesale (this PR uses a `TaskEventBus` + `RateLimitBudget` threaded via `NodeHandlerCtx`; #349 uses a standalone `rate-limit.ts`) — not a mechanical rebase. Suggest closing this PR. If the `TaskEventBus` / ctx-threaded budget is worth salvaging, that's a follow-up issue against the merged NF-3 code.
Author
Collaborator

Closing as superseded by #349 which landed NF-3 first and is already on main. Thanks for the parallel attempt — the ticket is closed and the implementation that merged is the canonical one. Closing this branch to keep the PR list clean.

Closing as superseded by #349 which landed NF-3 first and is already on main. Thanks for the parallel attempt — the ticket is closed and the implementation that merged is the canonical one. Closing this branch to keep the PR list clean.
code-lead closed this pull request 2026-04-24 14:08:48 +00:00
All checks were successful
qa / qa (pull_request) Successful in 4m42s
Required
Details
qa / dockerfile (pull_request) Successful in 12s

Pull request closed

Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
charles/claude-hooks!350
No description provided.