session-origin¶
PENDING design — a session's worktree ORIGIN becomes polymorphic (fresh node branch, or seeded from a PR), so an external PR can be pulled in as an ordinary agent-governed session. One seeding primitive; spex new --from-pr the only new surface. No code yet.
raw source¶
A session today is always born the same way: cut a node/<id> branch off the trunk and worktree it. But a
session is really just an agent governing a worktree — and the worktree's starting contents are a
construction parameter, not the session's identity. Once you can seed that worktree from anywhere in
git, an external branch or pull request (yours, or a collaborator's) becomes an ordinary SpexCode session:
a dedicated agent runs it, reads it, fixes it, and delivers it (deliver-port) — the thing SpexCode
never had, a way to receive outside contributions.
expanded spec¶
Origin is one polymorphic field, seeded once then forgotten. .session gains origin (and its source
ref); the portable-layout linker reads it. Two origins to start:
- fresh — a new
node/<id>branch off the trunk. The default; today's behaviour, byte-for-byte. - pr — fetch the pull request's head into the worktree (GitHub
refs/pull/<n>/head, GitLabrefs/merge-requests/<n>/head— a driver detail, so it routes through spec-forge's host-agnostic port, never aif githubin the session code).
Internally there is ONE seed-from-any-ref primitive; the CLI exposes only spex new --from-pr <url|#>
because that is the real need (collaborate on a PR). --from-branch and other origins are a zero-cost
future surfacing of the same primitive, held back on YAGNI until a real need names them.
A pulled-in session does NOT mint a spec node — and that is not a leak. The tidy "one session, one
node" reading was wrong: session ↔ node is a contract relation, not a production one. Every
session works under a governing spec (it references the nodes whose files it touches); only a delivery
whose destination is the trunk requires authoring — the fused spec+code commit — because that is the
trunk's own admission gate (main-guard / spec-lint sit on the gate, not on the session). So there
is one kind of session with the gate at the landing place, never two species (spec-native vs foreign).
A from-pr session references the governing nodes of the files its PR touches and delivers a verdict
by default (deliver-port); it authors a node only if a maintainer retargets it to the trunk.
This also names an accident already in the tree: a session whose branch was a raw forge URL had to make
the node id double as the origin (the URL stood in as the node name), which is why its spex ls label
read as a URL. With origin a first-class .session field, the node id goes back to being purely a
spec-tree name — the neighbouring scenario the fix also explains.