opencode-gbuild 0.6.3 → 0.7.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 +19 -8
- package/agents/gbuild-auditor.md +7 -5
- package/agents/gbuild-reviewer.md +15 -8
- package/index.ts +1 -1
- package/package.json +1 -1
- package/reference/cypher.md +10 -6
- package/reference/graph-format.md +5 -3
- package/reference/queries.md +3 -2
- package/skills/plan/SKILL.md +42 -23
- package/skills/pr/SKILL.md +18 -14
- package/skills/review/SKILL.md +13 -8
- package/skills/run/SKILL.md +50 -34
- package/skills/status/SKILL.md +9 -4
package/README.md
CHANGED
|
@@ -12,6 +12,10 @@ Plan in conversation first (your agent's normal plan mode), then hand that plan
|
|
|
12
12
|
3. `/gbuild:review <slug>` — audit the accumulated branch
|
|
13
13
|
4. Issues? `/gbuild:plan <slug> --add "<fix>"`, then `/gbuild:run` again. Clean? `/gbuild:pr <slug>`
|
|
14
14
|
|
|
15
|
+
The feature branch lives in its own git worktree (created by `plan`) — your checkout never changes
|
|
16
|
+
branches, your uncommitted work is never in the way, and several features can be in flight in parallel
|
|
17
|
+
without racing each other's `HEAD`.
|
|
18
|
+
|
|
15
19
|
(OpenCode: `/gbuild-plan`, `/gbuild-run`, … — same loop.)
|
|
16
20
|
|
|
17
21
|
Inspired by the graph-engineering thread at
|
|
@@ -93,7 +97,8 @@ OpenCode (same order, kebab-case names):
|
|
|
93
97
|
/gbuild-pr add-oauth-login-with-github
|
|
94
98
|
```
|
|
95
99
|
|
|
96
|
-
- **`plan`**
|
|
100
|
+
- **`plan`** creates the feature branch in its own git worktree and charts the feature into a
|
|
101
|
+
CypherLite graph store there (`.gbuild/<feature>/db/`) — `Feature`,
|
|
97
102
|
`Acceptance`, and `GbuildNode` nodes, each node's contract as `INPUT`/`OUTPUT` `Field` nodes, and
|
|
98
103
|
`FROM` edges carrying data from one node's output to the next node's input. Every dependency edge
|
|
99
104
|
passes the cut test — and because data flow is explicit, the validator checks it; every node has
|
|
@@ -101,12 +106,14 @@ OpenCode (same order, kebab-case names):
|
|
|
101
106
|
- **`run`** dispatches every node in the current ready wave concurrently — not one at a time — with
|
|
102
107
|
each file-touching node working in its own git worktree on its own branch, forked from the feature
|
|
103
108
|
branch. A dedicated `gbuild-reviewer` subagent reviews each node's output against its branch's diff;
|
|
104
|
-
only a passing node's branch is merged back into the feature branch
|
|
109
|
+
only a passing node's branch is merged back into the feature branch — in the feature's worktree, not
|
|
110
|
+
your checkout — and its worktree is removed.
|
|
105
111
|
Unaccepted work never lands. A review failure applies the node's declared failure policy. Re-invoking
|
|
106
112
|
after an interruption resumes only the remaining frontier, reusing the surviving worktrees.
|
|
107
113
|
- **`status`** reports the graph — frontier, blocked, in-flight, completed, each node's review verdict,
|
|
108
114
|
and evidence of what actually ran concurrently vs. serially.
|
|
109
|
-
- **`review`** audits the finished branch as a whole in a `gbuild-auditor` subagent
|
|
115
|
+
- **`review`** audits the finished branch as a whole in a `gbuild-auditor` subagent, working in the
|
|
116
|
+
feature worktree (the full suite runs there) — abstraction
|
|
110
117
|
quality, file size, spaghetti growth, and the cross-node duplication that per-node review can't see
|
|
111
118
|
(two nodes, two contexts, same sub-problem solved twice). Blocking findings go back into the graph as
|
|
112
119
|
a `plan --add` requirement. Ported from hone-ai's `review`.
|
|
@@ -185,7 +192,8 @@ curl -sSfL https://neo4j-labs.github.io/cypherlite/install.sh | bash
|
|
|
185
192
|
```
|
|
186
193
|
|
|
187
194
|
Every skill reads and writes the graph with `cypherlite` and nothing else — there is no Python and no
|
|
188
|
-
direct JSON editing. The plugin ships the queries as `.cypher` files; skills pipe them into the store
|
|
195
|
+
direct JSON editing. The plugin ships the queries as `.cypher` files; skills pipe them into the store
|
|
196
|
+
(`.gbuild/<feature>/db` inside the feature's worktree — examples below run from there):
|
|
189
197
|
|
|
190
198
|
```bash
|
|
191
199
|
cypherlite .gbuild/<feature>/db --mode jsonl < plugins/gbuild/cypher/validate.cypher # format gate: no output = valid
|
|
@@ -225,8 +233,11 @@ plugins/gbuild/
|
|
|
225
233
|
```
|
|
226
234
|
|
|
227
235
|
State lives outside the plugin, in the project: one CypherLite store per feature at
|
|
228
|
-
`.gbuild/<feature>/db
|
|
236
|
+
`.gbuild/<feature>/db/` inside the feature's own git worktree. It holds the plan, every node's status
|
|
237
|
+
and output values, and the full review
|
|
229
238
|
history. Only `db/graph.json` (CypherLite's JSON snapshot, kept current by every write) and the store's
|
|
230
|
-
own `.gitignore` are committed.
|
|
231
|
-
never in `git status`
|
|
232
|
-
|
|
239
|
+
own `.gitignore` are committed (on the feature branch). All of a feature's worktrees live under
|
|
240
|
+
`.git/gbuild/<feature>/` — never in `git status`: `tree/` is the feature worktree itself, created by
|
|
241
|
+
`plan` and kept until the feature is done, and during a run each file-touching node gets a `<node>/`
|
|
242
|
+
worktree that is removed the moment its node is accepted (merged into the feature branch, in `tree/`)
|
|
243
|
+
or terminally failed (discarded).
|
package/agents/gbuild-auditor.md
CHANGED
|
@@ -1,24 +1,26 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: gbuild-auditor
|
|
3
|
-
description: Strict end-of-feature maintainability auditor for a gbuild feature branch. Audits abstraction quality, file size, spaghetti growth, and missed code-judo simplifications across the
|
|
3
|
+
description: Strict end-of-feature maintainability auditor for a gbuild feature branch. Audits abstraction quality, file size, spaghetti growth, and missed code-judo simplifications across the feature branch's accumulated diff, working in the feature's git worktree. Use during the final review phase of a gbuild feature, after the graph's nodes are all complete.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# gbuild Auditor
|
|
7
7
|
|
|
8
8
|
Unusually strict review of implementation quality, maintainability, and abstraction health. Push for **ambitious** restructurings — "code judo" moves that preserve behavior while making the code dramatically simpler, smaller, and more direct. Delete complexity; don't rearrange it.
|
|
9
9
|
|
|
10
|
-
The caller passes you the resolved feature slug and the feature context it read from the gbuild store: the `destination` and the acceptance bar (each criterion with the nodes covering it). Use
|
|
10
|
+
The caller passes you the resolved feature slug, the **feature worktree** path, and the feature context it read from the gbuild store: the `destination` and the acceptance bar (each criterion with the nodes covering it). Use the context for scoping only — you are auditing the branch's code, not re-grading individual nodes (`gbuild-reviewer` already did that per node, against each node's own contract; your job is the thing no per-node pass can see — what the accumulated diff did to the codebase as a whole). The feature branch is checked out in the feature worktree: every file read, every check, and every git command runs there (`git -C <worktree> …` or with it as your working directory), never in the main tree. Do not open `.gbuild/` or run `cypherlite` — the caller owns the store. Do NOT write any file — output your audit as your final message exclusively.
|
|
11
11
|
|
|
12
12
|
## Run the branch's checks first
|
|
13
13
|
|
|
14
|
-
Before you audit, run the repo's own verification on the branch: the full test suite, plus typecheck and
|
|
15
|
-
lint where the repo defines them.
|
|
14
|
+
Before you audit, run the repo's own verification on the branch, in the feature worktree: the full test suite, plus typecheck and
|
|
15
|
+
lint where the repo defines them. A worktree is a fresh checkout — if the project needs installed
|
|
16
|
+
dependencies to build or test (`node_modules`, `.venv`, …), install or symlink them there first.
|
|
17
|
+
Per-node reviews only checked each node against its own acceptance
|
|
16
18
|
criteria — nobody has yet run the whole suite against the accumulated diff. A failing check is a
|
|
17
19
|
blocking finding: name the exact failures.
|
|
18
20
|
|
|
19
21
|
## Core Prompt
|
|
20
22
|
|
|
21
|
-
> Deep code-quality audit of the
|
|
23
|
+
> Deep code-quality audit of the feature branch. Rethink structure to improve quality without changing behavior. Improve abstractions, modularity, succinctness, legibility. Be ambitious — if restructuring the codebase yields a clearly better implementation, go for it. Measure twice, cut once.
|
|
22
24
|
|
|
23
25
|
## Standards
|
|
24
26
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: gbuild-reviewer
|
|
3
|
-
description: Fast per-node gate in a gbuild run — checks the node's outputs match their contract, its acceptance criteria are fulfilled, and the diff
|
|
3
|
+
description: Fast per-node gate in a gbuild run — checks the node's outputs match their contract, its acceptance criteria are fulfilled, and the diff neither duplicates something the repo already has nor adds a third copy where an abstraction is due. Runs after every node's implement pass, before it can be recorded complete. Never the same agent that implemented the node.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
You are reviewing one gbuild node's output. You did not implement it — do not defer to the implementer's
|
|
@@ -37,10 +37,16 @@ Three checks, in order:
|
|
|
37
37
|
overall" — go bullet by bullet, pass or fail each one individually, cite why. If a bullet names
|
|
38
38
|
something runnable (a command, a specific test file), run just that rather than taking the diff's
|
|
39
39
|
word for it — but never the whole suite; that's the end-of-feature audit's job.
|
|
40
|
-
3. **Does the diff duplicate
|
|
41
|
-
type, or pattern that already does what this node just built. If the
|
|
42
|
-
exists, that's a fail — cite the code it should have reused. A
|
|
43
|
-
the canonical code.
|
|
40
|
+
3. **Does the diff duplicate functionality, or add a copy where an abstraction is due?** Search for an
|
|
41
|
+
existing helper, utility, type, or pattern that already does what this node just built. If the
|
|
42
|
+
node's core deliverable already exists, that's a fail — cite the code it should have reused. A
|
|
43
|
+
partial overlap is an Issue citing the canonical code. Then count copies: if this diff adds a
|
|
44
|
+
**third** copy of the same logic (the other two anywhere in the repo, elsewhere in the diff, or one
|
|
45
|
+
of each), that's a missed abstraction and a fail — name all three sites and the shared helper that
|
|
46
|
+
should own the logic. Two copies can stand; the third is where extracting beats copying. The
|
|
47
|
+
counterweight is just as binding: YAGNI. Judge only copies that actually exist in the code today —
|
|
48
|
+
never fault the diff for lacking an abstraction that only hypothetical future callers would use,
|
|
49
|
+
and never treat a single concrete implementation left un-abstracted as a finding.
|
|
44
50
|
|
|
45
51
|
## GIT DIFF
|
|
46
52
|
|
|
@@ -68,13 +74,14 @@ Lead with the acceptance checklist, one line per bullet:
|
|
|
68
74
|
```
|
|
69
75
|
|
|
70
76
|
For a duplication fail, the `[fail]` line names what was duplicated: `[fail] duplicates <existing code> —
|
|
71
|
-
<what should have been reused
|
|
77
|
+
<what should have been reused>`, or for a missed abstraction: `[fail] third copy of <logic> (<site 1>,
|
|
78
|
+
<site 2>, this diff) — extract a shared <helper>`.
|
|
72
79
|
|
|
73
80
|
Then, only if there are findings beyond acceptance: `Issue` or `Suggestion`, each with a `Priority`
|
|
74
81
|
(`critical | high | medium | low`).
|
|
75
82
|
|
|
76
83
|
Finish with one verdict line: `VERDICT: pass` only if every output field has a value matching its shape,
|
|
77
|
-
every acceptance bullet passed, and the diff
|
|
78
|
-
otherwise `VERDICT: fail`. A single failed acceptance bullet or an output shape mismatch is enough to
|
|
84
|
+
every acceptance bullet passed, and the diff neither substantially duplicates existing repo code nor adds
|
|
85
|
+
a third copy where an abstraction is due — otherwise `VERDICT: fail`. A single failed acceptance bullet or an output shape mismatch is enough to
|
|
79
86
|
fail the whole node, even if everything else is clean. The caller records each `[fail]` line's criterion
|
|
80
87
|
as the review's failed criteria.
|
package/index.ts
CHANGED
|
@@ -43,7 +43,7 @@ instructions above:
|
|
|
43
43
|
- \`$ARGUMENTS\` refers to the arguments this skill was invoked with in the
|
|
44
44
|
conversation.
|
|
45
45
|
- run's "Workflow tool" backend is Claude-specific; always use the fallback
|
|
46
|
-
backend described in step
|
|
46
|
+
backend described in step 2.
|
|
47
47
|
`
|
|
48
48
|
|
|
49
49
|
const frontmatter = (raw: string): { description: string; body: string } => {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "opencode-gbuild",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.7.0",
|
|
5
5
|
"description": "OpenCode plugin for gbuild — graph-native task planning and execution with concurrent fan-out, per-node review, and durable checkpoints.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"license": "MIT",
|
package/reference/cypher.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Talking to the gbuild store
|
|
2
2
|
|
|
3
|
-
Every gbuild skill reads and writes the feature store (`.gbuild/<feature>/db
|
|
3
|
+
Every gbuild skill reads and writes the feature store (`.gbuild/<feature>/db/` inside the feature's git
|
|
4
|
+
worktree, modelled in
|
|
4
5
|
`reference/graph-format.md`) with the `cypherlite` CLI and nothing else. This file is the full operating
|
|
5
6
|
manual; the skills that only run plugin scripts carry the short version of these rules inline.
|
|
6
7
|
|
|
@@ -32,7 +33,9 @@ or writer — fails with `storage locked` (exit 1). So:
|
|
|
32
33
|
## Invocation
|
|
33
34
|
|
|
34
35
|
Always pass `--mode jsonl`: one compact JSON object per row, one row per line, and no output at all when
|
|
35
|
-
there are no rows. `DB` below is `.gbuild/<feature>/db
|
|
36
|
+
there are no rows. `DB` below is the feature store: `.gbuild/<feature>/db` inside the feature worktree
|
|
37
|
+
(`<git-common-dir>/gbuild/<feature>/tree/`), or in the main tree for a feature charted before the
|
|
38
|
+
worktree layout.
|
|
36
39
|
|
|
37
40
|
```
|
|
38
41
|
# a plugin script
|
|
@@ -75,12 +78,13 @@ CYPHER
|
|
|
75
78
|
|
|
76
79
|
## Creating a store
|
|
77
80
|
|
|
78
|
-
Only `plan` does this, once per feature
|
|
81
|
+
Only `plan` does this, once per feature, with `DB` = `.gbuild/<feature>/db` inside the feature worktree
|
|
82
|
+
it just created:
|
|
79
83
|
|
|
80
84
|
```
|
|
81
|
-
mkdir -p
|
|
82
|
-
cypherlite
|
|
83
|
-
printf '*\n!.gitignore\n!graph.json\n' >
|
|
85
|
+
mkdir -p DB
|
|
86
|
+
cypherlite DB --snapshot-format json < ${CLAUDE_PLUGIN_ROOT}/cypher/schema.cypher
|
|
87
|
+
printf '*\n!.gitignore\n!graph.json\n' > DB/.gitignore
|
|
84
88
|
```
|
|
85
89
|
|
|
86
90
|
`--snapshot-format json` belongs on this first call only (it applies to an empty directory). It installs
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
This file is normative. Where a skill disagrees with this doc, this doc wins.
|
|
4
4
|
|
|
5
|
-
One CypherLite store per feature: `.gbuild/<feature>/db
|
|
5
|
+
One CypherLite store per feature: `.gbuild/<feature>/db/` inside the feature's git worktree
|
|
6
|
+
(`<git-common-dir>/gbuild/<feature>/tree/` — `plan` creates the worktree; a feature charted before the
|
|
7
|
+
worktree layout keeps its store in the main tree). `plan` creates and charts it, `run` records
|
|
6
8
|
progress in it, and every skill reads it — **all through Cypher**. No skill reads or writes `graph.json`
|
|
7
9
|
directly; it is CypherLite's snapshot of the store. How to talk to the store (the single-writer rule,
|
|
8
10
|
invocation, quoting, the script catalog) is in `reference/cypher.md`.
|
|
@@ -39,7 +41,7 @@ data **and** constraints.
|
|
|
39
41
|
|
|
40
42
|
| property | type | meaning |
|
|
41
43
|
| -------------- | -------------- | ---------------------------------------------------- |
|
|
42
|
-
| `feature` | string | the slug — matches the `.gbuild/<feature>/` dir, immutable |
|
|
44
|
+
| `feature` | string | the slug — matches the `.gbuild/<feature>/` dir in the feature worktree, immutable |
|
|
43
45
|
| `destination` | string | one line: what is true once this is done |
|
|
44
46
|
| `context` | string | why this exists, one or two lines |
|
|
45
47
|
| `out_of_scope` | list of string | bullets, may be empty |
|
|
@@ -60,7 +62,7 @@ universal label is for `MATCH (n:GbuildNode)`; the type label enables `MATCH (n:
|
|
|
60
62
|
|
|
61
63
|
| property | type | meaning |
|
|
62
64
|
| ---------------- | -------------- | -------------------------------------------------------------- |
|
|
63
|
-
| `slug` | string | kebab-case, unique, immutable — the identity every skill keys on |
|
|
65
|
+
| `slug` | string | kebab-case, unique, immutable — the identity every skill keys on; `tree` is reserved (the feature worktree's directory name) |
|
|
64
66
|
| `title` | string | what the user reads; refer to nodes by title in conversation |
|
|
65
67
|
| `type` | string | `research \| decision \| code \| test \| verify \| chore` |
|
|
66
68
|
| `acceptance` | list of string | node-level criteria — mandatory, non-empty, concrete |
|
package/reference/queries.md
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# Ad-hoc queries
|
|
2
2
|
|
|
3
3
|
The plugin scripts (`reference/cypher.md` § Script catalog) cover everything the skills do. These are for
|
|
4
|
-
the questions in between. Run them with `cypherlite
|
|
5
|
-
time
|
|
4
|
+
the questions in between. Run them with `cypherlite DB --mode jsonl "<query>"`, one at a
|
|
5
|
+
time — `DB` is the feature store (`.gbuild/<feature>/db` inside the feature worktree);
|
|
6
|
+
return only the columns you need and keep a `LIMIT` on anything that can grow.
|
|
6
7
|
|
|
7
8
|
```cypher
|
|
8
9
|
-- the whole plan with progress
|
package/skills/plan/SKILL.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Decomposes a feature into a real dependency graph in the gbuild CypherLite store
|
|
2
|
+
description: Decomposes a feature into a real dependency graph in the gbuild CypherLite store — nodes with typed field contracts, mandatory concrete acceptance criteria, and edges that pass the cut test. Creates the feature branch in its own git worktree, never touching the main checkout. Use when starting new gbuild work, before /gbuild:run.
|
|
3
3
|
---
|
|
4
4
|
|
|
5
5
|
Plan the work described in `$ARGUMENTS` as a graph.
|
|
@@ -24,30 +24,45 @@ inform the choices below. `${CLAUDE_PLUGIN_ROOT}/reference/checklist.md` is the
|
|
|
24
24
|
| a description, link, or file path | **Chart** — new feature |
|
|
25
25
|
| an existing feature slug with `--add "<req>"` | **Reopen** |
|
|
26
26
|
|
|
27
|
-
A bare slug with no
|
|
27
|
+
A bare slug with no store is a description, not a slug — chart it. A slug's store lives in its feature
|
|
28
|
+
worktree at `<git-common-dir>/gbuild/<slug>/tree/.gbuild/<slug>/db` (a feature charted before the
|
|
29
|
+
worktree layout keeps its store at `.gbuild/<slug>/db` in the main tree).
|
|
28
30
|
|
|
29
31
|
## Chart
|
|
30
32
|
|
|
31
|
-
### 1. Slug and
|
|
33
|
+
### 1. Slug, branch, and feature worktree
|
|
32
34
|
|
|
33
35
|
Derive the feature slug from `$ARGUMENTS`: kebab-case, ≤4 words, names the outcome not the mechanism
|
|
34
36
|
(`oauth-device-flow`, not `add-some-auth-stuff`). It's the `.gbuild/<slug>/` directory name and the
|
|
35
37
|
`Feature` node's `feature` property — immutable once charted.
|
|
36
38
|
|
|
37
|
-
|
|
39
|
+
gbuild never changes the branch of the user's checkout: the feature branch lives in its own **feature
|
|
40
|
+
worktree**, so several features can be charted and run in parallel without racing each other's `HEAD`,
|
|
41
|
+
and uncommitted work in the main tree is irrelevant — there is no dirty-tree check. Resolve two paths,
|
|
42
|
+
both absolute: `GC` = `git rev-parse --git-common-dir` (resolve it to an absolute path), and `FT` =
|
|
43
|
+
`GC/gbuild/<slug>/tree` — the feature worktree, the one place the feature branch is checked out. Then:
|
|
38
44
|
|
|
39
|
-
-
|
|
40
|
-
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
45
|
+
- `FT` is already a registered worktree (`git worktree list --porcelain`) → reuse it, say so.
|
|
46
|
+
- A branch named `<slug>` or ending `/<slug>` already exists → if it's checked out somewhere (a feature
|
|
47
|
+
charted before the worktree layout usually has it in the main tree), that location is `FT`; otherwise
|
|
48
|
+
attach it: `git worktree add FT <branch>`.
|
|
49
|
+
- Otherwise create branch and worktree in one step, forked from the current HEAD:
|
|
44
50
|
|
|
45
|
-
|
|
51
|
+
```
|
|
52
|
+
git worktree add FT -b <prefix>/<slug> HEAD
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Take `<prefix>` from the repo's convention — project or user instructions first, else the dominant
|
|
56
|
+
pattern in `git branch --list` — and fall back to `gbuild` when there is none.
|
|
57
|
+
|
|
58
|
+
Report the branch and `FT`. Everything below happens in `FT`; `DB` below is
|
|
59
|
+
`FT/.gbuild/<slug>/db`.
|
|
46
60
|
|
|
47
61
|
### 2. Analyse the codebase
|
|
48
62
|
|
|
49
63
|
Read the project manifest(s), directory structure, `README.md`, and — for related in-flight work — the
|
|
50
|
-
`Feature` of every existing store (`feature.cypher` against each
|
|
64
|
+
`Feature` of every existing store (`feature.cypher` against each `GC/gbuild/*/tree/.gbuild/*/db`, plus
|
|
65
|
+
any legacy `.gbuild/*/db` in the main tree, one at a time). Resolve
|
|
51
66
|
file paths or URLs in `$ARGUMENTS`; if a reference fails to load, say so and ask.
|
|
52
67
|
|
|
53
68
|
### 3. Validate and explore
|
|
@@ -140,7 +155,7 @@ Then write the whole graph as **one** Cypher script, piped through a quoted here
|
|
|
140
155
|
the edges), `.commit`, `.checkpoint`.
|
|
141
156
|
|
|
142
157
|
```
|
|
143
|
-
cypherlite
|
|
158
|
+
cypherlite DB <<'CYPHER'
|
|
144
159
|
.begin
|
|
145
160
|
CREATE (f:Feature {feature: '<slug>', destination: '...', context: '...', out_of_scope: ['...']})
|
|
146
161
|
CREATE (a1:Acceptance {id: 'a-1', text: '...'})
|
|
@@ -163,7 +178,7 @@ slug) fails the transaction and writes nothing — fix the script and run it aga
|
|
|
163
178
|
### 9. Validate
|
|
164
179
|
|
|
165
180
|
```
|
|
166
|
-
cypherlite
|
|
181
|
+
cypherlite DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/validate.cypher
|
|
167
182
|
```
|
|
168
183
|
|
|
169
184
|
No output means valid. Every row is a violation (`check`, `detail`): fix it with Cypher — a `.begin` …
|
|
@@ -173,7 +188,7 @@ hand off or commit a graph that fails validation, and never edit `graph.json` di
|
|
|
173
188
|
Then confirm run-readiness:
|
|
174
189
|
|
|
175
190
|
```
|
|
176
|
-
cypherlite
|
|
191
|
+
cypherlite DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/progress.cypher
|
|
177
192
|
```
|
|
178
193
|
|
|
179
194
|
One row per wave: each row's `open` slugs are the decomposition, and the `frontier` counts are what
|
|
@@ -181,18 +196,21 @@ One row per wave: each row's `open` slugs are the decomposition, and the `fronti
|
|
|
181
196
|
|
|
182
197
|
### 10. Commit and stop
|
|
183
198
|
|
|
184
|
-
Commit `.gbuild/<slug>/` unless the repo ignores it (`git check-ignore -q
|
|
185
|
-
anything under it). The store's own `.gitignore` limits that to
|
|
186
|
-
|
|
199
|
+
Commit `.gbuild/<slug>/` on the feature branch unless the repo ignores it (`git -C FT check-ignore -q
|
|
200
|
+
.gbuild/`; if true, don't stage anything under it). The store's own `.gitignore` limits that to
|
|
201
|
+
`db/graph.json` and `db/.gitignore`. Stage and commit from the feature worktree:
|
|
202
|
+
`git -C FT add .gbuild/<slug>` and `git -C FT commit -m "<slug>: chart graph"`.
|
|
187
203
|
|
|
188
|
-
Report the branch, the waves, and the frontier. Close with `next: /gbuild:run <slug>`.
|
|
204
|
+
Report the branch, `FT`, the waves, and the frontier. Close with `next: /gbuild:run <slug>`.
|
|
189
205
|
|
|
190
206
|
## Reopen
|
|
191
207
|
|
|
192
208
|
`--add "<requirement>"`:
|
|
193
209
|
|
|
194
|
-
0.
|
|
195
|
-
|
|
210
|
+
0. Resolve `FT` and `DB` exactly as Chart's step 1 describes (reuse the existing feature worktree;
|
|
211
|
+
attach it if the branch is checked out nowhere). Never chart a reopen onto a different branch than
|
|
212
|
+
the one the graph was charted on, and never into the user's main checkout unless that's where the
|
|
213
|
+
feature branch already lives (a legacy feature).
|
|
196
214
|
1. Read the current graph narrowly: `progress.cypher` for its shape and what's done, and `node.cypher`
|
|
197
215
|
only for the nodes the requirement touches.
|
|
198
216
|
2. Design the delta: a new `Acceptance` node (next `a-` id) linked from the `Feature`, and whatever new
|
|
@@ -202,7 +220,7 @@ Report the branch, the waves, and the frontier. Close with `next: /gbuild:run <s
|
|
|
202
220
|
3. Write it as one script that `MATCH`es what it connects to and `CREATE`s the rest:
|
|
203
221
|
|
|
204
222
|
```
|
|
205
|
-
cypherlite
|
|
223
|
+
cypherlite DB <<'CYPHER'
|
|
206
224
|
.begin
|
|
207
225
|
MATCH (f:Feature), (up:GbuildNode {slug: '<existing-slug>'})-[:OUTPUT]->(up_out:Field {name: '<field>'})
|
|
208
226
|
CREATE (f)-[:HAS_ACCEPTANCE]->(a:Acceptance {id: 'a-3', text: '...'})
|
|
@@ -216,8 +234,9 @@ Report the branch, the waves, and the frontier. Close with `next: /gbuild:run <s
|
|
|
216
234
|
CYPHER
|
|
217
235
|
```
|
|
218
236
|
|
|
219
|
-
4. **Re-run `validate.cypher`** until it prints nothing, then `progress.cypher`. Commit
|
|
220
|
-
(
|
|
237
|
+
4. **Re-run `validate.cypher`** until it prints nothing, then `progress.cypher`. Commit in `FT`
|
|
238
|
+
(`git -C FT commit -m "<slug>: reopen graph — <what was added>"` after staging `.gbuild/<slug>`,
|
|
239
|
+
same ignore rule as Chart's step 10), report the new frontier.
|
|
221
240
|
|
|
222
241
|
If the requirement needs no new nodes (an existing node's contract already covers it), say so and stop
|
|
223
242
|
— don't manufacture graph churn.
|
package/skills/pr/SKILL.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Pushes the
|
|
2
|
+
description: Pushes the gbuild feature branch to the appropriate remote, opens a pull request with a concise description that classifies the change (new feature, fix, optimization, etc.) and notes any user-facing impact, then monitors CI checks in the background and auto-triggers a graph reopen + run if any fail. Works from the feature's own worktree, never touching the main checkout's branch. Use after /gbuild:review reports nothing blocking, to publish the finished feature branch.
|
|
3
3
|
---
|
|
4
4
|
|
|
5
5
|
Publish a finished feature branch: push it to the right remote, open a well-formed pull request, then watch the PR's CI checks and drive a graph reopen automatically when a check goes red — looping until the checks are green or a round cap is hit.
|
|
@@ -12,9 +12,9 @@ This skill MUST run in the **main conversation context**. It MUST NOT be invoked
|
|
|
12
12
|
|
|
13
13
|
`$ARGUMENTS` is free-form text: an optional feature slug and an optional `--max-rounds N` flag.
|
|
14
14
|
|
|
15
|
-
- **slug**: the first token that isn't a flag. If absent, infer it —
|
|
15
|
+
- **slug**: the first token that isn't a flag. If absent, infer it — if exactly one feature worktree exists (`<git-common-dir>/gbuild/*/tree`), that's the slug; otherwise fall back to the most recently modified `graph.json` under `<git-common-dir>/gbuild/*/tree/.gbuild/*/db` (or, for features charted before the worktree layout, `.gbuild/*/db/graph.json` in the main tree). If neither resolves, leave `<slug>` unresolved (the auto-fix step degrades gracefully — see Step 4).
|
|
16
16
|
|
|
17
|
-
When `<slug>` resolved, every graph read below goes through `cypherlite`: run `cypherlite --version` first (missing → stop; gbuild needs it), one command at a time, always `--mode jsonl` (no output = no rows), and on `storage locked` wait and retry up to 3 times. Anything else: `${CLAUDE_PLUGIN_ROOT}/reference/cypher.md`.
|
|
17
|
+
When `<slug>` resolved, every graph read below goes through `cypherlite`: run `cypherlite --version` first (missing → stop; gbuild needs it), one command at a time, always `--mode jsonl` (no output = no rows), and on `storage locked` wait and retry up to 3 times. Anything else: `${CLAUDE_PLUGIN_ROOT}/reference/cypher.md`. `DB` below is `FT/.gbuild/<slug>/db` (see Step 1 for `FT`).
|
|
18
18
|
- **max_rounds**: the value of `--max-rounds N` (also accept `--max-rounds=N`). Default `3` when absent.
|
|
19
19
|
|
|
20
20
|
## Step 1: Preconditions
|
|
@@ -24,10 +24,10 @@ Verify the environment before touching the remote. Stop with a clear, actionable
|
|
|
24
24
|
1. **Git repo.** This skill is git + GitHub specific. If the repo is not git, stop and explain that `/gbuild:pr` only supports git + GitHub (`gh`).
|
|
25
25
|
2. **GitHub CLI.** Confirm `gh` is installed and authenticated (`gh auth status`). If not, stop and tell the user to install/authenticate `gh`.
|
|
26
26
|
3. **Base branch.** Determine the upstream default branch: `gh repo view --json defaultBranchRef -q .defaultBranchRef.name`. Call it `<base>`.
|
|
27
|
-
4. **
|
|
28
|
-
5. **Clean tree.** Check for uncommitted changes (`git status --porcelain`). `/gbuild:run` commits each node's work as it goes, so
|
|
29
|
-
6. **Commits ahead of base.** Confirm the branch has commits the base lacks (`git log <base
|
|
30
|
-
7. **Graph finished.** When `<slug>` resolved, run `cypherlite
|
|
27
|
+
4. **Feature worktree and branch.** Resolve `FT` (the feature worktree) and `<branch>` (the feature branch checked out there) exactly as `/gbuild:run`'s step 0 describes — the registered worktree at `<git-common-dir>/gbuild/<slug>/tree`, a legacy feature whose branch is in the main tree, or attach a branch that is checked out nowhere. When `<slug>` is unresolved, use the main tree's current branch as `<branch>` and its root as `FT`. If `<branch>` equals `<base>`, stop — there is nothing to open a PR for.
|
|
28
|
+
5. **Clean tree.** Check for uncommitted changes in the feature worktree (`git -C FT status --porcelain`). `/gbuild:run` commits each node's work as it goes, so it should be clean. If there are uncommitted changes, warn the user and ask whether to proceed (they may want to commit first).
|
|
29
|
+
6. **Commits ahead of base.** Confirm the branch has commits the base lacks (`git log <base>..<branch> --oneline`). If empty, stop — nothing to push.
|
|
30
|
+
7. **Graph finished.** When `<slug>` resolved, run `cypherlite DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/progress.cypher`. If any row's `open` is non-empty, warn that the graph isn't finished (name the open nodes) and ask whether to open the PR anyway. If any row has `failed` > 0, get their names from `attention.cypher` and name them — a PR built on an escalated node is usually premature.
|
|
31
31
|
|
|
32
32
|
## Step 2: Determine the remote & push
|
|
33
33
|
|
|
@@ -37,7 +37,8 @@ Choose the push remote from the project's actual remotes:
|
|
|
37
37
|
2. **Exactly one remote** → use it.
|
|
38
38
|
3. **Multiple remotes** → look for a push-target hint in `AGENTS.md` or `CLAUDE.md` (e.g. an explicit statement that the project pushes to a fork). If a clear hint exists, use it. Otherwise, use `AskUserQuestion` to let the user pick which remote to push to (e.g. `origin` vs a fork remote).
|
|
39
39
|
|
|
40
|
-
Push the
|
|
40
|
+
Push the feature branch and set upstream: `git push -u <remote> <branch>` (branch names are refs — the
|
|
41
|
+
main tree's checkout is irrelevant).
|
|
41
42
|
|
|
42
43
|
## Step 3: Open the pull request
|
|
43
44
|
|
|
@@ -45,9 +46,9 @@ Build a **short, well-formed** description, then open the PR.
|
|
|
45
46
|
|
|
46
47
|
Gather context from:
|
|
47
48
|
|
|
48
|
-
- Commit subjects: `git log <base
|
|
49
|
-
- File overview: `git diff <base
|
|
50
|
-
- When `<slug>` resolved: `cypherlite
|
|
49
|
+
- Commit subjects: `git log <base>..<branch> --oneline`.
|
|
50
|
+
- File overview: `git diff <base>...<branch> --stat`.
|
|
51
|
+
- When `<slug>` resolved: `cypherlite DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/feature.cypher` — the `destination` and the acceptance bar (with the nodes covering each criterion).
|
|
51
52
|
|
|
52
53
|
Derive a concise, conventional-commit-style title from the feature/branch and the changes (e.g. `feat(auth): add OAuth login`).
|
|
53
54
|
|
|
@@ -72,13 +73,13 @@ This description was auto generated
|
|
|
72
73
|
|
|
73
74
|
The trailing `This description was auto generated` line is **mandatory** — it always ends the body, after every other section, and is never dropped or reworded.
|
|
74
75
|
|
|
75
|
-
Create the PR: `gh pr create --base <base> --title "<title>" --body "<body>"
|
|
76
|
+
Create the PR: `gh pr create --base <base> --title "<title>" --body "<body>"` — run it with `FT` as the working directory, so `gh` resolves the head from the feature branch (it handles fork `owner:branch` head refs automatically). Capture the PR URL and number (`<pr>`).
|
|
76
77
|
|
|
77
78
|
## Step 4: Monitor checks in the background → auto-fix loop
|
|
78
79
|
|
|
79
80
|
Watch the PR's CI checks and react when they fail. Run for at most `max_rounds` rounds:
|
|
80
81
|
|
|
81
|
-
1. **Launch the watch in the background.** Run `gh pr checks <pr> --watch --fail-fast` via the Bash tool with `run_in_background: true`. It exits `0` when all checks pass and non-zero when a check fails; the harness re-invokes this skill when the command exits, so continue from the result.
|
|
82
|
+
1. **Launch the watch in the background.** Run `gh pr checks <pr> --watch --fail-fast` (from `FT`) via the Bash tool with `run_in_background: true`. It exits `0` when all checks pass and non-zero when a check fails; the harness re-invokes this skill when the command exits, so continue from the result.
|
|
82
83
|
2. **Checks green (exit 0):** report success and go to Step 5.
|
|
83
84
|
3. **Checks red (non-zero exit):**
|
|
84
85
|
- Collect the failure detail: `gh pr checks <pr>` for the failed-check list, and `gh run view <run-id> --log-failed` for the failing logs.
|
|
@@ -88,7 +89,7 @@ Watch the PR's CI checks and react when they fail. Run for at most `max_rounds`
|
|
|
88
89
|
2. Run it unattended. `plan`'s Reopen asks nothing, but if executing it would prompt the user (an ambiguous decomposition), resolve it yourself from the failing logs and note the choice in the final report — `/gbuild:pr` runs without a human present.
|
|
89
90
|
3. If Reopen concludes the requirement needs no new nodes, stop the loop and go to Step 5 with an `unresolved` status — the failure isn't something the graph can act on, so surface the logs to the user.
|
|
90
91
|
4. Read `${CLAUDE_PLUGIN_ROOT}/skills/run/SKILL.md` and execute it inline against `<slug>` to run the newly-unblocked frontier. Suppress its trailing `next: /gbuild:status…` line — this skill owns the transition.
|
|
91
|
-
- After the run completes, push the new commits (`git push`) and **re-launch the watch** (next round).
|
|
92
|
+
- After the run completes, push the new commits (`git -C FT push`) and **re-launch the watch** (next round).
|
|
92
93
|
|
|
93
94
|
4. **Round cap reached while still red:** stop, print the still-failing checks and their logs, and tell the user to inspect manually. Go to Step 5 with an `unresolved` status.
|
|
94
95
|
|
|
@@ -100,3 +101,6 @@ Report the outcome:
|
|
|
100
101
|
PR: <url> (checks: green | fixed after <rounds> round(s) | unresolved after <max_rounds> round(s))
|
|
101
102
|
next: /gbuild:status <slug>
|
|
102
103
|
```
|
|
104
|
+
|
|
105
|
+
The feature worktree `FT` keeps the branch checked out until removed — once the PR is merged and the
|
|
106
|
+
graph is no longer needed, `git worktree remove FT` (and `git branch -d <branch>`) cleans up.
|
package/skills/review/SKILL.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Performs a strict end-of-feature maintainability audit of
|
|
2
|
+
description: Performs a strict end-of-feature maintainability audit of a gbuild feature branch — abstraction quality, file size, spaghetti growth, cross-node duplication, missed code-judo simplifications. Runs the audit in the gbuild-auditor sub-agent, in the feature's worktree, and relays its result to chat. Use after /gbuild:run finishes a graph, before /gbuild:pr.
|
|
3
3
|
---
|
|
4
4
|
|
|
5
5
|
Run the strict end-of-feature maintainability audit in a dedicated sub-agent, then relay its result.
|
|
@@ -10,10 +10,14 @@ missed abstractions that only exist *between* nodes, which no per-node review ca
|
|
|
10
10
|
|
|
11
11
|
## Arguments
|
|
12
12
|
|
|
13
|
-
`$ARGUMENTS` is optional. If present, treat it as the feature slug. If absent, infer it —
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
`$ARGUMENTS` is optional. If present, treat it as the feature slug. If absent, infer it — if exactly one
|
|
14
|
+
feature worktree exists (`<git-common-dir>/gbuild/*/tree`), that's the slug; otherwise fall back to the
|
|
15
|
+
most recently modified `graph.json` under `<git-common-dir>/gbuild/*/tree/.gbuild/*/db` (or, for
|
|
16
|
+
features charted before the worktree layout, `.gbuild/*/db/graph.json` in the main tree). Do NOT write
|
|
17
|
+
any file — this skill outputs to chat exclusively.
|
|
18
|
+
|
|
19
|
+
Resolve `FT`, the feature worktree, exactly as `/gbuild:run`'s step 0 describes (reuse the registered
|
|
20
|
+
worktree, attach if the feature branch is checked out nowhere). `DB` below is `FT/.gbuild/<slug>/db`.
|
|
17
21
|
|
|
18
22
|
Store rules: run `cypherlite --version` first (missing → stop; gbuild needs it). One `cypherlite`
|
|
19
23
|
command at a time, always `--mode jsonl` (no output = no rows); on `storage locked` wait and retry up to
|
|
@@ -22,7 +26,7 @@ command at a time, always `--mode jsonl` (no output = no rows); on `storage lock
|
|
|
22
26
|
Check the graph is finished — one row per wave, cheap:
|
|
23
27
|
|
|
24
28
|
```
|
|
25
|
-
cypherlite
|
|
29
|
+
cypherlite DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/progress.cypher
|
|
26
30
|
```
|
|
27
31
|
|
|
28
32
|
If any row's `open` is non-empty, say the graph isn't finished (name the open nodes) and ask whether to
|
|
@@ -34,7 +38,7 @@ address.
|
|
|
34
38
|
Fetch the feature context:
|
|
35
39
|
|
|
36
40
|
```
|
|
37
|
-
cypherlite
|
|
41
|
+
cypherlite DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/feature.cypher
|
|
38
42
|
```
|
|
39
43
|
|
|
40
44
|
Launch the `gbuild-auditor` subagent (agents/gbuild-auditor.md — this plugin's own copy, gbuild does not
|
|
@@ -43,7 +47,8 @@ depend on hone-ai being installed). Pass it:
|
|
|
43
47
|
- The resolved slug and the `feature.cypher` result verbatim (destination and the acceptance bar with
|
|
44
48
|
the nodes covering each criterion) — the auditor never opens the store itself, and reads the code from
|
|
45
49
|
the branch diff.
|
|
46
|
-
-
|
|
50
|
+
- The feature worktree path `FT` and the feature branch name — it audits the branch's code from `FT`:
|
|
51
|
+
every read, every check, and every git command runs there, never in the main tree.
|
|
47
52
|
|
|
48
53
|
The sub-agent runs the full audit in its own fresh context and returns the audit as its final message.
|
|
49
54
|
That message is a tool result — it is NOT shown to the user. So once it returns:
|
package/skills/run/SKILL.md
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
description: Executes a gbuild graph — dispatches every ready-and-independent node in the current wave concurrently, each file-touching node in its own git worktree, reviews each node's output with gbuild-reviewer before merging its branch and recording it complete, and resumes only the remaining frontier on re-invocation. Use after /gbuild:plan has charted the graph.
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
Run the graph
|
|
5
|
+
Run the graph for the feature `$ARGUMENTS` (the slug; step 0 resolves `DB`, the store — it lives in
|
|
6
|
+
the feature's own worktree, so this skill never changes the branch of the user's checkout).
|
|
6
7
|
|
|
7
8
|
**CRITICAL: this skill must run in the main context, not inside a forked agent.** It dispatches its own
|
|
8
9
|
subagents per node; a subagent cannot itself fan out further subagents reliably. It is also the store's
|
|
@@ -20,7 +21,25 @@ back in their final message, and this skill records it.
|
|
|
20
21
|
Exit code 1 = failure; read stderr. Anything beyond the scripts below: `${CLAUDE_PLUGIN_ROOT}/reference/cypher.md`.
|
|
21
22
|
- Never re-read what you already hold. The claimed wave's definitions stay valid for its retries.
|
|
22
23
|
|
|
23
|
-
## Step 0:
|
|
24
|
+
## Step 0: Establish VCS facts, then check and recover
|
|
25
|
+
|
|
26
|
+
Default to `git`. Resolve these facts first, absolute paths, and reuse them throughout:
|
|
27
|
+
|
|
28
|
+
- `GC` = `git rev-parse --git-common-dir`, resolved to an absolute path; `WT` = `GC/gbuild/$ARGUMENTS`
|
|
29
|
+
(the worktree root — inside `.git/`, so worktrees never appear in `git status` or get committed).
|
|
30
|
+
- `FT` = the feature worktree and `BRANCH` = the feature branch — the one place `BRANCH` is checked
|
|
31
|
+
out, and where every merge and store commit below lands:
|
|
32
|
+
1. `WT/tree` is a registered worktree (`git worktree list --porcelain`) → `FT` = it, `BRANCH` =
|
|
33
|
+
`git -C FT branch --show-current`.
|
|
34
|
+
2. Else a worktree whose branch is `$ARGUMENTS` or ends `/$ARGUMENTS` → `FT` = that worktree's path
|
|
35
|
+
(a feature charted before the worktree layout usually has its branch in the main tree).
|
|
36
|
+
3. Else such a branch exists but is checked out nowhere → attach it: `git worktree add WT/tree
|
|
37
|
+
<branch>`, `FT` = `WT/tree`.
|
|
38
|
+
4. Else → stop: there is no feature branch for `$ARGUMENTS` — chart it with `/gbuild:plan` first.
|
|
39
|
+
- `DB` = `FT/.gbuild/$ARGUMENTS/db`. `git -C FT check-ignore -q .gbuild/` tells you whether to commit
|
|
40
|
+
the store at all.
|
|
41
|
+
|
|
42
|
+
Then check and recover:
|
|
24
43
|
|
|
25
44
|
```
|
|
26
45
|
cypherlite DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/validate.cypher
|
|
@@ -31,7 +50,7 @@ cypherlite DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/attention.cypher
|
|
|
31
50
|
correctly.
|
|
32
51
|
- `attention` rows with reason `in_progress` are left over from an interrupted run (this skill is the
|
|
33
52
|
only writer and records every node before finishing). Check each one's worktree branch for commits
|
|
34
|
-
its agent already made (`git log
|
|
53
|
+
its agent already made (`git log BRANCH..gbuild/<feature>/<slug>` — empty
|
|
35
54
|
means it never got that far) and leave the worktree in place: the re-dispatch reuses it. Then reset
|
|
36
55
|
them all in one call so they re-dispatch, and mention it in the report:
|
|
37
56
|
|
|
@@ -40,19 +59,13 @@ cypherlite DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/attention.cypher
|
|
|
40
59
|
< ${CLAUDE_PLUGIN_ROOT}/cypher/set-status.cypher
|
|
41
60
|
```
|
|
42
61
|
|
|
43
|
-
- Sweep the worktree root
|
|
44
|
-
|
|
62
|
+
- Sweep the worktree root `WT` for leaks from an interruption that struck mid-cleanup: any worktree
|
|
63
|
+
under `WT` — **except `FT` itself (`WT/tree`)** — whose slug is *not* among the slugs just reset does
|
|
64
|
+
not belong to live work — remove it
|
|
45
65
|
(`git worktree remove --force`) and delete its branch (`git branch -D`). An unmerged branch is
|
|
46
66
|
unaccepted work, which must never land — that is what the isolation is for.
|
|
47
67
|
|
|
48
|
-
## Step 1:
|
|
49
|
-
|
|
50
|
-
Default to `git`. `git check-ignore -q .gbuild/` tells you whether to commit the store at all. Record
|
|
51
|
-
two facts for the wave mechanics below: `BRANCH` = `git branch --show-current` (the feature branch —
|
|
52
|
-
every accepted node merges back into it), and `WT` = `$(git rev-parse --git-common-dir)/gbuild/$ARGUMENTS`
|
|
53
|
-
(the worktree root — inside `.git/`, so worktrees never appear in `git status` or get committed).
|
|
54
|
-
|
|
55
|
-
## Step 2: Pick a backend
|
|
68
|
+
## Step 1: Pick a backend
|
|
56
69
|
|
|
57
70
|
**Workflow tool**, if this session has opted into multi-agent orchestration (ultracode, or the user
|
|
58
71
|
asked for a workflow explicitly) — translate each claimed wave into a `pipeline()`/`parallel()` script:
|
|
@@ -62,14 +75,14 @@ file-touching (`code`/`test`/`chore`) node gets `isolation: 'worktree'`.
|
|
|
62
75
|
Controlled-cycle clusters become a bounded `while` loop per `${CLAUDE_PLUGIN_ROOT}/reference/shapes.md`'s
|
|
63
76
|
round cap. Route `model_tier: strong` nodes via `opts.model` where the harness supports an override. The
|
|
64
77
|
script never touches the store: collect the results, land each accepted node's branch from the main
|
|
65
|
-
context (step
|
|
78
|
+
context (step 2.4), then record (step 2.5).
|
|
66
79
|
|
|
67
|
-
**Fallback** (default — no opt-in required, and always what step
|
|
80
|
+
**Fallback** (default — no opt-in required, and always what step 2 below assumes): fire one `Agent`
|
|
68
81
|
tool call per claimed node, **all in a single message** — this is what makes the fan-out real rather
|
|
69
82
|
than claimed. Do not dispatch them one at a time across separate messages; that's exactly the serial
|
|
70
83
|
behavior this plugin replaces.
|
|
71
84
|
|
|
72
|
-
## Step
|
|
85
|
+
## Step 2: One wave
|
|
73
86
|
|
|
74
87
|
1. **CLAIM.**
|
|
75
88
|
|
|
@@ -80,7 +93,7 @@ behavior this plugin replaces.
|
|
|
80
93
|
It moves the whole frontier to `in_progress` and prints one row per claimed node with everything its
|
|
81
94
|
agent needs: `slug`, `title`, `type`, `acceptance`, `failure_policy`, `model_tier`, `verify`,
|
|
82
95
|
`inputs` (an input with a `value` came from an upstream node; one without is external — its `shape`
|
|
83
|
-
says where to find it), and `outputs`. **No rows** → nothing is ready: go to step
|
|
96
|
+
says where to find it), and `outputs`. **No rows** → nothing is ready: go to step 4.
|
|
84
97
|
|
|
85
98
|
2. **IMPLEMENT.** First, give every claimed `code`/`test`/`chore` node its own worktree — one shell
|
|
86
99
|
loop over the wave's slugs, idempotent so an interrupted or re-dispatched node keeps its earlier
|
|
@@ -93,7 +106,8 @@ behavior this plugin replaces.
|
|
|
93
106
|
|| git worktree add WT/<slug> gbuild/<feature>/<slug>
|
|
94
107
|
```
|
|
95
108
|
|
|
96
|
-
(skip if the worktree already exists; else fork a fresh branch off `BRANCH
|
|
109
|
+
(skip if the worktree already exists; else fork a fresh branch off `BRANCH` — just a ref here, the
|
|
110
|
+
cwd doesn't matter; if the branch already
|
|
97
111
|
exists from an earlier attempt, attach to it instead — nothing is redone). Then, in one message,
|
|
98
112
|
spawn one `Agent` per claimed node with its row. Tell it to:
|
|
99
113
|
- actually do the work — for `code`/`test`/`chore` nodes make the change **in its worktree**
|
|
@@ -118,19 +132,20 @@ behavior this plugin replaces.
|
|
|
118
132
|
point). Never let the implementing agent review its own work.
|
|
119
133
|
|
|
120
134
|
4. **LAND.** For each `pass` verdict on a `code`/`test`/`chore` node, merge its branch into the
|
|
121
|
-
feature branch
|
|
135
|
+
feature branch — in the feature worktree `FT`, never the user's checkout — and clean up:
|
|
122
136
|
|
|
123
137
|
```
|
|
124
|
-
git merge --no-ff gbuild/<feature>/<slug> \
|
|
138
|
+
git -C FT merge --no-ff gbuild/<feature>/<slug> \
|
|
125
139
|
&& git worktree remove --force WT/<slug> \
|
|
126
140
|
&& git branch -d gbuild/<feature>/<slug>
|
|
127
141
|
```
|
|
128
142
|
|
|
129
|
-
A merge conflict means two supposedly independent nodes touched the same lines: `git merge
|
|
130
|
-
|
|
143
|
+
A merge conflict means two supposedly independent nodes touched the same lines: `git -C FT merge
|
|
144
|
+
--abort`
|
|
145
|
+
and treat the node as review-failed, the conflict as its failed criterion — step 5's policy decides
|
|
131
146
|
(a retry/repair re-dispatch tells the agent to rebase its branch onto `BRANCH` and resolve it).
|
|
132
147
|
Worktrees and branches are deleted only here, after acceptance — a failed node's stays for its next
|
|
133
|
-
attempt (step
|
|
148
|
+
attempt (step 5).
|
|
134
149
|
|
|
135
150
|
5. **RECORD** the whole wave in one call — one result per node, `verdict` from the reviewer's
|
|
136
151
|
`VERDICT:` line, `failed_criteria` from its `[fail]` lines:
|
|
@@ -165,16 +180,17 @@ behavior this plugin replaces.
|
|
|
165
180
|
`set-status.cypher` before the next claim.
|
|
166
181
|
|
|
167
182
|
Nodes in the same wave never read each other's outputs, and every file-touching node works in its own
|
|
168
|
-
worktree, so true concurrent dispatch is safe by construction — the store calls and the merges
|
|
169
|
-
|
|
183
|
+
worktree, so true concurrent dispatch is safe by construction — the store calls and the merges in `FT`
|
|
184
|
+
are the only serialized points, and since `FT` belongs to this feature alone, other features (or the
|
|
185
|
+
user) changing branches in their own checkouts cannot race them.
|
|
170
186
|
|
|
171
|
-
## Step
|
|
187
|
+
## Step 3: Next wave
|
|
172
188
|
|
|
173
|
-
If `.gbuild/` isn't ignored, commit the store: `git
|
|
174
|
-
`git commit -m "<feature>: record wave <n>"`. Then claim again (step
|
|
175
|
-
returns no rows.
|
|
189
|
+
If `.gbuild/` isn't ignored, commit the store in the feature worktree: `git -C FT add
|
|
190
|
+
.gbuild/<feature>/db` and `git -C FT commit -m "<feature>: record wave <n>"`. Then claim again (step 2).
|
|
191
|
+
Keep going until a claim returns no rows.
|
|
176
192
|
|
|
177
|
-
## Step
|
|
193
|
+
## Step 4: Report and stop
|
|
178
194
|
|
|
179
195
|
```
|
|
180
196
|
cypherlite DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/progress.cypher
|
|
@@ -194,7 +210,7 @@ Report: which nodes ran this invocation, which passed review outright vs. needed
|
|
|
194
210
|
|
|
195
211
|
## Resuming
|
|
196
212
|
|
|
197
|
-
Re-invoking `/gbuild:run <feature>` after an interruption re-runs step 0 fresh:
|
|
198
|
-
wave left `in_progress` are reset (their worktrees and any
|
|
199
|
-
re-dispatch reuses them), and the next claim picks up exactly
|
|
200
|
-
be told what already finished — the store is the memory.
|
|
213
|
+
Re-invoking `/gbuild:run <feature>` after an interruption re-runs step 0 fresh: the feature worktree is
|
|
214
|
+
resolved or re-attached, nodes an interrupted wave left `in_progress` are reset (their worktrees and any
|
|
215
|
+
commits on their branches survive — the re-dispatch reuses them), and the next claim picks up exactly
|
|
216
|
+
the remaining frontier. Nothing needs to be told what already finished — the store is the memory.
|
package/skills/status/SKILL.md
CHANGED
|
@@ -2,7 +2,11 @@
|
|
|
2
2
|
description: Reports a gbuild feature's graph — frontier, blocked, in-flight, completed, each node's review verdict, and the cluster shapes with evidence of what actually ran concurrently. Use to check progress or diagnose a stuck run.
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
Report status for `$ARGUMENTS`. This skill only reads the store
|
|
5
|
+
Report status for `$ARGUMENTS`. This skill only reads the store. `DB` below is the feature's store:
|
|
6
|
+
`FT/.gbuild/<feature>/db`, where `FT` is the feature worktree at `<git-common-dir>/gbuild/<feature>/tree`
|
|
7
|
+
(a feature charted before the worktree layout keeps its store at `.gbuild/<feature>/db` in the main
|
|
8
|
+
tree). Status never creates or attaches worktrees — if neither store exists, say the feature's worktree
|
|
9
|
+
is gone and that `git worktree add <git-common-dir>/gbuild/<feature>/tree <branch>` reattaches it.
|
|
6
10
|
|
|
7
11
|
## Store rules
|
|
8
12
|
|
|
@@ -17,7 +21,7 @@ Report status for `$ARGUMENTS`. This skill only reads the store; `DB` below is `
|
|
|
17
21
|
|
|
18
22
|
| arguments | mode |
|
|
19
23
|
| ------------------ | -------------------------------------- |
|
|
20
|
-
| empty | every feature
|
|
24
|
+
| empty | every feature store |
|
|
21
25
|
| a feature slug | that feature only |
|
|
22
26
|
|
|
23
27
|
## Single feature
|
|
@@ -76,10 +80,11 @@ don't let silence be ambiguous between "checked, clear" and "not checked."
|
|
|
76
80
|
|
|
77
81
|
## All-features mode
|
|
78
82
|
|
|
79
|
-
Don't read every node of every feature. For each
|
|
83
|
+
Don't read every node of every feature. For each store found — `<git-common-dir>/gbuild/*/tree/.gbuild/*/db`,
|
|
84
|
+
plus any legacy `.gbuild/*/db` in the main tree — one store at a time:
|
|
80
85
|
|
|
81
86
|
```
|
|
82
|
-
cypherlite
|
|
87
|
+
cypherlite DB --mode jsonl < ${CLAUDE_PLUGIN_ROOT}/cypher/progress.cypher
|
|
83
88
|
```
|
|
84
89
|
|
|
85
90
|
Print one line per feature: slug, node counts by state summed over its waves, and whether it's done
|