Skip to content

feat(coordination): autonomous-org backend — Brain loop + org.* bus + durable human-queue + dispatch - #211

Open
LamaSu wants to merge 6 commits into
masterfrom
feat/coordination-org-backend
Open

feat(coordination): autonomous-org backend — Brain loop + org.* bus + durable human-queue + dispatch#211
LamaSu wants to merge 6 commits into
masterfrom
feat/coordination-org-backend

Conversation

@LamaSu

@LamaSu LamaSu commented Jul 7, 2026

Copy link
Copy Markdown
Owner

Additive packages/coordination — the autonomous-org backend that ADOPTS the control-plane spine (does not fork it).

  • Brain loop (draft-first + kill switch, external-scheduler over @pcc/workflow)
  • org.* event bus (@pcc/a2a) + reaction engine + facet snapshot
  • Durable SQLite human-queue + idempotent workflow dispatch
  • 3 integration contracts as importable fns/seams: (a) OrgApprovalItem + listApprovals/resolveApproval, (b) watchOrgEvents(frameFactory), (c) Brain-intent + dispatchViaBroker

8/8 tests incl the kill-and-resume acceptance test; typecheck + build clean. Additive-only, no settlement touched. HTTP routes (/org/approvals, /org/watch) mounting in @pcc/gateway as a follow-on. Design: ai/strategy/pcc-autonomous-org-v2.md + coord doc §9.

🤖 Generated with Claude Code

LamaSu and others added 6 commits July 6, 2026 21:01
…ns, durable queue

Vertical slice foundation for the PCC autonomous-org coordination backend
(packages/coordination). Additive-only under packages/coordination/** per
ai/strategy/org-build/coordination-build.spec.md.

- snapshot/facade-snapshot.ts: read-only OrgFacadeSource tap -> OrgSnapshot,
  with a StubFacadeSource until real gateway-facade wiring lands.
- events/org-bus.ts: OrgBus wraps @pcc/a2a's message-bus backend on org.*
  subjects (exports ORG_BUS_FROM for reuse by the contract-(a) mapper).
- reactions/rule-engine.ts: declarative {match(event)->action} registry +
  the one shipped rule, staleKernelRule (observe-only escalation).
- queue/human-queue.ts: durable (own SQLite table, WAL) human-in-the-loop
  queue with a dispatch-linkage field; adds replaceActionArgs() for
  contract (a)'s editedArgs support.

Updates pnpm-lock.yaml to resolve @pcc/coordination's already-declared
workspace deps (@pcc/a2a, @pcc/workflow, better-sqlite3).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TbAyQbTcK2TVT8ySjHyqf3
…rt channel

- brain/supervisor.ts: Brain.tick() is the external-scheduler-driven cycle
  (snapshot -> evaluate reactions -> enqueue). Draft-first by construction —
  never dispatches, never calls a broker. Kill switch checks an env var
  (PCC_COORDINATION_BRAIN_HALT) or an optional sentinel file on every tick;
  tripped = clean no-op, no throw. Owns its own SQLite file, separate from
  any prod DB.
- alerts/channel.ts: AlertChannel + ConsoleAlertChannel, the one stub
  channel (no @pcc/alerts package exists). Brain raises an alert alongside
  the durable queue item for high/critical-severity reactions.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TbAyQbTcK2TVT8ySjHyqf3
…-watch seam

- queue/org-approval-item.ts: the exact OrgApprovalItem schema from
  UI-COORDINATION.md contract (a), plus listApprovals()/resolveApproval() —
  the GET /org/approvals and POST /org/approvals/:id/resolve handler
  bodies. Pure additive mapping layer over human-queue.ts's internal
  storage shape (documented scope decision in the file docblock), same
  pattern contracts.js already uses for its own QueueItem conversions.
- events/org-watch.ts: contract (b) — watchOrgEvents() projects org.* onto
  AG-UI-shaped STATE_SNAPSHOT/STATE_DELTA/CUSTOM frames via a swappable
  frameFactory seam. Ships a dependency-free stubFrameFactory; does NOT
  hard-depend on the harness's cross-repo contracts.js path (see docblock).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TbAyQbTcK2TVT8ySjHyqf3
… index

- dispatch/workflow-dispatch.ts: WorkflowDispatcher.dispatchApproved()
  starts a trivial, durable ApprovedActionWorkflow for every approved,
  undispatched queue item. Two-layer idempotency (listApprovedUndispatched
  excludes already-dispatched items; engine.start({findOrCreate:true})
  derives the run id from the queue item id, so a crash between dispatch
  and recordDispatch() still resumes the same run on retry instead of
  starting a second one). Contract (c): dispatchViaBroker is the seam a
  real harness tool-broker wires in later; the default performs the local
  dispatch directly since no such broker exists in this slice yet. The
  workflow durably blocks on ACTION_COMPLETION_SIGNAL after its one stub
  step (no real completion source exists yet — see file docblock);
  acknowledgeCompletion() delivers it, resolving the queue item and
  publishing org.workflow.completed to close the loop.
- index.ts: public barrel re-exporting every module above.

Type note (documented inline): engine.start<Args extends CanonicalInput,R>
requires Args declared as `type X = {...}`, not `interface X {...}` —
verified empirically against the repo's own tsc (an interface fails
TypeScript's index-signature-missing check against CanonicalInput's object
union member even when every property is compatible).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TbAyQbTcK2TVT8ySjHyqf3
- __tests__/kill-resume.test.ts: THE acceptance test (spec definition of
  done). Drives a Brain tick to a pending queue item, separately enqueues
  + approves + dispatches a second item with a real action, confirms the
  resulting workflow is genuinely dispatched-but-incomplete (durably
  blocked on a signal nothing has sent), simulates an ungraceful kill
  (drops every reference without closing anything), reopens everything
  against the same SQLite file, and asserts: the approved item + its
  dispatchRunId survive, WorkflowEngine.recover() resumes the SAME run,
  and a second dispatchApproved() pass dispatches nothing new.
- __tests__/org-approval-item.test.ts: contract (a) mapping derivations
  (authorityClass/trustLevel/persona/severity) + listApprovals/resolveApproval.
- __tests__/workflow-dispatch-completion.test.ts: proves "completion emits
  an org.* event closing the loop" — the one path kill-resume.test.ts
  deliberately does not exercise (it needs the run to stay incomplete).
- README.md: design principles, module map, the three integration
  contracts, usage, and honestly-documented known gaps.

Verified: pnpm --filter @pcc/coordination typecheck (clean), build (clean),
test -> 3 files / 8 tests passing, including the kill-resume acceptance
test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TbAyQbTcK2TVT8ySjHyqf3
…gateway HTTP routes

Adds packages/gateway/src/routes/org.ts, an additive-only HTTP adapter over
@pcc/coordination's three integration contracts, so the control-plane's
Approvals inbox + Activity feed have a live backend:

  GET  /org/approvals?status=&persona=   -> listApprovals()
  POST /org/approvals/:id/resolve        -> resolveApproval()
  GET  /org/watch                        -> SSE stream of org.* events

@pcc/coordination is added as a workspace:* dependency of @pcc/gateway.
Registered in server.ts alongside adminObservabilityRoutes; no existing
route file touched. Frame factory seam documented (stays on the default
stubFrameFactory rather than reaching into an out-of-workspace harness
path). Verified live: 12 vitest cases in __tests__/org.test.ts, including
a real-socket SSE test that opens /org/watch, publishes an org.* event onto
the exact bus the route subscribed to, and reads the resulting CUSTOM frame
back over the wire.

AGENT_NAME: mount-org-routes

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vhf19Lf2GJYw3wBa5kyuNP
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.

1 participant