opencode-gbuild 0.9.1 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -14
- package/index.ts +7 -2
- package/package.json +2 -2
- package/skills/design/SKILL.md +125 -0
- package/skills/plan/SKILL.md +12 -5
package/README.md
CHANGED
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
# gbuild — Claude Code + OpenCode plugin
|
|
2
2
|
|
|
3
|
-
Graph-native task planning and execution:
|
|
4
|
-
actual concurrent fan-out, a dedicated review pass on every node,
|
|
3
|
+
Graph-native task planning and execution: design a feature with the human, plan it as a real
|
|
4
|
+
dependency graph, then run it with actual concurrent fan-out, a dedicated review pass on every node,
|
|
5
|
+
and durable per-node checkpoints.
|
|
5
6
|
|
|
6
7
|
## The workflow
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
Design the feature first — `/gbuild:design` when the work needs shaping before it can be charted,
|
|
10
|
+
conversation (your agent's normal plan mode) when it doesn't — then hand it to gbuild:
|
|
9
11
|
|
|
10
|
-
1. `/gbuild:
|
|
11
|
-
2. `/gbuild:
|
|
12
|
-
3. `/gbuild:
|
|
13
|
-
4.
|
|
12
|
+
1. `/gbuild:design <the feature>` — shape it with the human into committed design artifacts (`docs/design/<slug>/`) on the feature branch in its own worktree; it ends only when you call the design good, and re-invoking with the slug resumes from the commits
|
|
13
|
+
2. `/gbuild:plan <the plan>` — chart it as a dependency graph
|
|
14
|
+
3. `/gbuild:run <slug>` — run it, once; it starts each node the moment its dependencies complete, until the graph completes (re-invoke only to resume an interrupted run)
|
|
15
|
+
4. `/gbuild:review <slug>` — audit the accumulated branch
|
|
16
|
+
5. Issues? `/gbuild:plan <slug> --add "<fix>"`, then `/gbuild:run` again. Clean? `/gbuild:pr <slug>`
|
|
14
17
|
|
|
15
|
-
The feature branch lives in its own git worktree (created by `plan`) — your checkout never changes
|
|
18
|
+
The feature branch lives in its own git worktree (created by `design` or `plan`) — your checkout never changes
|
|
16
19
|
branches, your uncommitted work is never in the way, and several features can be in flight in parallel
|
|
17
20
|
without racing each other's `HEAD`.
|
|
18
21
|
|
|
@@ -45,9 +48,9 @@ claude --plugin-dir ./plugins/gbuild
|
|
|
45
48
|
### OpenCode
|
|
46
49
|
|
|
47
50
|
The same directory is also an OpenCode (V2) plugin, published to npm as
|
|
48
|
-
[`opencode-gbuild`](https://www.npmjs.com/package/opencode-gbuild) — `index.ts` registers the
|
|
49
|
-
skills and
|
|
50
|
-
`/gbuild-pr`) from the same markdown the Claude plugin uses.
|
|
51
|
+
[`opencode-gbuild`](https://www.npmjs.com/package/opencode-gbuild) — `index.ts` registers the six
|
|
52
|
+
skills and six slash commands (`/gbuild-design`, `/gbuild-plan`, `/gbuild-run`, `/gbuild-status`,
|
|
53
|
+
`/gbuild-review`, `/gbuild-pr`) from the same markdown the Claude plugin uses.
|
|
51
54
|
|
|
52
55
|
```bash
|
|
53
56
|
opencode plugin add opencode-gbuild
|
|
@@ -83,6 +86,7 @@ prompt. The review is still a fresh, isolated agent — never the implementer.
|
|
|
83
86
|
Claude Code:
|
|
84
87
|
|
|
85
88
|
```
|
|
89
|
+
/gbuild:design add OAuth login with GitHub
|
|
86
90
|
/gbuild:plan add OAuth login with GitHub
|
|
87
91
|
/gbuild:run add-oauth-login-with-github
|
|
88
92
|
/gbuild:status add-oauth-login-with-github
|
|
@@ -93,6 +97,7 @@ Claude Code:
|
|
|
93
97
|
OpenCode (same order, kebab-case names):
|
|
94
98
|
|
|
95
99
|
```
|
|
100
|
+
/gbuild-design add OAuth login with GitHub
|
|
96
101
|
/gbuild-plan add OAuth login with GitHub
|
|
97
102
|
/gbuild-run add-oauth-login-with-github
|
|
98
103
|
/gbuild-status add-oauth-login-with-github
|
|
@@ -100,7 +105,17 @@ OpenCode (same order, kebab-case names):
|
|
|
100
105
|
/gbuild-pr add-oauth-login-with-github
|
|
101
106
|
```
|
|
102
107
|
|
|
103
|
-
- **`
|
|
108
|
+
- **`design`** shapes a feature with the human before `plan` charts it — for when the destination
|
|
109
|
+
still has options, the moving parts aren't named, or the trade-offs are unmade. It analyses the
|
|
110
|
+
codebase, drives the discussion in batched question rounds (the destination first, one line), and
|
|
111
|
+
commits each settled piece to `docs/design/<slug>/` on the feature branch in its own worktree —
|
|
112
|
+
`design.md` carries the destination, scope, decisions with their ruled-out alternatives, and the
|
|
113
|
+
open questions. It ends only when the human calls the design good — never on its own judgement —
|
|
114
|
+
writes no implementation (unknowns that need code become open questions for `plan` to chart as
|
|
115
|
+
`research` nodes), and runs without `cypherlite` or a store; re-invoking with the slug resumes
|
|
116
|
+
from the committed artifacts.
|
|
117
|
+
- **`plan`** creates the feature branch in its own worktree (reusing the one `design` left, when
|
|
118
|
+
there is one) and charts the feature into a
|
|
104
119
|
machine-local CypherLite graph store (`<git-common-dir>/gbuild/<feature>/db`) — `Feature`,
|
|
105
120
|
`Acceptance`, and `GbuildNode` nodes, each node's contract as `INPUT`/`OUTPUT` `Field` nodes, and
|
|
106
121
|
`FROM` edges carrying data from one node's output to the next node's input. Every dependency edge
|
|
@@ -263,7 +278,7 @@ plugins/gbuild/
|
|
|
263
278
|
reference/ # graph-format.md (normative model), cypher.md (how to talk to the store), queries.md (ad-hoc recipes); shapes/failure-policies/cost-model/checklist inform plan
|
|
264
279
|
cypher/ # schema, validate, progress/attention/status/node/feature reads, run's dispatch/record/set-status, and brief/check-result/symbols for its agents
|
|
265
280
|
templates/example.cypher # a worked 4-node diamond, written the way plan writes a feature
|
|
266
|
-
skills/{plan,run,status,review,pr}/
|
|
281
|
+
skills/{design,plan,run,status,review,pr}/
|
|
267
282
|
index.ts # OpenCode plugin entry: registers the skills + /gbuild-* commands, translating paths/names
|
|
268
283
|
package.json # OpenCode plugin manifest (npm package "opencode-gbuild")
|
|
269
284
|
cypher.test.ts # node --test contract tests for the Cypher layer (repo-root `npm test`)
|
|
@@ -276,7 +291,7 @@ It holds the plan, every node's status and output values, the full review histor
|
|
|
276
291
|
reviewer's checklist), and the notes and symbols agents left; CypherLite checkpoints the store on exit,
|
|
277
292
|
so `db/graph.json` is just the engine's local snapshot. All of a feature's worktrees live under
|
|
278
293
|
`.git/gbuild/<feature>/` — never in `git status`: `tree/` is the feature worktree itself, created by
|
|
279
|
-
`plan` and kept until the feature is done, and during a run each file-touching node gets a `<node>/`
|
|
294
|
+
`design` or `plan` and kept until the feature is done, and during a run each file-touching node gets a `<node>/`
|
|
280
295
|
worktree that is removed the moment its node is accepted (merged into the feature branch, in `tree/`)
|
|
281
296
|
or terminally failed (discarded). Beside them, `inbox/` holds the run's hand-off files (`<slug>.json`,
|
|
282
297
|
`<slug>.review.json`), emptied when a run starts and cleared for each node once it is recorded.
|
package/index.ts
CHANGED
|
@@ -19,7 +19,7 @@ import type { Plugin } from "@opencode/plugin"
|
|
|
19
19
|
|
|
20
20
|
const root = dirname(fileURLToPath(import.meta.url))
|
|
21
21
|
|
|
22
|
-
const SLUGS = ["plan", "run", "status", "review", "pr"] as const
|
|
22
|
+
const SLUGS = ["design", "plan", "run", "status", "review", "pr"] as const
|
|
23
23
|
type Slug = (typeof SLUGS)[number]
|
|
24
24
|
|
|
25
25
|
const OPENCODE_NOTES = `
|
|
@@ -61,10 +61,15 @@ const frontmatter = (raw: string): { description: string; body: string } => {
|
|
|
61
61
|
return { description, body: match[2] ?? "" }
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
// `/gbuild:<slug>` → `/gbuild-<slug>`, derived from SLUGS so the alternation
|
|
65
|
+
// can never drift from the registered skills (a "/" needs no escaping in the
|
|
66
|
+
// string form a RegExp constructor takes).
|
|
67
|
+
const SLUG_REF_RE = new RegExp(`/gbuild:(${SLUGS.join("|")})\\b`, "g")
|
|
68
|
+
|
|
64
69
|
const translate = (text: string): string =>
|
|
65
70
|
text
|
|
66
71
|
.replaceAll("${CLAUDE_PLUGIN_ROOT}", root)
|
|
67
|
-
.replace(
|
|
72
|
+
.replace(SLUG_REF_RE, "/gbuild-$1")
|
|
68
73
|
|
|
69
74
|
interface LoadedSkill {
|
|
70
75
|
readonly slug: Slug
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "opencode-gbuild",
|
|
4
|
-
"version": "0.
|
|
5
|
-
"description": "OpenCode plugin for gbuild —
|
|
4
|
+
"version": "0.10.0",
|
|
5
|
+
"description": "OpenCode plugin for gbuild — design a feature with the human, plan it as a dependency graph, run it with concurrent fan-out, per-node review, and durable checkpoints.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"author": {
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Designs a feature with the human — the design step before /gbuild:plan charts it: analyses the codebase, drives the discussion in batched question rounds, and commits the design artifacts (docs/design/<slug>/, entry doc design.md) to the feature branch in its own git worktree, never touching the main checkout. Ends only when the human calls the design good; re-invoking with the slug resumes from the committed artifacts. Runs without cypherlite and without a store — use when the work needs shaping before it can be charted.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Design the feature described by `$ARGUMENTS` — with the human, before `/gbuild:plan` charts it.
|
|
6
|
+
|
|
7
|
+
`plan` decomposes a feature that already makes sense: a one-line destination, a scope with edges,
|
|
8
|
+
constraints it can verify against. When the work isn't there yet — the destination still has
|
|
9
|
+
options, the moving parts aren't named, the trade-offs are unmade — this skill shapes it into
|
|
10
|
+
committed artifacts first. It writes the design onto the feature branch and stops: no graph, no
|
|
11
|
+
store, no implementation. The committed artifacts are the design's whole state, so re-invoking
|
|
12
|
+
`/gbuild:design <slug>` resumes exactly where the commits left off. After it, `/gbuild:plan <slug>`
|
|
13
|
+
has a design to decompose instead of a guess.
|
|
14
|
+
|
|
15
|
+
## Mode
|
|
16
|
+
|
|
17
|
+
| arguments | mode |
|
|
18
|
+
| --------------------------------------------------------- | --------------------------------------------------- |
|
|
19
|
+
| a description, link, or file path | **Design** — new feature |
|
|
20
|
+
| a slug with a feature worktree or branch, and no store | **Resume** — continue the committed artifacts |
|
|
21
|
+
| a slug whose store already exists | **Redirect** — `/gbuild:plan <slug> --add "<req>"` |
|
|
22
|
+
|
|
23
|
+
`$ARGUMENTS` is slug-shaped only if it is one kebab-case token. Then, in order: a store at
|
|
24
|
+
`<git-common-dir>/gbuild/<slug>/db` (its `graph.json` present) means `plan` already charted the
|
|
25
|
+
feature — don't design a charted feature; say so and point at `/gbuild:plan <slug> --add
|
|
26
|
+
"<requirement>"`, which is how a charted feature takes new work. A feature worktree or a branch
|
|
27
|
+
named `<slug>` or ending `/<slug>`, with no store, means a design started here and wasn't charted —
|
|
28
|
+
resume it. Anything else is a description — design it.
|
|
29
|
+
|
|
30
|
+
## Design
|
|
31
|
+
|
|
32
|
+
### 1. Slug, branch, and feature worktree
|
|
33
|
+
|
|
34
|
+
Derive the feature slug from `$ARGUMENTS`: kebab-case, ≤4 words, names the outcome not the mechanism
|
|
35
|
+
(`oauth-device-flow`, not `add-some-auth-stuff`). It names the artifact home below and the
|
|
36
|
+
`gbuild/<slug>/` directory `plan` later creates — immutable once the design is committed.
|
|
37
|
+
|
|
38
|
+
If the derived slug's store already exists (`<git-common-dir>/gbuild/<slug>/db`), stop: the feature
|
|
39
|
+
is charted, and new work goes to `/gbuild:plan <slug> --add`. Resolve `FT` (the feature worktree)
|
|
40
|
+
exactly as `/gbuild:plan`'s Chart step 1 describes (`${CLAUDE_PLUGIN_ROOT}/skills/plan/SKILL.md`) —
|
|
41
|
+
reuse the registered worktree, attach a branch checked out nowhere, or create branch and worktree
|
|
42
|
+
forked from the current HEAD. Report the branch and `FT`; everything below happens in `FT`. If
|
|
43
|
+
`docs/design/<slug>/` on that branch already has committed artifacts, this is a resume that arrived
|
|
44
|
+
as a description — read them (Resume below) instead of writing over them.
|
|
45
|
+
|
|
46
|
+
### 2. Analyse the codebase
|
|
47
|
+
|
|
48
|
+
Read the project manifest(s), directory structure, `README.md`, and the code the feature touches.
|
|
49
|
+
Resolve file paths or URLs in `$ARGUMENTS`; if a reference fails to load, say so and ask. For
|
|
50
|
+
related in-flight work — best-effort, never required: when `cypherlite` is on PATH, read the
|
|
51
|
+
`Feature` of every existing store (`feature.cypher` with `--read-only` against each
|
|
52
|
+
`<git-common-dir>/gbuild/*/db`, one at a time); when it isn't, skip — this skill needs neither
|
|
53
|
+
`cypherlite` nor a store, and never installs or creates either.
|
|
54
|
+
|
|
55
|
+
### 3. Fix the artifact home
|
|
56
|
+
|
|
57
|
+
The design artifacts live at `docs/design/<slug>/` on the feature branch; the entry doc is
|
|
58
|
+
`design.md`, and everything else hangs off it. Before writing anything, look at how the repo already
|
|
59
|
+
documents work — `docs/` layout, ADR or decision-record folders, README patterns — and follow an
|
|
60
|
+
existing convention when one is present: supporting docs take the repo's naming and format; only
|
|
61
|
+
the home and the entry doc are fixed here.
|
|
62
|
+
|
|
63
|
+
### 4. The design loop
|
|
64
|
+
|
|
65
|
+
The design is written by discussing it, one settled piece at a time. The loop runs until the human
|
|
66
|
+
calls the design good — never less, and never on your own judgement of when it's good enough.
|
|
67
|
+
|
|
68
|
+
1. **Open with what the analysis found.** A few lines: the pieces that exist, the gap, the
|
|
69
|
+
constraints — grounding, not a report. End with the first batch of questions.
|
|
70
|
+
2. **Ask in batches.** Put the round's open questions to the human in one message — cap at ~5. The
|
|
71
|
+
destination comes first, and it must end up one line, the thing that is true once this is done;
|
|
72
|
+
everything past it is scope to defend or cut. Then what the destination needs decided: scope
|
|
73
|
+
edges, naming, the trade-offs with real alternatives, the risks worth stating. Never one question
|
|
74
|
+
at a time, and never 20 questions — a round with more than ~5 open questions hasn't converged:
|
|
75
|
+
settle what the last answers gave you, and batch the rest into the next round.
|
|
76
|
+
3. **Settle as they solidify.** Fold each round's answers into the artifacts the moment they're
|
|
77
|
+
agreed, and commit — message `docs(design/<slug>): <what settled>` — so an interruption costs
|
|
78
|
+
nothing that had settled. `design.md` carries the state: the destination (one line), the scope
|
|
79
|
+
and out-of-scope, what the analysis found, each decision with its rationale and the alternatives
|
|
80
|
+
it ruled out, and the open questions still in play. Supporting docs — whatever this design
|
|
81
|
+
needs: diagrams, data shapes, interface sketches — follow the repo's convention (step 3).
|
|
82
|
+
4. **An unknown that needs code is an open question, not a prototype.** Design writes no
|
|
83
|
+
implementation — no scaffolding, no probes, no spike branches. A question the analysis can't
|
|
84
|
+
answer by reading goes into `design.md`'s open questions for `/gbuild:plan` to chart as a
|
|
85
|
+
`research` node.
|
|
86
|
+
|
|
87
|
+
### 5. Report and hand over
|
|
88
|
+
|
|
89
|
+
Only after the human has called the design good: ask nothing more, write and commit the last of it,
|
|
90
|
+
then report the artifacts (every file under `docs/design/<slug>/`), the branch, and `FT`. The feature
|
|
91
|
+
worktree stays — `plan` reuses it. Then both exits, the human's to pick:
|
|
92
|
+
|
|
93
|
+
- **Continue into gbuild** — `next: /gbuild:plan <slug>`.
|
|
94
|
+
- **A design review on a PR** — ask the agent to open it directly with `gh` from `FT` (push the
|
|
95
|
+
branch, `gh pr create`): `/gbuild:pr` can't, it needs a graph store, and a design isn't charted.
|
|
96
|
+
|
|
97
|
+
## Resume
|
|
98
|
+
|
|
99
|
+
Re-invoking `/gbuild:design <slug>` continues a design the feature worktree or branch already holds —
|
|
100
|
+
the mode table routed you here:
|
|
101
|
+
|
|
102
|
+
0. Resolve `FT` exactly as step 1 describes — reuse the registered worktree, attach the branch if
|
|
103
|
+
it's checked out nowhere. Never into the user's main checkout unless that's where the feature
|
|
104
|
+
branch already lives (a legacy feature).
|
|
105
|
+
1. Read the committed artifacts at `docs/design/<slug>/` in `FT`. `design.md` says what's decided
|
|
106
|
+
and what's open; the commit log says what settled when. Anything the loop left uncommitted never
|
|
107
|
+
settled — start that piece over.
|
|
108
|
+
2. Continue the loop (step 4) from the open questions. A settled decision reopens only on new
|
|
109
|
+
information, said out loud — not on a fresh context's second thoughts.
|
|
110
|
+
|
|
111
|
+
## Rules
|
|
112
|
+
|
|
113
|
+
- **Design, don't build.** Nothing lands on the branch but the artifacts under
|
|
114
|
+
`docs/design/<slug>/` — no implementation, no scaffolding, no probes. Unknowns that need code
|
|
115
|
+
become open questions for `plan` to chart as `research` nodes.
|
|
116
|
+
- **The human closes the design.** The loop ends on the human calling it good, never on your own
|
|
117
|
+
judgement; the closing report follows that word and nothing before it.
|
|
118
|
+
- **Commit as work solidifies.** Everything agreed is written and committed in the round it was
|
|
119
|
+
agreed in — the branch is the state, there is no store, and an interrupted design must resume
|
|
120
|
+
having lost nothing that had settled.
|
|
121
|
+
- **No cypherlite, no store.** This skill runs without either and never installs or creates
|
|
122
|
+
either: a store's existence only routes the mode, and sibling stores are read best-effort
|
|
123
|
+
(step 2), only when `cypherlite` is already on PATH.
|
|
124
|
+
- **The user's checkout never changes branch.** Every edit, commit, and check happens in `FT`; the
|
|
125
|
+
main tree is never touched.
|
package/skills/plan/SKILL.md
CHANGED
|
@@ -6,10 +6,11 @@ Plan the work described in `$ARGUMENTS` as a graph.
|
|
|
6
6
|
|
|
7
7
|
## The loop
|
|
8
8
|
|
|
9
|
-
The intended workflow:
|
|
10
|
-
skill: `/gbuild:run <slug>` once — it starts each
|
|
11
|
-
completes. Then `/gbuild:review <slug>`; if it
|
|
12
|
-
`/gbuild:plan <slug> --add "<fix>"` and `/gbuild:run` again; if clean,
|
|
9
|
+
The intended workflow: `/gbuild:design <slug>` when the work needs shaping, ordinary conversation
|
|
10
|
+
when it doesn't, then chart it here. After this skill: `/gbuild:run <slug>` once — it starts each
|
|
11
|
+
node as its dependencies complete, until the graph completes. Then `/gbuild:review <slug>`; if it
|
|
12
|
+
finds issues, reopen with `/gbuild:plan <slug> --add "<fix>"` and `/gbuild:run` again; if clean,
|
|
13
|
+
`/gbuild:pr <slug>`.
|
|
13
14
|
|
|
14
15
|
Read `${CLAUDE_PLUGIN_ROOT}/reference/graph-format.md` (the normative graph model) and
|
|
15
16
|
`${CLAUDE_PLUGIN_ROOT}/reference/cypher.md` (how to talk to the store) before doing anything, and run
|
|
@@ -63,7 +64,13 @@ Report the branch and `FT`. Everything below happens in `FT`; `DB` below is `WT/
|
|
|
63
64
|
Read the project manifest(s), directory structure, `README.md`, and — for related in-flight work — the
|
|
64
65
|
`Feature` of every existing store (`feature.cypher` with `--read-only` against each `GC/gbuild/*/db`,
|
|
65
66
|
one at a time). Resolve
|
|
66
|
-
file paths or URLs in `$ARGUMENTS`; if a reference fails to load, say so and ask.
|
|
67
|
+
file paths or URLs in `$ARGUMENTS`; if a reference fails to load, say so and ask. When `FT` holds the
|
|
68
|
+
feature's design artifacts — committed by `/gbuild:design` at `docs/design/<slug>/`, entry doc
|
|
69
|
+
`design.md`, everything else hanging off it — read all of them first: they are the design context the
|
|
70
|
+
graph is charted from; its settled decisions are facts to decompose, not questions to reopen. When
|
|
71
|
+
no design is at `docs/design/<slug>/` in `FT`, check `docs/design/*` in `FT` before charting
|
|
72
|
+
fresh: a re-described feature — the same work, described again under a different slug — still
|
|
73
|
+
finds its committed design that way, and it is read exactly as above.
|
|
67
74
|
|
|
68
75
|
### 3. Validate and explore
|
|
69
76
|
|