spec-forge¶
Provenance¶
- Source:
.spec/spexcode/spec-forge/spec.md - Source SHA-256:
1172673c3ce33b0ee49c75da6bd5348acb1e485264aa0fc175bc897cc0279f19
A sibling package (alongside spec-cli, spec-dashboard, spec-eval) that relates an external forge's work objects to the spec graph. The two are different kinds of thing on different axes: a spec node defines (the condition/need), while a forge issue/PR does (the working process toward it). An issue is therefore not a node mirrored out — it is the work spawned by the gap between a node and reality. So spec-forge does not project the graph onto a forge; it reads the forge and links its work back to the nodes that work serves.
The bridge is a single host-agnostic [[port]] (ForgeDriver) that reads a host's open issues and
PRs; per-host drivers sit behind it (github via gh today; gitlab/bitbucket later). The host-agnostic
[[links]] resolver then inverts that raw work into node → { issues, prs }. The capstone [[forge-cli]]
exposes it on the real CLI as spex forge links. Downstream, this read also feeds the unified Issue
port (spec-cli's [[issues]]), where a forge issue and a local issue thread are the same object behind
per-issue storage; that Issue port is also the only caller allowed to use [[port]]'s narrow write verbs
(direct forge create, promotion, reply, close). The tracer path here stays read-only.
How a forge object names its node — three sources, no datastore of our own:
- PR branch (free): a PR heading off
node/<id>is structurally bound to that node — the convention SpexCode worktrees already use, no marker needed. - Issue-body marker (the one convention): an issue body line
Spec: <node-id>(comma-separated for several) names the node(s) it serves. Chosen over labels because it needs no per-node label pre-creation and scales to any number of nodes while staying human-visible. - Transitive (free): an unmarked issue still links through a PR that closes it on a node branch
(issue ←
closingIssuesReferences← PR → node).
The non-negotiable contract: git/.spec is the single source of truth. The forge owns execution
(its issues/PRs), the graph owns definition, and the two authorities never cross. Definition flows
DOWN (a node motivates work); the tracer never writes a node's version or status — a node's status stays
git-derived (deriveStatus), so the only execution fact that reaches the graph (a merge) arrives
through git, never through this package.
Out of scope: any write to a forge from the tracer (the [[port]] carries narrow write verbs used solely by the Issue port in spec-cli's [[issues]] — so the driver stays the single network seam; the tracer itself never writes), and surfacing links in the dashboard (a sibling node — this package is CLI-first because frontend can't be verified here).