# Roadmap

Build order de-risks the unproven shell API first and defers the large Discord build, even though capture currently lives in Discord. Reavo keeps copy-pasting ideas out of Discord until Phase 3; in the meantime the DRI creates issues from those pastes and the system is dogfooded from there.

**Status: all four phases delivered** (Phase 4 closed 2026-07-25). What follows is the
build path as planned, annotated with what shipped; waves after Phase 4 are recorded in
`W*-PLAN.md` and the sections below them.

## Phase 1 — Shell + GitHub, no Discord, no daemon — **delivered**

Prove the shell API end-to-end against a **dummy testing repo** (never a real-work repo) before anything depends on it.

- Alchemy shell adapter, bound to one repo, alias names the repo.
- Verbs: `create`, `view`, `list`, `state`, `tag`, `comment`, `help` (`create`/`comment` ride `spt shell send`; the rest ride `spt shell cmd`).
- State in the `state: *` label (format `state: VALUE`); the full State set and mapping from ADR-0004.
- Credentials from Windows Credential Manager, env-var override, resolution order: flag → env → store.
- Driven by hand from an agent. Surfaces the first doyle feature requests (e.g. `--json` on write verbs) while they are cheap.

## Phase 2 — Dispatch + Done automation (the MVP) — **delivered**

The slice that removes the copy-paste dispatch bottleneck. Deliverable without any Discord.

- `dispatch` (push) → auto-transition to WIP; any endpoint may dispatch to any other.
- Agents receiving a dispatch are instructed to write `fixes #N`.
- Merge-close → Acceptance; release sweep reads the release's closed issues → Done, posts the roundup.
- `Done` via release (primary) or Operator override (C); verification-pass sweeper (B) deferred until needed.

## Phase 3 — Hub Daemon + Discord sync — **delivered**

The large build, now on a proven core.

- Hub Daemon: detached child of a shell instance on the configured node, singular Discord gateway connection, GitHub polling (no public ingress).
- `#`-capture → Seed → Type-reaction mint → Bot post; Needs Operator button on the Bot post.
- State threads, relocation on transition, `#edit` reply flow + Edit modal (prefilled).
- Seeds / Updates / Releases threads. Runs in a **separate Discord server** from the personal legacy server.

## Phase 4 — Multi-agent + team layer — **delivered** (W14 Watches, W15 Milestones, W16 Tags + Liaison)

Depends on everything below it.

- Watches: every-state-change stream per Request, `--states` filter (fires at registration when already reached or passed), one-shot default / persistent, `--for` on-behalf ownership; registry = per-repo masterlist issue (`kind: SPT-TRACKING`), one comment per Watch (ADR-0009); Watch engine polls GitHub independent of the Discord gateway. Stand in for cross-Project blocking.
- Milestones as `kind: MILESTONE` parent issues with sub-issues (ADR-0005); greenlight is milestone-level only and Greenlit/WIP/Acceptance cascade to live children (never Done, never terminal children); `milestone` verb takes ref lists; milestone cards live in Active/Inactive Milestones threads and list their sub-issues.
- Liaisons, off-node submit-and-comment, the `#< … #>` tag syntax (digest-scanned, `seq`/`--after` replay-safe, challenge + confirm-tag round-trip on destructive writes); one live Liaison for spt-progress-tool.
- ~~Legacy import~~ — cut (Operator ruling 2026-07-23): legacy items are hand-added as ordinary Requests; no Imported thread, no Verification pass.

## Distribution — **delivered** (W17, unplanned scope)

Not in the original four phases: alchemy was registered in dev copy-mode from a stable
directory, so no other node could get it and this one could only move forward by hand.
W17 made it shippable — `[update] avenue = "gh_release"` in the manifest, `v0.2.0`
published on `BigscreenVR/spt-progress-tool` with `adapter.spt` + `SHA256SUMS`, and
`docs/RELEASE-RUNBOOK.md` as the source of truth. Acquisition (`adapter add --release`)
and update both work; *spawning* from a release install does not, because spt-core
resolves neither the install dir nor `{adapter_dir}` for `[shell].spawn` — filed, with a
local absolute-path registration as the interim (`W17-PLAN.md`, `docs/KNOWN-HAZARDS.md`).
Signing is deliberately deferred: it needs a key-custody decision, which is the
Operator's, not the DRI's.

## Known unknowns to resolve during build

- ~~Whether an owner seated on node B can drive a shell instance on node A~~ — **resolved NO** (empirical, ball-b @ ENLYZEAM, 2026-07-23): `spt shell spawn` refuses on a node without the adapter registered (`SHELL_ADAPTER_UNREGISTERED`, no cross-node routing) and a foreign owner's instance is invisible cross-node (`NO_SHELL:… for <owner>` — per-owner, per-node scoping). Motivated spt-core request filed with doyle; until it lands, remote CRUD proxies through a Liaison or dispatch.
- ~~`spt shell cmd --json` on action verbs, to return a new issue number inline instead of via a later `spt send`~~ — **resolved NO** (empirical, this node, 2026-07-25): the drive commands are dispatch-only. `spt shell cmd --json alchemy-1 help` and `spt shell send --json alchemy-1 help` both return the plain human ack `SHELL_SPOOLED:… (relay drain: api poll --link)` — not JSON, and carrying no shell result; the shell's answer arrived afterwards as an ordinary `spt send` message. (`--json` must also precede the shell ref: placed after the op it is consumed as a positional arg and the vocabulary check refuses it.) So a Liaison cannot answer "filed as #N" in the same turn it files. spt-core request filed with doyle; until it lands, a Liaison files and then relays the shell's later message.
- The cross-org sub-issue REST/changelog contradiction — irrelevant while grouping stays intra-repo, but test before ever relying on cross-owner sub-issues.
