fix(operations): per-project git sync + completion receipts in brief (S2, S3)

Brief.Git was a single GitSync read from ORCHESTRA_DATA (never a git
checkout), and completions were counted but discarded their report_ref/
receipt. Brief.Git is now keyed by project ID and built from each
project's real repo; GitSync gained Ahead/Behind vs upstream; Brief now
carries Receipts pulled from each TaskCompleted payload.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W1rkJ2hBMybnJctPbcy4tT
This commit is contained in:
kami
2026-07-27 23:25:01 +04:00
parent 1f46a34afb
commit 5fb88724bd
5 changed files with 97 additions and 13 deletions
+27
View File
@@ -840,6 +840,33 @@ by `TestFanoutContinuesAfterSendError` (`internal/delivery/delivery_test.go`
sender both receive the event, the cursor still advances, and `Run` only
exits on context cancellation, never on the send error.
### S2, S3 — closed, 2026-07-27
`Brief.Git` was a single `GitSync` read from `ORCHESTRA_DATA` (the event-log
directory, never a git checkout, so it always reported `"git unavailable"`) —
S2 named this and asked for per-project state from the actual worktrees.
`Brief.Git` is now `map[string]GitSync` keyed by project ID; `/v1/brief`
(`cmd/orchestra/main.go`) builds it from `registry.Project.Repo` for every
project that sets one, falling back to a single `"default"` entry keyed off
`ORCHESTRA_REPO` for single-repo deployments that predate per-project repos.
`operations.GitState` also gained `Ahead`/`Behind` (via
`git rev-list --left-range --count @{u}...HEAD`) so "what pushed" and "what
workpc still needs to pull" (§7.4's own phrasing) are both answerable, not
just branch/HEAD/dirty.
S3: `BuildBrief` counted `TaskCompleted` but discarded the payload, so the
brief never carried the `report_ref`/receipt proofs §7.4 names as the reason
completions are surfaced at all ("the receipts for every completion"). Added
`operations.CompletionReceipt{TaskID, ReportRef, Receipt}` and
`Brief.Receipts []CompletionReceipt`, populated straight from each
`TaskCompleted` event's existing payload (no new event fields needed —
`domain.ValidatePayload` already requires both on every `TaskCompleted`).
Covered by an updated `TestBuildBrief` (`internal/operations/operations_test.go`)
asserting a completion's `report_ref`/`receipt` and a project's `GitSync`
both come through in the brief.
`go build ./...`, `go vet ./...`, `go test ./...` all pass.
### Design consequences (not yet implemented)
1. **Percentages are a level, not a delta.**