Skip to content

Frontstage Channel And Lease Roadmap

LoopX should not become a chat product. Its durable value is the backstage control plane: registry, active state, append-only event history, quota, gates, leases, and auditable recovery. The missing product layer is a frontstage projection that lets people understand and coordinate that control plane without reading raw CLI dumps.

This note frames the product direction as:

frontstage channel UX + backstage LoopX ledger

The channel is a view. The ledger is truth.

Product Boundary

LoopX should borrow collaboration language without moving the source of truth into chat history:

  • A goal can project as a channel: one timeline with latest state, next action, user todos, agent todos, gates, artifacts, quota, and run events.
  • An agent can project as a workspace member: controller, executor, reviewer, monitor, critic, or dreaming/planning proposer, each with scope and last action.
  • A task claim is a soft per-todo route by default. When a concrete contention case needs exclusivity, an optional hard lease adds TTL, write scope, idempotency, and conflict handling for one todo_id.
  • A chat or channel thread is a projection: useful for human collaboration, but never the only durable authority.

The key product lesson is not "add Slack-like chat". It is that humans think in channels, members, tasks, and approvals, while agents need registry, state, history, quota, gates, and leases.

Minimal Schemas

goal_channel_projection_v0

This is a read-only, human-facing projection over existing LoopX state. It lets a frontstage render a goal as a channel without making the channel a new source of truth. The append-only run ledger, active state, and registry remain authoritative; the projection only carries compact source references and freshness metadata.

{
  "schema_version": "goal_channel_projection_v0",
  "goal_id": "loopx-meta",
  "display_name": "LoopX Meta",
  "generated_at": "2026-06-20T00:00:00Z",
  "source_refs": {
    "status_generated_at": "2026-06-20T00:00:00Z",
    "active_state_updated_at": "2026-06-20T00:00:00Z",
    "latest_run_generated_at": "2026-06-19T23:55:00Z",
    "review_packet_generated_at": null
  },
  "waiting_on": "codex",
  "latest_status": "terminal_bench_case_running",
  "next_action": "compact-poll the active benchmark job",
  "decision_frame": {
    "user_action_required": false,
    "agent_action_required": true,
    "quiet_noop_allowed": false
  },
  "quota": {
    "state": "eligible",
    "reason": "1 compute quota",
    "spend_policy": "spend after validated writeback"
  },
  "user_todos": [
    {
      "todo_id": "todo_user_1",
      "title": "Review the bounded delivery packet.",
      "status": "open",
      "priority": "P0"
    }
  ],
  "agent_todos": [
    {
      "todo_id": "todo_agent_1",
      "title": "Advance the first executable safe side path.",
      "status": "open",
      "priority": "P1",
      "claimed_by": "codex-side-bypass"
    }
  ],
  "open_gates": [
    {
      "gate_id": "gate_owner_decision",
      "kind": "operator_gate",
      "status": "waiting_on_user",
      "blocks": ["todo_user_1"]
    }
  ],
  "artifacts": [
    {
      "kind": "doc",
      "label": "latest public review packet",
      "path": "docs/showcases/README.md"
    }
  ],
  "active_leases": [
    {
      "todo_id": "todo_agent_1",
      "owner_agent": "codex-side-bypass",
      "lease_until": "2026-06-20T00:30:00Z",
      "write_scope": ["docs/**"]
    }
  ],
  "recent_events": [
    {
      "generated_at": "2026-06-19T23:55:00Z",
      "classification": "validated_progress",
      "summary": "public-safe compact progress event"
    }
  ],
  "source_warnings": []
}

The v0 source map should stay boring and inspectable:

Projection field Source surface
goal_id, display_name, waiting_on, latest_status loopx status project asset and registry metadata
next_action, user_todos, agent_todos, open_gates active state todo/gate sections plus review-packet summaries
decision_frame interaction_contract from quota should-run and review-packet routing
quota quota should-run, including the spend policy and capability/workspace guards when present
artifacts public-safe docs, compact run artifacts, review packets, or showcase assets already allowed by goal_boundary
active_leases current soft claims and explicitly supplied optional task_lease_v0 rows
recent_events compact run-history rows only, not raw logs or transcripts
source_warnings stale state, todo projection gaps, private-boundary omissions, or missing authority sources

The projection must exclude raw chat transcripts, raw benchmark task text, raw trajectories, credentials, production logs, private document URLs, local absolute paths, and write-capable commands. If a useful frontstage field would need one of those sources, emit a compact source_warnings item instead of copying the raw material.

Frontstage consumers should treat this as an input snapshot:

  • refresh it from LoopX rather than editing it in the UI;
  • render controlled actions as links to CLI/review-packet flows, not as hidden write authority;
  • show stale or missing-source warnings near the affected card;
  • keep event detail drill-downs tied to compact run artifacts; and
  • never let the channel view override goal_boundary, operator gates, quota, required capabilities, workspace guards, or task leases.

The first product-path read model lives in loopx/control_plane/goals/goal_channel_projection.py and is covered by examples/project/goal-channel-projection-smoke.py plus examples/project/goal-channel-frontstage-fixture-smoke.py. It intentionally stays read-only: callers pass already-compact status, quota, run-history, review-packet, artifact, and lease/claim payloads; the builder emits source_warnings when raw or private-looking fields appear instead of copying those values into the channel. The static HTML renderer in loopx/presentation/renderers/goal_channel_html.py and fixture in examples/goal-channel-frontstage-fixture.py renders that projection into semantic panels with data-panel markers, no write controls, and a visible truth contract. loopx --format json status and the loopback serve-status feed now expose the same read-only projection on attention_queue.items[].goal_channel_projection, so a dashboard can render the channel without recomputing project truth.

agent_profile_v1 And agent_member_v1

The registry-owned agent_profile_v1 contract is defined in docs/product/foundations/agent-profile-contract.md. Use it as the source of truth for registered agent id and advisory capability, scope, and action preferences. Runtime authority still comes from peer identity, task claims/leases, boundaries, repository policy, and explicit continuation policy. The channel roadmap only needs the read-only member projection.

This is an identity and activity projection for an actor participating in a goal:

{
  "schema_version": "agent_member_v1",
  "agent_id": "codex-local-controller",
  "agent_model": "peer_v1",
  "profile_role": "reviewer",
  "profile_role_is_advisory": true,
  "goal_id": "loopx-meta",
  "current_claims": ["todo_abc123"],
  "last_action": "refresh_state",
  "handoff_assignment_status": "task_policy_selected"
}

Profile roles should stay product-level and portable: executor, reviewer, monitor, critic, dreaming proposer. They guide UI copy and discovery, not identity rank or default permission. Concrete authority comes from goal_boundary, claims/leases, typed task policy, and active-state todos.

task_lease_v0

This optional local file-backed concurrency contract is shipped through loopx task-lease acquire|renew|transfer|release|inspect. It does not replace the default soft claimed_by route or participate in quota decisions. The pending key is per todo: (goal_id, todo_id). Do not serialize an entire goal just because one todo is claimed; independent todos under the same goal should remain independently claimable when gates and write scopes allow it. LoopX does not have a separate issue object in this runtime model: goal_id names the control-plane boundary, and todo_id names the work item inside that boundary. The peer control plane keeps assignment explicit: claimed_by or a task lease owns one todo, and repository-writing peers use isolated worktrees when task or goal policy requires it. A small AGENTS-eligible change may self-merge with evidence; otherwise completion creates an independent successor or an explicit review action over an independent handoff, optionally excluding the author.

{
  "schema_version": "task_lease_v0",
  "goal_id": "loopx-meta",
  "todo_id": "todo_123",
  "owner": "codex-local-controller",
  "idempotency_key": "loopx-meta:todo_123:20260615T1230Z",
  "write_scopes": ["docs/product/roadmaps/frontstage-channel-lease-roadmap.md"],
  "version": 1,
  "acquired_at": "2026-06-15T12:00:00Z",
  "updated_at": "2026-06-15T12:00:00Z",
  "expires_at": "2026-06-15T12:30:00Z",
  "status": "active"
}

The current implementation is local and file-backed, with per-goal locking, renewal, transfer, release, registered-owner validation, and stale-owner invalidation. A later server can own the same schema and coordination surface. Conflicts should be detected by (goal_id, todo_id) plus overlapping write-scope checks: another agent may claim a different todo in the same goal, but a second pending claim on the same todo must fail closed, renew, or explicitly transfer ownership.

Priority

P1:

  • Keep the shipped optional task_lease_v0 runtime and conflict smoke stable. Adopt it in a host execution path only after a concrete concurrent-write bad case demonstrates value; do not silently turn it into a default quota gate.
  • Treat the shipped React /frontstage route as the baseline goal_channel_projection_v0 reader. Future work should polish visual acceptance, operator onboarding, and local fixture realism while preserving the invariant that the CLI/status export is the source and the browser has no write authority.

P2:

  • Decide whether active hard-lease rows should join the existing agent-member status/review projection after an adoption case proves the extra signal useful.
  • Build a Raft-style local frontstage view that renders channel timelines and member activity from LoopX projections.
  • Let dreaming/planning proposals appear as a separate channel lane or badge.
  • Add bridge adapters that can post channel summaries to collaboration tools, while preserving LoopX as the ledger of record.

Non-Goals

  • Do not make conversation history the only project state.
  • Do not let UI membership labels override goal_boundary, operator gates, or run permissions.
  • Do not require a server for the first schema; the CLI must remain a usable fallback/client.
  • Do not let background dreaming claim delivery work without the normal quota should-run and lease path.

Acceptance Frame

The first successful slice should prove that a human can open one goal view and see:

  • what the goal is;
  • who or what is currently responsible;
  • which task is claimed and until when;
  • which files/surfaces that claim may touch;
  • which event made the current state true;
  • what the next safe action is.

The corresponding agent should be able to read the machine projection and avoid double-running, double-spending, or writing outside scope.