Commit Graph

9 Commits

Author SHA1 Message Date
kami c85fb81663 feat(orchestrator): milestone rotation and thrash detection (S11)
Closes the last two S11 triggers. internal/herdr/activity.go normalizes
tool/function calls per harness (ClaudeActivity verified against the
existing transcript format, CodexActivity best-effort/unverified,
OpenCodeActivity refuses — no confirmed per-tool-call source exists) and
implements the three thrash rules plus a narrow milestone check
(successful git commit as the last call).

CLIAdapter.RequestHandoffReason asks the agent to write a handoff with
meta.reason set, same "ask, don't invent" pattern as the existing handoff/
report requests. rotate() and TurnDecision generalize the manual-bypass
shortcut to manual/milestone/thrash and request (never directly release)
on a detected trigger.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W1rkJ2hBMybnJctPbcy4tT
2026-07-28 00:09:57 +04:00
kami 86cc0b9276 feat(orchestrator): agent-initiated ROTATE via handoff reason=manual (S11)
rotate() and TurnDecision now check the agent's own handoff for
meta.reason=="manual" before evaluating occupancy/turn-boundary — per
spec §5.3, that reason is itself the boundary signal ("a coherent unit
finished and the next is independent"), so it bypasses both checks and
releases immediately. Extracted the shared release-and-anchor-certify
tail into Coordinator.finishRelease so the manual path gets the same
anchor safety guarantee as the threshold path.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W1rkJ2hBMybnJctPbcy4tT
2026-07-27 23:44:04 +04:00
kami 84d09ce114 feat(orchestrator): soft occupancy threshold requests handoff early (S11 partial)
Coordinator.Soft (default 0.55, ORCHESTRA_OCCUPANCY_SOFT) makes rotate()
and TurnDecision request a handoff advisory-only once occupancy crosses
the soft threshold, well before Hard forces a release/rotation.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W1rkJ2hBMybnJctPbcy4tT
2026-07-27 23:40:46 +04:00
kami 972845bd98 feat(orchestrator): wire turn-decision endpoint and QuotaReported producer
Closes Phase 2 items 1-2 (AUDIT.md): Coordinator.TurnDecision evaluates
occupancy/turn-boundary/handoff state synchronously per turn and returns
continue/prepare_handoff/rotate_now/refuse, exposed via POST
/v1/harness/turn. The Claude Stop hook now calls it on ordinary turn
boundaries instead of no-op'ing, and exits 2 on refuse.

Also closes B7's post-hoc producer: /v1/harness/complete now appends a
QuotaReported event from the completing lease's harness usage, so the
router's quota-availability filter and the brief's quota_consumed stop
evaluating against a permanent zero. Live per-harness push producers
(Claude statusline, Codex rollout tail) remain unbuilt — investigation
recorded in AUDIT.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W1rkJ2hBMybnJctPbcy4tT
2026-07-27 23:17:21 +04:00
kami 0ca78243b9 feat(continuity): wire §6.3 shared-docs staleness notice
MarkdownChanges was deleted as dead code, but the underlying spec
requirement wasn't abandoned — rebuilt it independently. Adds
continuity.ConventionsHash for AGENTS.md/CLAUDE.md/VOCAB.md, tracks a
per-session snapshot on herdr.Session, and adds
Coordinator.checkConventions (run every Monitor tick) which compares
each active session's snapshot against its project's base repo and
pushes an in-pane notice via a new herdr.ConventionsNotifier
capability when they drift.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W1rkJ2hBMybnJctPbcy4tT
2026-07-27 22:25:53 +04:00
kami 3fe3aee5b7 fix(herdr): close Phase 4 item 2 — actually ask the agent for a handoff
Release already validated and uploaded a §6.1 handoff, but nothing ever
told the agent the .orchestra-handoff.json convention existed, so the
file it waited on never got written. rotate() now prompts the agent
once via a new optional herdr.HandoffRequester capability
(CLIAdapter.RequestHandoff) when the file is missing, and defers
Release until it appears, mirroring the .orchestra-report.md/B3 ask
pattern rather than inventing a handoff.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W1rkJ2hBMybnJctPbcy4tT
2026-07-27 22:10:22 +04:00
kami 7bcad64398 fix(orchestrator): wire TASK.md writing and §6.2 pickup validation (B6, partial)
Fixes AUDIT.md's B6: nothing wrote a TASK.md into a worktree, so
continuity.ValidatePickup had no caller and no file to check.

- continuity.RenderTaskFile/TaskFileHash: render and hash the immutable
  §6.2 TASK.md from a domain.Task.
- GitWorktrees.Create writes and commits TASK.md into every freshly
  created worktree (must be committed, not dirty, for ScratchCommit's
  immutability check and for a stable hash).
- Coordinator.Start now runs continuity.ValidatePickup (anchor SHA,
  dirty-file hashes, TASK.md hash) against the real worktree before
  bootstrapping a successor onto a handoff_ref, and blocks the task
  instead of bootstrapping on a validation failure.

Still open from Phase 4: handoff production (agent writing the real
handoff; Release still refuses per B5), ScratchCommit wiring before
release, and the §6.2 bootstrap-prompt rewrite — see AUDIT.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W1rkJ2hBMybnJctPbcy4tT
2026-07-27 21:44:00 +04:00
kami ac38b59322 fix(orchestrator): resolve adapters by herdr instance id, not harness kind (B2)
AdapterFactory.Herdrs is keyed by herdr instance id (e.g. "homesrv-claude"),
but Reconcile, expire, and rotate all looked adapters up by session.Harness
(the harness kind, e.g. "claude"). In production this key never resolves,
so every one of those call sites silently no-ops via a bare `continue`:
orphaned panes are never killed on restart, expired leases never kill their
pane, and rotation exits before it begins.

Add Coordinator.adapterFor(taskID, session), matching the fallback already
used correctly by refreshSessionHealth (HerdrID, then the lease's
HarnessID, then Harness as a last resort), and route all four call sites
through it.

Regression test TestAdapterResolvedByHerdrIDNotHarnessKind registers an
adapter under "homesrv-claude" and leases with Session.Harness == "claude"
(reproducing the real key mismatch) and asserts rotation still fires — the
existing rotation tests used a keyed-by-nothing fake adapter that matched
any lookup string and so masked this bug entirely.

AUDIT.md B2.
2026-07-27 18:18:50 +04:00
kami ce6f02f9e6 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.
2026-07-27 18:15:02 +04:00