Commit Graph

5 Commits

Author SHA1 Message Date
soroush.asadi 2ebe2808be Wire skills into agent runs: org-scoped, published-only, org-preferred resolution
ISkillCatalog.GetByKeysAsync now takes the org id and resolves each key within that org's namespace
only — the org's own published skill, else a shared builtin (null org), never another org's. Org-owned
is preferred over the builtin; only Published (golden-tested) skills are injected; the resolved
skill@version is recorded in the prompt heading and run trace. AgentRunExecutor threads
context.OrganizationId. SeatsPage now loads the org library (builtins + authored + installed), dedupes
to one entry per key, and flags drafts (won't run until published).

Verified: ArchitectureTests 8/8, IntegrationTests 48/48 (new SkillRunScopingTests: a run assembles the
org's own skill over the builtin of the same key, and another org's same-key skill never leaks in),
client build green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 13:35:53 +03:30
soroush.asadi fe7a5c481e M6: working memory + the PO→QA trigger + analytics — V1 complete
Working memory (Memory module's first real code):
- MemoryEntry (schema "memory", vector(384), InitialMemory migration); TeamMemory implements
  the SharedKernel ITeamMemory seam (embed-and-store on write, cosine recall on read);
  GET /api/memory/search. HashingTextEmbedder promoted to SharedKernel (pure, deterministic;
  swapped for ONNX/BYOK embedders later behind ITextEmbedder).
- Written on approval: Governance's approve stores an Approval/Correction entry per decision.
- Read at assembly: the executor recalls the team's top-3 relevant entries; the prompt gains
  a "# Team memory" section (treated as data, not instructions).

The single V1 event trigger:
- IAgentDispatcher (SharedKernel) implemented by Assembler's AgentRunDispatcher (shared by
  the API and triggers). OrgBoard's QaHandoffTrigger: a task hitting done creates a QA task
  (provenance parent, assigned to the QA agent) and dispatches a run for the team's QA AI
  seat. Guardrails: Test/Review tasks never re-trigger (no self-cascade) and a task hands
  off at most once. Audited as handoff.triggered.

Analytics — the V1 verdict view:
- IBoardStats (SharedKernel) implemented by OrgBoard; GET /api/governance/analytics returns
  approval rate, avg edit distance, per-agent metrics + edit-distance trend, tasks done.
- UI: /analytics — stat cards, per-agent table, recharts edit-distance trend per agent.

Verified: build green; ArchitectureTests 8/8; IntegrationTests 42/42 incl. the M6 acceptance
end to end — a dev marks a story done → Quill wakes via the handoff (QA task with provenance,
assigned to the agent) → drafts a test plan that waits in review → approve records the second
agent's edit distance → analytics show approval rate 100%, avg edit distance > 0, and trends
for BOTH Aria and Quill; memory written on Aria's corrected approval is recalled into her next
prompt; the guardrails hold. Client build green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 12:07:35 +03:30
soroush.asadi d83ad87151 M5: action gate + review inbox — edit distance captured for real
SharedKernel:
- ActionRisk (risk lives on the action) + GatePolicy (the pure autonomy x risk matrix:
  Read never holds, Draft/Publish hold unless Autonomous, Destructive ALWAYS holds).
- IActionGate (AgentActionProposal -> execute|hold) and IBoardWriter.AttachArtifactAsync.

Governance:
- ReviewItem (held action: artifact, child titles, trace, decision, edit distance) in a new
  review_items table (AddReviewItems migration).
- ActionGate: hold -> ReviewItem + "action.held" audit; autonomous -> execute + audit.
- HeldActionExecutor: writes the artifact onto the task and creates the child tasks via
  IBoardWriter (implemented by OrgBoard — no cross-module table access).
- Review inbox API: GET /api/governance/reviews (scope-filtered to where the caller may
  approve), POST /reviews/{id}/approve (optional edited content/children -> normalized
  edit distance recorded — the north-star metric), POST /reviews/{id}/sendback. Deciding
  twice is 409; Members are 403.

Assembler:
- OutputParser (numbered-list child titles, conservative) and the executor now hands every
  completed run's proposal to the gate.

OrgBoard: WorkItem.AttachArtifact + BoardWriter.AttachArtifactAsync.

Verified: build green; ArchitectureTests 8/8; IntegrationTests 41/41 incl. the full M5
acceptance — Aria (gated) proposes a spec, it waits in the inbox with its trace, a Member is
403'd, the owner edits-and-approves, the spec + four child stories land on the board, edit
distance > 0 is recorded and audited; Quill (autonomous) executes straight to the board;
destructive holds even for an autonomous seat and can be sent back. Plus the GatePolicy matrix.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 07:45:35 +03:30
soroush.asadi d9f9349117 M4: the assembler — assemble → model → parse (Increment 2)
SharedKernel contracts (so Assembler stays decoupled): IAgentRunContextProvider (agent +
task) and ISkillCatalog (skill prompts by key). Implemented by OrgBoard (AgentRunContextProvider)
and Skills (SkillCatalog).

Assembler:
- PromptAssembler builds house-style + identity + the agent's skill bodies + the task, and
  derives the primary action + risk from the agent's first skill. RAG/working-memory join at M6.
- AgentRunExecutor (real): resolve context + skills → assemble → resolve BYOK config (with
  fallback) → call IModelClient → parse into action + risk → capture all on the AgentRun.

Verified: build green; ArchitectureTests 8/8; IntegrationTests 29/29 — incl. the M4 acceptance:
assigning a Spec task to Aria (PO, gated, stub BYOK) yields a Completed run with the assembled
prompt (skill body + task title), action "write-spec", risk "Draft", and model output. Nothing
executes — the gate is M5.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 06:19:02 +03:30
soroush.asadi 09eaf360a3 M4: agent-run job queue + worker drain (Increment 1)
SharedKernel: IWorkerModule seam (RegisterWorker runs in the worker host only).
Bootstrap: AddTeamUpWorkerServices; the worker host now wires it.

Assembler module (schema "assembler", InitialAssembler migration):
- Job (Pending→Processing→Done/Failed) + AgentRun (Queued→Running→Completed/Failed) entities.
- JobQueue: enqueue + ClaimNextAsync using `FOR UPDATE SKIP LOCKED` in a transaction.
- AgentRunExecutor (Increment-1 placeholder — real assemble/model/parse lands in Increment 2).
- JobProcessor BackgroundService drains the queue on the worker host (web off the model path).
- POST /api/assembler/runs enqueues a run; GET /api/assembler/runs/{id} reads it.

Verified: build green; ArchitectureTests 8/8 (Assembler references only SharedKernel);
IntegrationTests 28/28 incl. enqueue→claim(SKIP LOCKED)→process→Completed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 01:16:37 +03:30