Today every extract requires a human to click "Run skill". The
next step is to react to source changes automatically: when a
sync brings in new or changed intent, fire extract on just those
units and one model pass over the resulting graph. HITL stays
intact — proposals still land in the pending inbox for human
review before they touch the graph.
Scope
- New domain port
Reactor in @braidhq/core/domain/reactor/.
ReactorService subscribes to WorkspaceEventBus; reacts to
source.synced only.
- On
source.synced:
- Call
IntentExtractionLedger.diff for the synced source.
- For each
new ∪ changed unit, dispatch braid-extract via
the existing SkillRunner.
- Dispatch one
braid-model pass once all extracts finish
(or fail).
- Update the ledger.
- PRODUCT.md gains:
reactor:
enabled: false # off by default
maxRunsPerHour: 5 # hard cap, fail-closed
- SSE events on the workspace bus:
reactor.dispatched,
reactor.completed, reactor.throttled.
- Studio: small banner under the existing in-flight-run banner.
Reuse cancel-run plumbing.
Out of scope
- Reacting to
proposal.applied (graph-delta drift sweep).
- Refining existing proposals; needs a Fork primitive.
- Per-workspace budget / cost meter. Hard cap is the v0
guardrail.
- Cohort tracking of proposals across reactor runs.
Acceptance
- Service unit test with fake event bus + fake skill runner:
emitting source.synced with 3 new units triggers 3 extracts
then 1 model.
maxRunsPerHour blocks the 6th dispatch within an hour and
emits reactor.throttled.
- Dogfood: enable reactor on a workspace whose intent source
points at this repo's issues. Close one issue, sync, observe
extract + model fire automatically — no CLI invocation.
Depends on: #27 #28.
Today every extract requires a human to click "Run skill". The
next step is to react to source changes automatically: when a
sync brings in new or changed intent, fire extract on just those
units and one model pass over the resulting graph. HITL stays
intact — proposals still land in the pending inbox for human
review before they touch the graph.
Scope
Reactorin@braidhq/core/domain/reactor/.ReactorServicesubscribes toWorkspaceEventBus; reacts tosource.syncedonly.source.synced:IntentExtractionLedger.difffor the synced source.new ∪ changedunit, dispatchbraid-extractviathe existing
SkillRunner.braid-modelpass once all extracts finish(or fail).
reactor.dispatched,reactor.completed,reactor.throttled.Reuse cancel-run plumbing.
Out of scope
proposal.applied(graph-delta drift sweep).guardrail.
Acceptance
emitting
source.syncedwith 3 new units triggers 3 extractsthen 1 model.
maxRunsPerHourblocks the 6th dispatch within an hour andemits
reactor.throttled.points at this repo's issues. Close one issue, sync, observe
extract + model fire automatically — no CLI invocation.
Depends on: #27 #28.