checkpoint: multi-repo Gitea ingestion, per-project repos, rotation anchor_sha fix

Pre-existing uncommitted work found at session start: rotation now emits
anchor_sha on TaskReleased (previously silently dropped by store.Append
validation), multi-repo Gitea provider support, per-project git worktree
roots, and associated test coverage. Committing as a checkpoint before
starting remediation work tracked in AUDIT.md.
This commit is contained in:
kami
2026-07-27 18:15:02 +04:00
parent 325c684eb0
commit ce6f02f9e6
31 changed files with 2717 additions and 320 deletions
+163 -179
View File
@@ -2,197 +2,181 @@
Updated: 2026-07-26
## Gaps until full implementation
## Current state
This is the canonical, exhaustive server-side gap list against `orchestra-spec (1).md`. Full implementation is not complete until every item below is closed and covered by an integration test.
This is a working Go implementation of `orchestra-spec (1).md`'s Layer 13
(substrate, harness/rotation, continuity) plus a first cut of Layer 4
(surfaces). `go build ./...` and `go test ./...` both pass. The codebase is
small (~4.6k lines across `internal/{domain,store,provider,registry,router,
herdr,orchestrator,continuity,federation,delivery,authz,operations,admin}`
and `cmd/orchestra/main.go`).
- **Execution runtime:** construct adapters for Claude, Codex, opencode, and local-model herdrs from configuration; validate herdr protocol versions with `ping`; persist session/worktree mappings; recover or reconcile them after restart; and emit lifecycle events for startup, exit, failure, release, completion, and block outcomes.
- **Worktrees and Git transport:** implement project-aware repository/worktree resolution, immutable `TASK.md` provisioning, scratch-branch WIP commits, push/pull synchronization, cross-machine checkout coordination, and synchronization/error status exposed to operations.
- **Rotation control:** implement adapter turn-boundary callbacks for all harnesses, milestone and thrash triggers, soft/hard occupancy policy, handoff creation and schema validation, anchor/TASK.md validation before close, split-then-close ordering, kill/timeout handling, and lease transfer without duplicate sessions.
- **Harness monitoring:** implement Claude stop-hook integration, Codex active-session discovery from its state database, opencode server/SSE `session.status` monitoring with message-file/stats fallback, pane-exit handling, TTL fallback, and monitor health reporting.
- **Lifecycle contracts:** replace map-based lifecycle handling with typed payloads; enforce expected-version/TTL/anchor/receipt semantics; require valid completion reports and block evidence; validate all referenced artifacts and cross-field relationships; expose handoff/report upload and amendment APIs.
- **Router availability:** implement live herdr registration/heartbeat, protocol/reachability health, concurrency accounting from actual sessions, quota headroom filtering, conservative 80% quota-full behavior, and retry/lease recovery across restarts.
- **Providers:** run JSONL and Gitea workers with cancellation, restart/error supervision, deduplication/update semantics, terminal-state reflection, webhook/poll health, and provider-to-event audit metadata.
- **Quota and standup:** implement per-harness/per-window quota projection from native session data, rolling and weekly windows, receipts summed across rotations, 3am safety behavior, scheduled standup advisories, and approval-gated application of advisories.
- **Surfaces and delivery:** implement server-side event subscriptions, Telegram/ntfy brief and alert delivery, Gitea terminal reflection, Maven gated control, approval propagation/deduplication, and artifact revalidation at every control-capable boundary.
- **Federation:** implement worker registration, heartbeats, event/lease transport, offline reclamation, remote worktree ownership, cross-machine lease correctness, and authoritative synchronization state.
- **API and operations:** add readiness probes that test dependencies, herdr/provider/project administration and diagnostics, report/handoff/amendment endpoints, structured error responses, bounded request/body handling, event cursor/subscription semantics, and complete metrics for sessions, rotations, quota, providers, and failures.
- **Durability and safety:** persist runtime state needed for crash recovery, make background loops cancellable and supervised, ensure no orphaned lease/session can survive reconciliation, and remove remaining placeholder/generated lifecycle evidence.
- **Verification:** add end-to-end tests covering ingest → route → worktree → harness → rotation → completion, restart/replay, provider retries/reflection, authorization across every surface, quota exhaustion, worker loss, and concurrent version conflicts.
Earlier revisions of this file accumulated a long, self-contradictory
chronological log — gaps were listed as open in one section and then claimed
closed in a later section, sometimes inaccurately. This revision replaces
that log with one audited snapshot. Treat prior git history of this file as
session notes, not as ground truth.
## Implementation review — 2026-07-26
### Verified fixed this pass
`go test ./...` passes, but the implementation is still a tested substrate/router prototype rather than a functioning unattended multi-harness orchestra. The following gaps were verified against `orchestra-spec (1).md` and the current code:
- **Rotation emitted an invalid `TaskReleased` (the previously reported
highest-priority defect) — now fixed.** `internal/orchestrator.Coordinator.rotate`
built the release payload as `{"handoff_ref","reason"}`, omitting the
`anchor_sha` the spec (§4, §6.2) and `domain.ValidatePayload` require
whenever `handoff_ref` is present. `store.Append` would reject it, the
error was discarded (`if c.Store.Append(e) == nil`), and the lease/session
silently never rotated — the coordinator would just retry next tick with
no visible failure. Fixed by adding `herdr.HeadSHA(worktree)` and having
`rotate` populate `anchor_sha` from the real worktree HEAD before
appending; if the anchor can't be read, rotation now correctly skips that
tick (leaving the lease intact for TTL/next-tick reclaim) instead of
emitting a payload guaranteed to fail validation.
Covered by `internal/orchestrator/rotation_test.go`
(`TestRotationEmitsValidReleaseWithAnchorSHA`), which drives the real
`Coordinator.Monitor` loop against an actual git worktree and asserts the
emitted event passes `domain.ValidatePayload` with the correct SHA — the
previous end-to-end test masked this bug by manually crafting a
replacement `TaskReleased` event after observing the (silently failed)
adapter-side release.
- **The federation worker release endpoint had the same gap.** The
`/v1/federation/workers/{id}/release` handler (cmd/orchestra/main.go)
built `TaskReleased` from a request body with only `handoff_ref`, no
`anchor_sha`. Since a remote worker is the only party with the actual
checkout (§2.1: "validate against the local checkout wherever the harness
runs"), the endpoint now requires and forwards a 40-hex-char `anchor_sha`
in the request body, rejecting the call with 400 otherwise.
- **Harness execution is wired for configured Git/Codex deployments.** The router invokes the coordinator; `ORCHESTRA_REPO` + `ORCHESTRA_WORKTREE_ROOT` enable Git worktree creation, configured herdr socket adapters, session creation, and optional bootstrap. Other harness types and monitoring callbacks remain pending.
- **Rotation is partially implemented.** The configured coordinator polls adapter occupancy, releases above `ORCHESTRA_OCCUPANCY_HARD` (default 75%), and publishes a handoff-backed `TaskReleased` event. Turn-boundary callbacks, milestone/thrash triggers, and split-then-close safety remain pending.
- **Lifecycle API payloads are invalid.** The release, complete, and block endpoints all emit `{"source":"api"}`, while validation requires `handoff_ref` or `reason`, `report_ref`, and `blocker` respectively. The documented lifecycle endpoints therefore cannot complete successfully.
- **Provider integrations are partially wired.** JSONL watching and optional Gitea webhook/poll loops now start from environment configuration, but terminal reflection, provider health, cancellation, and delivery fan-out remain absent.
- **CAS references are not content-verified at event append.** Lifecycle events check that referenced files exist, but do not verify that the file content hashes to the supplied reference.
- **Replay bypasses event validation.** Startup replay unmarshals and applies events without validating the event envelope, payload schema, or sequence/version invariants.
- **Snapshots are written but never loaded or used for replay acceleration.** Startup always replays the complete event log.
- **Task creation projection is incomplete.** `parent`, `due`, `inherent_priority`, and `estimate` are defined in the domain model but are not projected from `TaskCreated` payloads.
- **Occupancy support is incomplete relative to the spec.** Native readers and configured hard-threshold monitoring exist, but Codex active-session discovery, opencode server/SSE plus fallback, and turn-boundary monitoring are not implemented.
- **Authorization is mostly enforced at HTTP ingress.** Lifecycle and approval handlers now call `AuthorizeEvent`; an absent surface still defaults to full-control Web, and non-HTTP/event-bus integrations remain unwired.
### Multi-repo Gitea ingestion (new)
The first pass closed the store/API defects (lifecycle defaults, CAS content verification, validated replay, snapshot loading, and projection of task metadata) and added optional Gitea webhook/poll wiring. The remaining server-side gaps are below.
- `provider.Gitea` gained an optional `Project` field and `SourceName()`
(`"gitea"` if unset, `"gitea:<project>"` if set) — the namespaced source
doubles as the `(source,external_id)` dedup key, so issue #7 in two
different repos never collides, and as the reflection dispatch key.
- New `provider.MultiGitea{Sources map[string]Gitea}` implements
`TaskReflector` by looking up `task.Source` and forwarding to the matching
Gitea instance — lets several Gitea repos (one per project) share one
`ReflectingSink`.
- New `provider.GiteaSourceConfig` + `LoadGiteaConfigs(path)` load a JSON
array of `{project,base_url,owner,repo,token,webhook_secret}`.
`main.go` reads this from `ORCHESTRA_GITEA_CONFIG` if set; each source
gets its own poll supervisor (`gitea:<project>`) and webhook path
(`/v1/providers/gitea/webhook/<project>`).
- The legacy single-repo env vars (`ORCHESTRA_GITEA_URL/TOKEN/OWNER/REPO/
WEBHOOK_SECRET`) still work unchanged when `ORCHESTRA_GITEA_CONFIG` is
unset — same unprefixed webhook path, same `project = ORCHESTRA_GITEA_REPO`
tagging, same dedup source `"gitea"` — so existing deployments and
already-configured Gitea webhooks need no changes.
- Added `internal/provider/gitea_test.go` — previously **there were zero
tests exercising the Gitea provider at all** despite progress.md's prior
claim of Gitea webhook/poll test coverage; that claim was not accurate.
New tests cover source-name namespacing, webhook signature
verification/rejection, project tagging, `MultiGitea` dispatch-by-source
(via two `httptest.Server`s, asserting only the right one is hit), and
`LoadGiteaConfigs` validation/duplicate-project rejection.
### Remaining server-side gaps
### Per-project repos (new)
- **The orchestration coordinator is operational but incomplete.** It is constructed from deployment configuration, resolves a worktree, invokes `herdr.Adapter.Lease`, bootstraps handoffs, monitors occupancy, and rotates through handoff references. Session mappings are in-memory and turn-boundary monitoring is still pending.
- **Rotation remains incomplete.** Occupancy-triggered release is wired, but adapter turn-boundary callbacks, milestone/thrash triggers, and split-then-close safety are not.
- **Harness discovery and registration are not operational.** Static herdr configuration and socket clients exist, but startup does not create adapters, ping configured herdrs, discover active Codex sessions, subscribe to opencode SSE, or run the required fallback/TTL monitoring loop.
- **Provider ingestion is only partially wired.** JSONL and Gitea are available when configured, but there is no provider lifecycle management, cancellation, error health projection, terminal-state reflection, or provider fan-out.
- **Lifecycle event contracts remain incomplete.** Validation does not enforce the spec's `expected_version`, `ttl`, `anchor_sha`, `receipt`, or optional `handoff_ref` relationships, and the HTTP API does not validate actor/surface authorization at the event construction site. Completion without a report currently creates a generated placeholder artifact rather than requiring the stop-hook/wrapper receipt described by the spec.
- **Quota and standup scheduling are not implemented.** The event types and brief fields are accepted, but there is no per-harness/window quota projection, conservative availability filter, 3am safety behavior, or scheduled standup advisory producer.
- **Brief delivery and provider reflection are not implemented.** `/v1/brief` is read-only and computes local git state, but no Telegram/ntfy delivery, Gitea terminal reflection, Maven subscription, or cross-surface approval subscriber is started by the server.
- **Federated worker behavior is not complete.** Machine affinity filtering is implemented, but there is no worker registration/heartbeat protocol, remote event transport, cross-machine worktree coordination, or server-side synchronization status beyond local git inspection.
- **The server API is narrower than the spec.** There are no explicit task amendment/report/handoff upload endpoints, event subscription/streaming endpoint, health/readiness detail for providers and herdrs, or administrative endpoints for project/machine/herdr status.
- `registry.Project` gained optional `repo`/`worktree_root` fields. Each
project can now resolve its own git checkout rather than every project
sharing one global `ORCHESTRA_REPO`/`ORCHESTRA_WORKTREE_ROOT` — matches
spec §2.2 ("projects are first-class and extensible... the binding is a
field + a config entry, not a schema change"). `main.go` builds a
`orchestrator.PerProjectGitWorktrees` from the registry, falling back to
the global default for any project that omits these fields, so
single-repo deployments are unaffected. Covered by
`internal/orchestrator/worktrees_test.go`.
The latest pass now applies `AuthorizeEvent` to lifecycle and approval writes and adds `/readyz` with router/provider configuration checks. Readiness is configuration-level only; it does not yet probe herdr/provider health.
### Closed this pass (were open gaps as of the last snapshot)
The lifecycle API contract pass now requires callers to provide explicit release evidence (`reason` or `handoff_ref`), a block `blocker`, and a completion `report_ref`. The server no longer creates generated placeholder completion artifacts or converts malformed/empty lifecycle bodies into defaults. Regression coverage validates that release, completion, and block events reject missing evidence.
- **Bus-level authorization.** `authz.AuthorizeEvent` is now enforced inside
`store.Append` itself — the single choke point every event passes through
(HTTP handlers, router, coordinator/rotation, providers, federation relay)
— not just at HTTP handlers. Event schema bumped to v2, which requires
every event to declare a `Surface`; a new `authz.System` surface (full
control) covers internal emitters (router leases/failures, coordinator
releases/blocks, standup advisory/apply). Schema v1 events on disk still
replay (tolerant reader). Covered by `internal/store/store_test.go` and
`internal/router/router_test.go` additions asserting a non-HTTP append
with no/wrong surface is rejected.
- **Dual quota windows.** `router.QuotaAvailability` now tracks a 5-hour
rolling window and a 7-day weekly window independently per harness
(`QuotaWindowLimits{FiveHour, Weekly}`), applying the conservative 80%
rule to each separately — a harness over threshold on either window is
unavailable. Replaces the old single-`Window` field. Covered by new
`router_test.go` cases for weekly-only and 5h-only exhaustion.
- **Turn-boundary detection made observable, not silently optional.**
Rotation still can't force a harness adapter to implement `TurnBoundary`
Face B, but an adapter that fails to answer it now blocks that tick's
release (never treats a failed check as "safe to proceed"), and any
adapter without the capability — or one whose check errors — increments
`MonitorHealth.TurnBoundaryDegraded`, exposed via the coordinator's health
endpoint so degraded-safety operation is visible, not silent.
- **Cross-machine lease correctness has a real test.**
`internal/integration/federation_lease_test.go`
(`TestCrossMachineLeaseAnchorAndQuotaArePerHost`) exercises a lease
claimed through the federation worker HTTP API, validates the anchor
against that worker's own local checkout (not the router's), and asserts
quota is accounted per-host. Spec §9 item 8 said "prove on the first
federated run" — this is that proof for the primitives that exist today
(registration, heartbeat, lease-claim); it does not yet run against two
real physical machines.
- **Fuzz coverage for lifecycle payload validation.**
`internal/domain/fuzz_test.go` adds `FuzzValidatePayload` and
`FuzzValidateEvent` covering all event types (including malformed nested
`receipt`/`knowledge` shapes) — asserts no panic and always a typed error
on adversarial input.
Item 1 substrate hardening pass: newly appended events use schema envelope version 1; replay rejects unsupported versions and non-object payloads; and `TaskLeased` carries an `expected_version` guard that is checked before append. Legacy envelope events remain readable for tolerant replay.
### Believed accurate from prior sessions (spot-checked, not exhaustively re-verified)
Harness registration now uses configured `harness` and `protocol` fields, pings each configured herdr before exposing it to orchestration, selects Claude/Codex/opencode adapters accordingly, and skips unavailable or unsupported deployments at startup. This is an initial discovery/health slice; active-session discovery and ongoing heartbeats remain open.
- Event log: append-only JSONL, versioned envelope (schema v1), snapshot
load/replay, CAS with content-hash verification at append.
- `domain.ValidatePayload` enforces required fields per event type,
including `expected_version`/`ttl` on `TaskLeased`, `anchor_sha` on
`TaskReleased` (now correctly emitted, see above), `report_ref`+`receipt`
on `TaskCompleted`, and `blocker` on `TaskBlocked`.
- Router: project→affinity→machine resolution, capability match, quota
availability at conservative 80% threshold, derived-importance ordering,
retry-then-`TaskFailed`.
- herdr adapters (Claude/Codex/opencode) with native occupancy readers,
optional `TurnBoundary`/`RotationSignal`/`PaneExit` capability interfaces,
bootstrap/lease/release/kill.
- Continuity: strict handoff schema/validation, CAS save/load, pickup
validation (HEAD match, dirty-file hashes, immutable `TASK.md` hash),
scratch-branch commit/push/pull helpers.
- Provider layer: JSONL watcher, Gitea webhook+poll with HMAC auth,
idempotent `(source,external_id)` dedup, terminal-state reflection,
supervised restart with backoff.
- Federation: worker registration, heartbeat/TTL offline detection, event
cursor polling/ack, lease claim endpoint.
- Authorization: bus-level capability table (notify-only / full / gated) is
applied to lifecycle and approval writes via `AuthorizeEvent`.
- Delivery: Telegram/ntfy fan-out for completion/failure/block/approval
events.
- `/readyz`, `/v1/brief`, `/v1/providers/health`, `/v1/standup` exist and
return real state (not stubs).
Added bounded `POST /v1/artifacts` CAS upload support for report/handoff evidence. It returns the verified content hash used by lifecycle events and rejects empty or oversized uploads.
## Known open gaps (named, not silently assumed done)
The coordinator now persists active task→herdr session mappings in an atomic runtime state file, reloads them after restart, reconciles them against durable task leases, kills stale recoverable sessions, and removes orphan mappings before monitoring begins.
- **Cross-machine lease correctness is proven at the primitive level, not on
real hardware.** `TestCrossMachineLeaseAnchorAndQuotaArePerHost` exercises
the federation worker HTTP API (registration, lease-claim, anchor
validation against the worker's own checkout, per-host quota) inside one
test process. Spec §9 item 8 says "prove on the first federated run" —
that means an actual homesrv/workpc pair over the real mesh, which this
repo cannot exercise by itself. Named here as the one item that needs a
live two-machine run to fully close, not more code.
- **Turn-boundary Face B still degrades to occupancy-only for adapters that
don't implement it**, by design — the spec's Face B is per-harness native
session state (Stop hook / rollout tail / SSE), which this repo can only
wire against a real running herdr+harness pair. The degradation is now
observable (`MonitorHealth.TurnBoundaryDegraded`) and blocks-on-failure
rather than silently proceeding, but whether Claude/Codex/opencode's
native hooks are wired in a live deployment is a deployment-config fact,
not something provable from source alone.
Provider supervision/reflection is now wired: Gitea webhook and polling use append-first task reflection, JSONL and Gitea loops restart with bounded backoff, and `/v1/providers/health` exposes running/error state. Provider lifecycle cancellation remains tied to process shutdown until the server gains a root cancellation context.
Quota reporting now has strict payload validation, and `router.QuotaAvailability` implements rolling-window conservative headroom filtering: a harness is considered full at 80% of its configured limit. Standup event payloads also require an items field; scheduled advisory production and approval application remain open.
Notification delivery now supports Telegram and ntfy fan-out for completion, failure, block, and approval events, with event cursors, bounded polling, and notify-only surface policy preserved. Configure `ORCHESTRA_TELEGRAM_BOT_TOKEN`/`ORCHESTRA_TELEGRAM_CHAT_ID` or `ORCHESTRA_NTFY_TOPIC` to enable it.
Rotation now honors an optional herdr turn-boundary probe (`pane.status`) before hard-threshold release. Adapters without the optional capability retain occupancy-based fallback behavior.
Federation control-plane foundations now include worker registration, heartbeat updates, TTL-based offline status, and `/v1/federation/workers` plus per-worker heartbeat endpoints. Remote event/lease transport and remote worktree ownership remain to be layered on this registry.
Configured herdr `quota_limit` values are now wired into router availability using the rolling-window 80% conservative filter; previously the quota implementation existed but was not active in server routing.
Quota/standup scheduling now treats `QuotaReported` and `StandupAdvisory` as global events, adds `/v1/standup` read/request behavior, and emits one daily advisory during the 03:00 UTC safety window. Advisory contents include queued, leased, and blocked tasks.
Harness adapters now expose optional `pane.rotation_signal` support for milestone/thrash triggers. The coordinator records the returned trigger reason in the handoff release and still requires a safe turn boundary before releasing.
The previously named remaining work is now implemented and integration-tested:
- quota receipts aggregate across rotations and rolling/weekly windows; conservative availability sums receipts;
- standup advisories have scheduled generation plus approval-gated application;
- federation has authenticated worker registration, heartbeat/offline reclamation, event cursor polling/ack, and lease claim/handoff coordination;
- provider supervision retries failed loops and terminal reflection is append-first;
- end-to-end tests cover ingest → route → lease → rotation → completion, restart/replay, orphan cleanup, provider retry/reflection, quota exhaustion, and version conflicts.
Recommended order:
1. Add the orchestration coordinator: lease → worktree → harness session → bootstrap → lifecycle events.
2. Implement rotation and turn-boundary monitoring.
3. Wire provider lifecycle management, JSONL startup, terminal reflection, and delivery integrations.
4. Add quota/standup projections and conservative availability filtering.
5. Add federated worker health/synchronization and the remaining control-plane API surface.
6. Add endpoint/contract tests for the coordinator and lifecycle receipts.
## Server implementation checklist
This is the implementation-oriented breakdown of the specification. It is a project checklist, not a replacement for the binding spec.
1. **Complete the substrate****baseline complete**
- Done: append-only JSONL event log, replay projection, task schema, optimistic versions, lifecycle events, lease TTL groundwork, CAS artifacts, sortable ULID-like IDs, event payload validation, CAS-reference validation, durable atomic snapshots, corruption errors during replay, fsync-backed event writes, and API event metadata.
- Follow-up hardening: replace the remaining map-based projection logic with generated/schema-backed payload structs and add snapshot-based replay acceleration.
2. **Provider layer****complete**
- Done: Provider/Sink contracts and replay-safe JSONL adapter.
- Done: append-only JSONL file watcher/ingester with rotation handling and bounded records.
- Done: Gitea issue adapter for webhook and open-issue polling, including label-to-capability mapping.
- Done: Gitea reflection for terminal task state, keyed by the task's stable external issue number.
- Done: constant-time HMAC webhook authentication and injectable HTTP clients for testing.
3. **Projects and machine registry****complete**
- Done: typed JSON project, machine, and herdr configuration with duplicate/reference validation.
- Done: machine-bound herdr registry with per-herdr capabilities, endpoint override, and concurrency configuration.
- Done: injectable reachability checks plus TCP reachability implementation.
- Done: hard project machine-affinity resolution; candidates are restricted to configured, reachable herdrs on allowed machines.
- Done: optional `ORCHESTRA_CONFIG` startup validation.
4. **Router and leases****complete**
- Done: manual lease/release/complete/block endpoints and lease-expiry release.
- Done: assignment on `TaskCreated` and lease release/expiry.
- Done: project-affinity, capability, reachability, availability, and concurrency filtering.
- Done: derived importance ordering, retry/backoff, and terminal `TaskFailed`.
5. **Herdr integration****complete**
- Done: Unix-socket JSON-RPC client, ping protocol check, semantic prompt/wait and worktree operations.
- Done: Claude, Codex, and opencode adapter contracts with bootstrap, release, kill, and occupancy methods.
- Done: native session usage readers and bounded current-turn occupancy calculation.
- Done: anchor validation primitive for split-then-close rotation safety.
6. **Continuity****complete**
- Done: strict JSON handoff schema/validator, including framed knowledge fields and size-safe typed fields.
- Done: CAS-backed handoff save/load with content-address verification.
- Done: pickup validation against repository HEAD, dirty-file hashes, and immutable `TASK.md` hash.
- Done: scratch-branch WIP commit helper and Markdown change notices.
7. **Authorization and surfaces****implemented**
- Done: centralized bus-level surface capabilities and optional bearer-token authentication.
- Done: full-control TUI/web policy, notify-only Telegram/ntfy policy, and gated MCP/Maven policy.
- Done: approval-request endpoint (`POST /v1/tasks/{id}/approval`) and approval event payload validation.
- Note: TUI/web, Telegram/ntfy, MCP, and Maven remain client integrations over the server's polling/event APIs; the server is the authorization boundary.
8. **Projections and operations****complete**
- Done: read-only windowed brief projection for completions, failures, blocks, approvals, quota reports, and local git sync state.
- Done: quota and standup event types are accepted by the event schema for projection/scheduling integrations.
- Done: git failures are surfaced as an unsynchronized/unavailable state.
- Done: operational projection code is covered by tests.
- Done: Prometheus-compatible task metrics and a systemd deployment unit.
## Completed
- Built the first Go server slice from `orchestra-spec (1).md`.
- Added append-only JSONL events and replay projection in `internal/store`.
- Added task creation, external-key deduplication, optimistic versions, lifecycle states, and SHA-256 CAS artifacts.
- Added HTTP endpoints on default port `9145`: health, task ingest/list, and event cursor reads.
- Added lease/release lifecycle endpoints and lease-expiry reclamation.
- Finished the item 1 provider port: `provider.Provider`/`Sink` interfaces and a replay-safe JSONL adapter.
- Finished item 2: JSONL watching, authenticated Gitea webhook/poll ingestion, and terminal-state reflection.
- Added event-type payload validation for lifecycle and amendment events.
- Unit tests pass with `go test ./...`.
- Implemented item 4 router assignment, lease-expiry polling, and retry policy.
- Implemented item 5 herdr socket integration, harness adapters, native occupancy readers, bootstrap, and anchor validation.
- Implemented item 6 continuity: validated CAS handoffs, pickup anchors/TASK.md, scratch-branch commits, and shared Markdown change notices.
## Current API additions
- `POST /v1/tasks/{id}/lease` with `{"harness_id":"...","ttl_seconds":1800}`
- `POST /v1/tasks/{id}/release`
- `POST /v1/tasks/{id}/complete`
- `POST /v1/tasks/{id}/block`
## Item 3 status
Item 3 (projects and machine registry) is implemented in `internal/registry`. Static JSON configuration is loaded and validated, projects resolve only to their explicitly configured machines, and candidate herdrs are filtered by registration and injected reachability. Set `ORCHESTRA_CONFIG` to validate a configuration file at server startup.
## Item 2 status
Item 2 (provider layer) is implemented. `internal/provider` now includes `JSONLWatcher`, `Gitea.Poll`, `Gitea.WebhookHandler`, `Gitea.IngestWebhook`, and `Gitea.ReflectTask`. Gitea ingestion remains idempotent through the store's `(source, external_id)` key. The server wiring can attach these components to deployment-specific routes and polling loops without adding provider-specific logic to the domain.
## Item 1 status
Item 1 (task schema + provider port + JSONL adapter) is implemented as the baseline slice. The event schema is still deliberately versionless and should receive an envelope/version field during item 2 without breaking tolerant readers.
## Important limitations
- This is still a Layer 1/2 prototype. Harness adapter and continuity primitives exist, but unattended orchestration, rotation, quota accounting, and delivery integrations are not server-wired.
- Surface authorization is enforced by the shared HTTP/bus policy; set `ORCHESTRA_*_TOKEN` variables to require bearer authentication per surface.
- Event payload validation currently checks required fields and primitive types; replace the remaining map-based application logic with typed payload structs before exposing the API beyond the homelab.
- Router retry counts/backoff and terminal `TaskFailed` are implemented; retry policy is currently configured in server wiring.
## Next agent: recommended order
1. Begin item 2: harden the event log and state projection with snapshots, corruption handling, and a versioned envelope.
2. Add project, machine, and herdr registries from static TOML/JSON config.
3. Implement router selection: project affinity, reachability, capability, availability, and importance ordering.
4. Add retry policy and a background lease-expiry loop.
5. Implement handoff/report schemas and CAS reference validation.
6. Integrate herdr only after the substrate/router tests are stable.
Everything else named as open in the previous snapshot (bus-level
authorization, dual 5h/weekly quota windows, fuzz coverage of lifecycle
payload validation) is now closed — see "Closed this pass" above. Broader
areas (provider layer, continuity, router matching, delivery, federation
registration) were spot-checked against the code and their tests and
matched their described behavior.