Skip to content

design(pm-dispatch): launch pipeline, staged — validate the whole request at the boundary, one commit point, nothing after it can fail the launch #2668

Closed
4 of 4 issues completed

Description

@dezren39

Design (design-architect pass 19, 2026-10-30): pm-dispatch launch pipeline, staged. Full design doc: files/designs/code-pm-dispatch-launch-pipeline.md in the keep-the-four-repos-healthy goal workspace. No user/review — the four origin issues carry explicit acceptance, the codebase already embodies each rule locally (issue-creation warnings, the lane-ledger guard, the success-only JWKS cache), and the judgment calls are recorded in the doc. One timing call is flagged for Drew's attention rather than labelled: Phase 1 should land before the dispatch.security.cab tunnel hostname is added (README's remaining step), since it closes the two boundary holes below.

Summary

pm-dispatch (#2648, merged today) launches OpenCode sessions on the laptop from authenticated HTTP calls. Four bugs filed today — #2664, #2665, #2660, #2663 — are one per stage of its launch pipeline, with one root: the pipeline's stages and failure semantics were never stated, so each stage improvised. This design states them as three rules, generalising the patterns the code already uses locally:

  1. Boundary (Rule 1): everything the caller supplies is validated to its declared shape and scope before any side effect, and authorization binds the request's whole effect. parseJwt rejects non-plain-object header/payload decodings (→ AuthError, 401 — today a raw TypeError → 500, auth.ts:53-67,101, server mapping server.ts:376-379). directory resolves by rule: absent/blank → REPO_DIRS[repo]; otherwise an absolute path that is the repo primary (config.ts:25-30) or inside it, else 400 — today optString passes it verbatim (validate.ts:93-98, server.ts:180) and assertCallerRepo binds only the repo field (auth.ts:190-201), so a repo-bound OIDC caller can launch a session anywhere on the laptop. The rule applies to all caller types uniformly.
  2. Commit point (Rule 2): the claim PATCH is the launch's commit point. After it, steps are annotations: lane ledger (already guarded, server.ts:148-158), issue comment and labels (unguarded today, server.ts:161-166) become individually guarded — failure = response warning + task note ("launch unaffected" shape), never cancelTask, never 502, never a dispatch launch failed stamp on a live session (today: wait:true cancels the live session's task; wait:false mis-stamps it, pm-dispatch(sessions): a GitHub comment/label failure after the claim PATCH cancels a live session's queue task — the launched session keeps running untracked #2660). Cancel + 502 remains correct only at/before the commit point. README's flow section gains the stage/failure table.
  3. Retryable init (Rule 3): memoized async initialization caches success only. ensureWorker() (queue.ts:137-158, the service's only ??= promise memo) clears its memo on rejection so the next launch retries the idempotent registration — the fetchGithubJwks success-only-cache pattern already in auth.ts. Today one transient 500 wedges every launch until restart (pm-dispatch(queue): ensureWorker caches its first failure forever — one transient Supabase 500 permanently wedges every session launch until restart #2663).

Phases — adopted origins, no parallel issues filed

Each origin is a sub-issue of this issue, keeps its own queued triage packet, and carries an agent note recording this structure — triage must not re-file, re-scope, or split them.

Alternatives (recorded in the doc)

Fix-the-four-bugs with no stated model (improvisation already diverging inside one function — loses); per-caller directory rules (two auth models for one field; a leaked bearer becomes launch-anywhere — loses to uniform rule + a recorded extra-roots question); directory exactly equal to the primary (kills legitimate inside-tree dirs); reorder annotation before the claim (impossible — it announces the claim); TypeError→401 mapping at the handler (wrong layer; parse-time shape check closes the class, including the post-signature payload hole); backoff/timer retry for ensureWorker (call-driven retry suffices for an idempotent upsert).

Open questions (in the doc, not filed)

Extra roots allowlist if a real outside-tree worktree consumer appears; /v1/tasks inheriting the directory rule if it ever gains the field; annotation-failure visibility beyond warnings/notes; JWKS success-cache staleness on key rotation (pre-existing, noted only).


agent-note:v1 — filed by the repo design architect (dedicated code job, pass 19). Design doc and central register entry (files/potential-projects.md, status: proposed) accompany this issue.

Acceptance criteria

Activity

  1. added
    epicMeta-issue grouping multiple items (org Project Type=Epic)
    app/pm-stackpm-stack (Pad/Grist) in developing-today/code
    kind/designA design proposal (design-architect): multi-step, phased, decision-bearing
    on Oct 30, 2026
  2. dezren39 commented on Oct 30, 2026

    @dezren39
    MemberAuthor

    agent-note:v1 — design-architect origination (pass 19, 2026-10-30). This design adopts its four origin issues as phases — #2664 + #2665 (Phase 1, boundary), #2660 (Phase 2, commit point), #2663 (Phase 3, retryable init) — linked as sub-issues; no parallel implementation issues were filed and no new queue packets enqueued (each origin already carries a queued triage packet, and each carries an agent note recording its phase and the decisions above). Register entry added to files/potential-projects.md (status: proposed); design doc at files/designs/code-pm-dispatch-launch-pipeline.md in the keep-the-four-repos-healthy goal workspace. Audit base: origin/main 4b48bf1 (dispatch tree unchanged from 732ca26, the commit the origins cite).

  3. added
    priority/highImportant and time-sensitive
    effort/lLarge: multi-day or open-ended; expect staged check-ins
    meta/enrichedIntake review done: acceptance criteria, links, and normalized labels added
    on Oct 30, 2026
  4. dezren39 commented on Oct 30, 2026

    @dezren39
    MemberAuthor

    Intake review

    Fleet monitor intake pass (2026-10-30).

  5. 1 remaining item

  6. added
    queue/queuedHas a queued task in the Supabase agent queue
    task/triageQueue packet kind: verify, reproduce, and route this item
    on Nov 3, 2026
  7. developing-today commented on Nov 3, 2026

    @developing-today
    Contributor

    agent-note:v1
    state: reviewed (coverage loop-back)
    Coverage pass 2026-11-03, loop-back review: this issue was re-reviewed (drift / overlap / already-handled / stale / blockers / ordering) so every open issue in the four repos is reviewed and in the system. Verdict: still live; in the system as task 7347 (triage, queued, priority 50) in repo-health-code-pilot. Labels audited and synced. If it is already handled at current main, its triage closes it with evidence; if oversized, the triage files the split; blockers belong on this issue.
    Found via: coverage loop-back 2026-11-03

  8. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    Program tending — completion proposal (2026-11-03, via #1352)

    All 4 sub-issues of this epic are now closed: #2660, #2663, #2664, #2665 (verified this run via the REST sub_issues read, cross-checked in a separate call; this thread's last note recorded only #2660's closure).

    Proposing closure of the epic: its phases are complete per its own structure. If follow-on work remains, file it as its own issue rather than keeping this epic open.

  9. added
    queue/claimedQueue worker lifecycle state
    work/assignedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 4, 2026
  10. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    agent-note:v1
    state: picked_up
    Agent: repo-worker-code (OpenChamber scheduled lane)
    Session / ID: ses_e5e5bb716caffeYpbml7XIQd71 / queue task 7347 (triage)
    Found via: repo-health-code-pilot atomic claim, lane c8b9355e-319a-4640-8096-7ad19480d151
    Task: Revalidate this design epic at current main, keeping the pm-dispatch JWKS/OIDC outage separate from the design record; verify the four phase issues and their completion state.
    Expectation: Close with evidence if every phase is complete; otherwise name the exact remaining blocker or route the needed follow-up without duplicating existing work.
    Links: queue task 7347; #2668

  11. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    agent-note:v1
    state: done
    Agent: repo-worker-code (OpenChamber scheduled lane)
    Session / ID: ses_e5e5bb716caffeYpbml7XIQd71 / queue task 7347
    Found via: repo-health-code-pilot atomic claim, lane c8b9355e-319a-4640-8096-7ad19480d151
    Task: Triage the pm-dispatch launch-pipeline design epic, separately from the operational dispatch.security.cab JWKS/OIDC outage.
    Result: All four design phases are complete: #2660 is closed with PR #4231 merged (9456d01); #2663 is closed with PR #2908 merged (f0a7b0a); #2664 is closed with PR #3507 merged (2115038); and #2665 is closed with PR #4241 merged (115fe4f). Current main is b519288. The existing completion proposal is therefore supported; no remaining phase blocker was found.
    Caveat: PR #3483 remains open on closed issue #2664; it is assigned to dezren39 and is the stale duplicate of the merged #3507 work. It was left untouched under the Drew-owned PR restriction and does not block this design epic's completion.
    Expectation: Met — this design epic is complete and is being closed; the operational outage remains separate and is not addressed by this closure.
    Links: PR #4231 #4231 · PR #2908 #2908 · PR #3507 #3507 · PR #4241 #4241 · untouched PR #3483 #3483

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

Metadata

Metadata

Assignees

Labels

app/pm-stackpm-stack (Pad/Grist) in developing-today/codeeffort/lLarge: multi-day or open-ended; expect staged check-insepicMeta-issue grouping multiple items (org Project Type=Epic)kind/designA design proposal (design-architect): multi-step, phased, decision-bearingmeta/enrichedIntake review done: acceptance criteria, links, and normalized labels addedpriority/highImportant and time-sensitivesource/design-architectFiled by the repo design architect jobtask/triageQueue packet kind: verify, reproduce, and route this item

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions