Skip to content

T27 OS orchestra: lanes as panes -- spawn with a title, a brief file and a permission mode; wait, status and a read tail for T27OS_CTL #11316

Open

Description

@gHashTag

Owner directive 2026-10-20 (translated): "Switch to working through T27 OS, it is cheaper. Update the skills to work this way, improving the tools for remote control of the orchestra. And I must see in the app how the work goes."

Today the orchestrating session runs lanes as paid subagents. The cheaper path is a lane as an agent PANE of T27 OS: Claude Code in the pane runs on the key master's free tier (glm-4.5-flash, then OpenRouter :free, #11284, #11285), the owner watches every lane live in the window, and the orchestrator drives it with T27OS_CTL. Measured on the bench Mac: T27OS_CTL=list answers (pane 0 agent 0 state 2 flags 3 key 2); a restored pane answered a prompt in 7 s on glm-4.5-flash (#11284 acceptance).

What T27OS_CTL lacks for that (pty_server.t27 header: list, spawn, kill, read, write):

  1. A pane spawned for a lane starts claude --session-id ... --model ... with no permission mode, so the agent stops at the first tool prompt and the lane never runs unattended.
  2. No way to hand a pane a long brief: write types keys; a multi-line brief needs the text from a file.
  3. No "is it done": the orchestrator can only poll read. The server already receives the agent's hook payloads (T27OS_HOOK=1), so it can know when the agent stopped.
  4. No lane name: the owner cannot tell which pane is which lane.

Only .t27 (skill only-t27): every rule a tested fn in pty_logic.t27 / session_store.t27; pty_server.t27 only calls them.

Requirements

  • FR-001 (spawn of a lane): T27OS_CTL=spawn MUST accept T27OS_TITLE=<lane> (shown as the pane's title in the window and in list), T27OS_PROMPT_FILE=<path> (the brief given to the agent as its first prompt) and T27OS_PERM=<mode>, which puts --permission-mode <mode> on the claude command line. Only the modes the owner allows are accepted (see the owner's decision below); anything else is refused with a named error, never passed through.
  • FR-002 (wait): T27OS_CTL=wait T27OS_PANE=<n> [T27OS_TIMEOUT=<s>] MUST return when the pane's agent reports Stop through its hook (or the pane exits), printing idle, exited <code> or timeout.
  • FR-003 (status): one line per pane: pane, title, agent, key, model, state (busy / idle / exited), and the traffic light of T27 OS: a traffic light per agent pane and in the window foot: green paid, yellow free tier, red no balance #11314 once it exists.
  • FR-004 (read): T27OS_TAIL=<n> lines, so a report can be read without the whole scrollback.
  • FR-005: tests for every new decision (the command line with and without each flag, the refused modes, the wait outcomes from hook events, the status line).

The owner's decision this needs

Which permission mode a lane pane may get. Proposed default: acceptEdits (edits in the lane's own worktree without a prompt; every shell command still asks), plus nothing broader until the owner says so. bypassPermissions only on the owner's explicit word.

Boundary

  • specs/t27os/pty_server.t27
  • specs/t27os/pty_logic.t27
  • specs/t27os/session_store.t27

Success Criteria

  • t27c test-report on pty_logic.t27 and session_store.t27 prints FAIL 0 and vacuous passes 0; t27b test <spec> --check exit 0 for every changed spec
  • on the bench Mac: a lane pane spawned with a title and a brief file runs, wait returns idle, read with a tail shows its report, and the window shows the title

🤖 Generated with Claude Code

Activity

  1. gHashTag commented on Oct 20, 2026

    @gHashTag
    OwnerAuthor

    Owner's decision, 2026-10-20 (translated): option A. A lane pane gets --permission-mode acceptEdits plus an allowlist of t27c, t27b and git commands; everything else still asks. bypassPermissions stays refused.

    How this lands in #11316: T27OS_PERM accepts exactly acceptEdits (any other value is refused with a named error), and the pane's command line also carries --allowedTools with the allowlist: the t27c and t27b binaries, and the git verbs a lane needs (status, diff, log, add, commit, fetch, merge, rev-parse, ls-remote, and push origin HEAD:refs/heads/lane/*, never a force push). Until #11316 lands, the same rule is written into the lane worktree's own .claude/settings.local.json (git-ignored), so a pane started there runs unattended under the same limits.

    🤖 Generated with Claude Code

  2. gHashTag commented on Oct 20, 2026

    @gHashTag
    OwnerAuthor

    Measured while running the first two lanes as T27 OS panes (#11378, #11380), for the verbs of this issue:

    • write sends the text and its carriage return as one burst. Claude Code in the pane treats that as a paste, strips the carriage return ("Removed 1 invisible character - review and press Enter to send") and waits, so the brief is typed but never sent. A separate bare carriage return a second later (T27OS_KEYS empty) sends it. FR for this issue: write (or the brief of spawn with T27OS_PROMPT_FILE) MUST send the text, wait, then send the Enter as its own keystroke, and only after the agent's prompt is ready (a write about 10 s after spawn arrived before Claude Code was ready).
    • list showed state 3 for both panes while their agents were working; the agent's progress was readable only from its Claude Code session transcript (~/.claude/projects/<the pane's cwd, with "/" and "." as "-">/<session>.jsonl). FR for status: report busy or idle from the agent's hook events, and the last tool the agent ran.

    🤖 Generated with Claude Code

  3. gHashTag commented on Oct 20, 2026

    @gHashTag
    OwnerAuthor

    Measured, the first two real lanes run as T27 OS panes (#11378, #11380), on the running build (claude panes on glm-4.7-flash):

    • Both agents ignored the brief's paths and command lines. One read the specs of a different, stale checkout by absolute path, then the orchestrator's memory and session transcripts under the user's Claude directory; the other ran cd <that checkout> && t27c test-report ... with a bare t27c that is not on the allowlist. Under permission mode A every such read or command outside the lane worktree stops the pane at a permission prompt, so neither lane progressed (one pane twice). Both lanes were escalated to Sonnet subagents, as specs/claw/model_route.t27 prescribes after two failed pane attempts.
    • For this issue: a lane pane's permission file SHOULD also deny reads and edits outside the lane worktree and the stale-checkout cd, so the agent gets an error and goes on instead of waiting at a prompt; status SHOULD report a pane that is waiting at a permission prompt (it showed state 3, as if idle).
    • A small, path-pinned task (run one t27c line, write a file) passed unattended earlier the same evening; multi-file spec lanes did not on this model. The next pane try waits for the rebuild with the free-tier default glm-4.5-flash (T27 OS: a restored pane starts on the free flash model with the rotation's key and fails over on an empty key #11287).

    🤖 Generated with Claude Code

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