Skip to content

Change: skein-control-plane #120

Open

Description

@androidand
Proposal

Why

Charter §9.1 requires cross-repository orchestration in an independent Skein control
plane, separate from the per-repository project server, so the platform can drive Claude
Code and other runtimes without a permanent OpenCode dependency.

Research (R6/R7) found the control plane is already largely built in the Go skein
repo (github.com/androidand/skein): internal/domain has the full work model
(WorkRef, ClaimRequest/AdmitClaim with path-scope conflict detection,
WorkInventory, PortfolioSpec with cross-repo DependsOn, P1–P5 priority,
checkpoints, dirty-path ownership, findings); internal/funnel has ready-task picking;
internal/supervisor has admission/aging/antiloop/assignment; internal/watchdog has
lease and stuck-recovery. Its store is SQLite (single-host).

This change extracts and extends that orchestration into the independent control
plane: a distributed store for cross-host claims, project-server registration, the
specsync ready-work contract, and the llama-skein resource broker. It does not
reimplement the domain model and does not run model turns.

What Changes

  • Extract the pure domain primitives (WorkRef, ClaimRequest, AdmitClaim,
    ValidateClaimTarget, WorkInventory, PortfolioSpec, PathScope) into a shared
    package the control plane and project servers both use — no duplication.
  • Add a distributed store (PostgreSQL) for cross-host claims, workflow state, and
    execution records. Claims use transactional compare-and-swap with a fencing/ownership
    generation token (charter §8.5). The existing SQLite store remains for single-host
    runtime state.
  • Project-server registration: each project server registers with the control plane
    (repo id, capabilities, reachable agents); the control plane tracks which repo is
    owned by which server.
  • Ready-work contract: the control plane asks the specsync-backed tracker for
    claimable work (priority + dependencies) rather than re-deriving priority (charter
    §10.2, ADR 8).
  • Resource broker: requests GPU/inference allocations through the llama-skein lease
    API; llama-skein remains the authoritative lease holder (ADR 7).
  • API + CLI surface: skein status|projects|agents|work|fleet|trace|doctor
    (charter §17), reconciled with the existing Go skein CLI.
  • Reuse swarm-coordinator primitives (gates, rules, nudge, claims) as the
    project-local conductor; the control plane owns cross-repo assignment only.

Impact

  • Affected specs: skein-control-plane (new), swarm-coordinator (boundary clarified),
    auto-across-repos (ready-work integration), skein-pool (lease broker).
  • New Go service (or a new command in the existing skein binary) + PostgreSQL.
  • A project-server registration protocol (new).
  • No changes to the ACP runtime or the per-repo execution path.

Tasks

Phase 1: Domain extraction (reuse, don't duplicate)

  • 1.1 Extract the pure domain primitives from github.com/androidand/skein
    internal/domain into a shared package: WorkRef, PathScope, ClaimRequest,
    ClaimSnapshot, AdmitClaim, ValidateClaimTarget, WorkInventory,
    PortfolioSpec, PortfolioTask, ChangeSnapshot, TaskSnapshot,
    WorktreeSnapshot, DirtyPathSnapshot, WorkFinding.
  • 1.2 Keep the primitives storage- and transport-agnostic (pure functions; no
    SQLite/PostgreSQL import). Add unit tests for AdmitClaim scope-conflict cases
    (read/write overlap, change-level claims, same-task re-claim).
  • 1.3 Confirm which existing skein packages the control plane reuses vs.
    re-homes (R6): funnel (ready-task), supervisor (admission/aging/antiloop),
    watchdog (lease/stuck-recovery). Document the boundary in the change.

Phase 2: Distributed store

  • 2.1 PostgreSQL schema for cross-host claims, workflow state, and execution
    records (mirrors the domain model; single source of truth per concern, ADR 6).
  • 2.2 Transactional compare-and-swap claim grant with a fencing/ownership-generation
    token (charter §8.5). A stale claim cannot overwrite a newer generation.
  • 2.3 Reconciliation loop: re-read live claims, expire lapsed leases, release
    orphaned claims (no blind re-run of non-idempotent work).
  • 2.4 Test: two hosts race for the same task; exactly one wins; the loser gets a
    ClaimRejection naming the owner. Seen red against a naive store first.

Phase 3: Project-server registration

  • 3.1 Registration protocol: a project server registers (repo id, path, reachable
    agents, capabilities) and heartbeats; the control plane tracks ownership.
  • 3.2 Deregistration on server death (heartbeat lapse); its in-flight claims are
    released for re-claim, not silently dropped.
  • 3.3 The control plane never runs a model turn; it only assigns work to registered
    project servers / agents.

Phase 4: Ready-work contract

  • 4.1 Query the specsync-backed tracker for claimable work (priority + dependencies)
    — do not re-derive priority (ADR 8). needs-research R5: specsync is
    write-mostly; add a ready-work/claimable query (new specsync endpoint or
    control-plane-side tracker query).
  • 4.2 Missing tracker binding → explicit safe fallback (no silent approval of
    unchecked tasks).
  • 4.3 Cross-repo dependency resolution from PortfolioTask.DependsOn.

Phase 5: Resource broker

  • 5.1 Request GPU/inference allocations through the llama-skein lease API
    (POST/DELETE /api/slots/lease); llama-skein stays the authoritative lease holder
    (ADR 7).
  • 5.2 Scheduling policy (model suitability, context, warm reuse, fairness) lives in
    the broker; the lease lives in llama-skein.
  • 5.3 needs-research: llama-skein leases have no renewal or list endpoint
    (R4) — add renewal/list to llama-skein or model renewal client-side (owner
    decision).

Phase 6: API + CLI

  • 6.1 skein status|projects|agents|work|fleet|trace|doctor (charter §17),
    reconciled with the existing Go skein CLI conventions.
  • 6.2 Correlation IDs on every operation (objective/work_item/execution/agent/
    session/turn/model_request/lease/trace) — feeds skein-observability.

Phase 7: Cross-repo orchestration

  • 7.1 Funnel: pick ready tasks across the portfolio, respecting dependencies,
    priority, and path-scope claims.
  • 7.2 Assign to registered project servers; track execution records; nudge on
    stall (reuse swarm-coordinator primitives).
  • 7.3 Test: a two-repo objective with a cross-repo dependency completes in the
    correct order; no double-claim.

Phase 8: Distributed soak

  • 8.1 Soak the distributed control plane (multiple hosts, multiple repos) — feeds
    skein-soak-hardening.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions