@flumecode/runner 0.10.0 → 0.12.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/dist/cli.js +1082 -870
- package/package.json +1 -1
- package/skills-plugin/skills/implement-plan/SKILL.md +10 -8
- package/skills-plugin/skills/lint-plugin-generator/SKILL.md +96 -0
- package/skills-plugin/skills/request-to-plan/SKILL.md +13 -5
- package/skills-plugin/skills/resolve-merge-conflict/SKILL.md +32 -4
package/package.json
CHANGED
|
@@ -96,8 +96,9 @@ the next step.
|
|
|
96
96
|
useful). For **each** AC it must return: the criterion text verbatim, a verdict
|
|
97
97
|
(**met / not met / unclear**), a one-or-two-sentence rationale, and — this is the
|
|
98
98
|
evidence the report needs — the **exact diff hunk(s)** that prove it, each tagged
|
|
99
|
-
with its file path (the
|
|
100
|
-
`git --no-pager diff
|
|
99
|
+
with its file path (the hunks that prove it, copied verbatim from
|
|
100
|
+
`git --no-pager diff`, such that the union of every AC's evidence covers the
|
|
101
|
+
entire diff — each changed hunk cited under at least one criterion). A _met_ AC should cite at least one
|
|
101
102
|
hunk; _not met_ / _unclear_ may cite none. **Ground every verdict in the actual
|
|
102
103
|
diff:** a criterion may be marked _met_ only if `git --no-pager diff` really
|
|
103
104
|
contains the change that satisfies it, and each cited hunk must be copied verbatim
|
|
@@ -105,7 +106,7 @@ the next step.
|
|
|
105
106
|
implement subagent claimed. If `git --no-pager diff` is empty, the implementation
|
|
106
107
|
produced no changes: no criterion may be _met_, and the review must say so. Tell it
|
|
107
108
|
to return this as a clean, structured list so you can hand it straight to the
|
|
108
|
-
report step.
|
|
109
|
+
report step. In addition to per-AC verdicts, cross-check that every hunk in `git --no-pager diff` is cited by at least one AC's evidence; report any uncovered hunk as a coverage gap (signalling a missing AC or an out-of-scope change).
|
|
109
110
|
|
|
110
111
|
5. **Code-quality review** — Task, `model: "opus"`, read-only. Give the subagent
|
|
111
112
|
the coding guidelines (verbatim) and tell it to review the changes for
|
|
@@ -131,7 +132,7 @@ the next step.
|
|
|
131
132
|
copied verbatim from that live diff — it must drop or correct any hunk carried
|
|
132
133
|
over from step 4 that no longer appears in the actual diff, and the **Files
|
|
133
134
|
changed** list must come from `git --no-pager diff --stat`, not from what an
|
|
134
|
-
earlier subagent claimed. **If `git --no-pager diff` is empty, the
|
|
135
|
+
earlier subagent claimed. Tell it to enumerate all hunks from `git --no-pager diff` and ensure each is attached to ≥1 AC's `evidence`; any hunk mapping to no plan AC goes under `## Caveats / follow-ups` as an explicit unattributed change. **If `git --no-pager diff` is empty, the
|
|
135
136
|
implementation changed nothing:** the report must say so plainly — an honest
|
|
136
137
|
`summary`, no AC marked `met` with evidence — and must never describe edits
|
|
137
138
|
that aren't in the diff. Tell it to submit the user-facing report by calling
|
|
@@ -149,13 +150,13 @@ The report subagent calls `submit_report` with these fields:
|
|
|
149
150
|
|
|
150
151
|
- **`summary`** — one or two sentences on what was implemented.
|
|
151
152
|
- **`prose`** — markdown for the remaining sections, using `##` headings:
|
|
152
|
-
**
|
|
153
|
-
it), **Code quality** (the quality-review outcome and anything left as
|
|
153
|
+
**Code quality** (the quality-review outcome and anything left as
|
|
154
154
|
nice-to-have), **Files changed** (the list from the diff), **Build / tests** (lists
|
|
155
155
|
each verification command and its final pass/fail result, or explains that no
|
|
156
156
|
build/test setup was found), and **Caveats / follow-ups** (anything deferred,
|
|
157
|
-
unmet, or worth a human's eyes
|
|
158
|
-
|
|
157
|
+
unmet, or worth a human's eyes — including any diff hunks that map to no plan AC,
|
|
158
|
+
listed explicitly as unattributed changes). Do **not** put the acceptance-criteria
|
|
159
|
+
section in `prose`, and do **not** include a PR link — the runner adds it.
|
|
159
160
|
- **`acceptanceCriteria`** — one entry per AC from the plan, in plan order, each:
|
|
160
161
|
- `criterion` — the AC text verbatim.
|
|
161
162
|
- `status` — `"met"` / `"not_met"` / `"unclear"`, mirroring the AC review.
|
|
@@ -177,3 +178,4 @@ The report subagent calls `submit_report` with these fields:
|
|
|
177
178
|
once — not as prose for you to echo. Each acceptance criterion carries the diff
|
|
178
179
|
hunk(s) that prove its verdict, copied verbatim from the live `git --no-pager diff`
|
|
179
180
|
— never fabricated. An empty diff means an honest "nothing changed" report.
|
|
181
|
+
- The report exists so the human reviewer can verify each acceptance criterion is satisfied — the ACs and their diff evidence are the primary review surface.
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: lint-plugin-generator
|
|
3
|
+
description: >-
|
|
4
|
+
Generate a concrete plan to install the FlumeCode Lint plugin for THIS repo —
|
|
5
|
+
a .flumecode/plugins/lint/ manifest wired to the pre-commit socket that runs
|
|
6
|
+
the repo's lint/format checks and reports a heartbeat.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# lint-plugin-generator
|
|
10
|
+
|
|
11
|
+
You generate a concrete, repo-specific plan to install the FlumeCode Lint
|
|
12
|
+
plugin. You work **read-only**: inspect the repo and produce a plan via
|
|
13
|
+
`submit_plan`; never edit files.
|
|
14
|
+
|
|
15
|
+
## Orient yourself first
|
|
16
|
+
|
|
17
|
+
Before producing the plan, inspect:
|
|
18
|
+
|
|
19
|
+
1. `.flumecode/wiki/README.md` and `components/skills-plugin.md` (if present) for context.
|
|
20
|
+
2. `package.json` `scripts` — look for `lint`, `format`, `format:check`, `typecheck`, `test`.
|
|
21
|
+
3. `.lintstagedrc.json` / `.lintstagedrc.js` — staged-file formatters.
|
|
22
|
+
4. `.husky/pre-commit` — the exact commands the pre-commit hook already runs.
|
|
23
|
+
5. ESLint config (`eslint.config.*`, `.eslintrc.*`) and Prettier config (`.prettierrc.*`) to confirm tools are present.
|
|
24
|
+
|
|
25
|
+
From this, determine the **exact shell commands** the run script should execute
|
|
26
|
+
(e.g. `pnpm exec lint-staged && pnpm lint && pnpm typecheck`). Do not
|
|
27
|
+
hard-code — derive from the repo.
|
|
28
|
+
|
|
29
|
+
## Produce the plan
|
|
30
|
+
|
|
31
|
+
Call `submit_plan` **once**, passing a `plans` array with one entry whose steps
|
|
32
|
+
instruct the implementer to create:
|
|
33
|
+
|
|
34
|
+
### Artifact 1 — `.flumecode/plugins/lint/plugin.json`
|
|
35
|
+
|
|
36
|
+
```json
|
|
37
|
+
{
|
|
38
|
+
"key": "lint",
|
|
39
|
+
"socket": "pre-commit",
|
|
40
|
+
"run": "node .flumecode/plugins/lint/run.mjs",
|
|
41
|
+
"heartbeat": {
|
|
42
|
+
"url": "https://<flumecode-base-url>/api/runner/plugins/heartbeat",
|
|
43
|
+
"token": "<repo-scoped-token>"
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
`url` and `token` are placeholders — note in the plan that the user must fill
|
|
49
|
+
them in via the FlumeCode web UI after installation. The plan must **not**
|
|
50
|
+
commit a real token value.
|
|
51
|
+
|
|
52
|
+
### Artifact 2 — `.flumecode/plugins/lint/run.mjs`
|
|
53
|
+
|
|
54
|
+
A Node.js ES module that:
|
|
55
|
+
|
|
56
|
+
1. Reads `plugin.json` from the same directory to get `heartbeat.url` and `heartbeat.token`.
|
|
57
|
+
2. Determines the current git branch (`git rev-parse --abbrev-ref HEAD`).
|
|
58
|
+
3. Runs each detected lint/format/typecheck command with `child_process.execSync` (stdio: `inherit`).
|
|
59
|
+
4. On success, POSTs to the heartbeat URL:
|
|
60
|
+
`{ repoId: process.env.FLUMECODE_REPO_ID, pluginKey: "lint", branch, status: "pass", timestamp: new Date().toISOString() }`
|
|
61
|
+
(`FLUMECODE_REPO_ID` — the runner will inject this in Plan 2; if not yet available, the heartbeat may omit repoId or read it from .flumecode/config.json)
|
|
62
|
+
5. On any command failure, exits non-zero (and optionally POSTs `status: "fail"`).
|
|
63
|
+
|
|
64
|
+
The `repoId` comes from the `FLUMECODE_REPO_ID` environment variable that the
|
|
65
|
+
runner sets. The heartbeat request uses `Authorization: Bearer <token>`.
|
|
66
|
+
|
|
67
|
+
### Manifest shape
|
|
68
|
+
|
|
69
|
+
The manifest `plugin.json` must have exactly these fields:
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
{ key, socket, run, heartbeat: { url, token } }
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
This is the shape the FlumeCode plugin loader expects.
|
|
76
|
+
|
|
77
|
+
### Heartbeat endpoint
|
|
78
|
+
|
|
79
|
+
`POST /api/runner/plugins/heartbeat` with JSON body:
|
|
80
|
+
`{ repoId, pluginKey, branch, status, timestamp }`
|
|
81
|
+
(this endpoint does not exist yet — it will be created by Plan 2; include this as a step in the generated plan or as a prerequisite note)
|
|
82
|
+
|
|
83
|
+
### Acceptance criteria the plan must include
|
|
84
|
+
|
|
85
|
+
- `.flumecode/plugins/lint/plugin.json` exists with `key: "lint"`, `socket: "pre-commit"`, `run: "node .flumecode/plugins/lint/run.mjs"`.
|
|
86
|
+
- `.flumecode/plugins/lint/run.mjs` runs the repo's detected lint/format/typecheck commands and exits non-zero on any failure.
|
|
87
|
+
- A successful run POSTs a heartbeat with `{ repoId, pluginKey: "lint", branch, status: "pass", timestamp }`.
|
|
88
|
+
|
|
89
|
+
## Always
|
|
90
|
+
|
|
91
|
+
- Stay read-only. Produce the plan via `submit_plan`; never edit files.
|
|
92
|
+
- The plan must be specific enough for an `implement-plan` run to execute
|
|
93
|
+
without re-deriving the commands — include the actual detected commands in
|
|
94
|
+
the step descriptions and pseudo code.
|
|
95
|
+
- Leave `heartbeat.url` and `heartbeat.token` as placeholders — document that
|
|
96
|
+
the user fills them in via the FlumeCode web UI after installation.
|
|
@@ -71,11 +71,19 @@ Field-by-field guidance:
|
|
|
71
71
|
- **`description`** — what changes and why: the concrete change being made and the rationale for it. Use concrete file references (`path/to/file.ts`) and name the functions/symbols involved.
|
|
72
72
|
- **`pseudoCode`** — an array of `{ file, pseudoCode }` entries. Provide an entry for every file the step touches **except** documentation files (SKILL.md, README.md, wiki pages, etc.). `pseudoCode` is optional in the schema but expected for all non-documentation files. Each entry names the file path and contains pseudo code that precisely describes the changes to make in that file.
|
|
73
73
|
- **`acceptanceCriteria`** — **required; at least 2 items.** Each criterion must
|
|
74
|
-
be
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
74
|
+
be a concrete, deterministically-checkable condition that a third party can verify
|
|
75
|
+
without knowing the author's intent. Write each as a trigger/precondition and the
|
|
76
|
+
exact observable result: `run X → output Y`, `file Z contains W`, `calling f(a) returns b`.
|
|
77
|
+
No vague adjectives (`robust`, `clean`, `properly`, `works correctly`). The set
|
|
78
|
+
must be **collectively exhaustive** — every step's intended change is covered by
|
|
79
|
+
at least one AC. Do **not** restate a step as a criterion.
|
|
80
|
+
|
|
81
|
+
**Good vs bad examples:**
|
|
82
|
+
- ✅ `grep -rn "What changed" apps/runner/src/report.ts` produces no matches.
|
|
83
|
+
- ❌ The report is cleaner and no longer mentions 'What changed'. _(vague, not checkable)_
|
|
84
|
+
- ✅ `pnpm test` in the repo root exits 0 and report.test.ts output contains no failures.
|
|
85
|
+
- ❌ Tests pass correctly. _(no trigger, no observable result)_
|
|
86
|
+
|
|
79
87
|
- **`risks`** — anything that could change the approach or surface a problem.
|
|
80
88
|
- **`outOfScope`** — what you are deliberately not doing.
|
|
81
89
|
|
|
@@ -25,11 +25,34 @@ branch was building, which is exactly the intent you must preserve when you choo
|
|
|
25
25
|
to integrate each conflict. Check the FlumeCode wiki (`.flumecode/wiki/README.md`) if
|
|
26
26
|
one exists to understand the conflicting code.
|
|
27
27
|
|
|
28
|
+
If the prompt includes a **'Related sessions behind the incoming changes'** section, read it carefully — it carries the accepted plan and final implementation report of the other coding sessions whose work landed on the merge branch and is now conflicting with yours. Use those plans and reports to understand what _they_ were building so you can resolve each conflict in a way that preserves both sessions' intent, not just this one's.
|
|
29
|
+
|
|
30
|
+
## Why conflicts are routine here (and how to avoid making them worse)
|
|
31
|
+
|
|
32
|
+
Every coding session is frozen to one commit, but several sessions often run against
|
|
33
|
+
the same base at once. When a sibling session merges first, this branch's base
|
|
34
|
+
(usually `main`) moves and the overlap surfaces as a conflict — so conflicts are a
|
|
35
|
+
normal, expected event, not a sign anything went wrong. **Rebasing onto the base does
|
|
36
|
+
not make a genuine conflict disappear** — it just replays this branch's commits onto
|
|
37
|
+
the new base, and the same overlapping lines collide there too. Integration is
|
|
38
|
+
unavoidable; your job is to do it well, preserving both intents.
|
|
39
|
+
|
|
28
40
|
## Step 1 — Find every conflict
|
|
29
41
|
|
|
30
42
|
- `git status` shows the unmerged paths; `git diff --diff-filter=U` shows the
|
|
31
43
|
conflicting hunks. Work through **all** of them — a single leftover marker fails the
|
|
32
44
|
run.
|
|
45
|
+
- **Generated/derived files: regenerate, don't hand-merge.** Some conflicted files are
|
|
46
|
+
not authored directly — they're produced from a source of truth by a tool (DB
|
|
47
|
+
migrations + their journal/snapshot from a schema, lockfiles from a manifest, bundled
|
|
48
|
+
or compiled output, sequentially-numbered files, generated API clients/types). For
|
|
49
|
+
these, **removing the markers is not enough**: a hand-merge can be marker-free yet
|
|
50
|
+
inconsistent, which breaks the build in a way the conflict markers never warned about.
|
|
51
|
+
Resolve the **source** first (e.g. the schema or manifest), then **re-run the
|
|
52
|
+
generator** to rebuild the derived files from scratch rather than stitching both
|
|
53
|
+
sides together by hand. Check the repo's wiki (`.flumecode/wiki/`) for the exact
|
|
54
|
+
regeneration command and any conventions — and if a regeneration step exists, prefer
|
|
55
|
+
it over editing the generated file directly.
|
|
33
56
|
|
|
34
57
|
## Step 2 — Resolve each conflict correctly
|
|
35
58
|
|
|
@@ -53,13 +76,18 @@ coding guidelines verbatim) — subagents start blank.
|
|
|
53
76
|
|
|
54
77
|
Run the project's build and tests to confirm the resolved tree is correct (the
|
|
55
78
|
runner's commit will also run the repo's pre-commit hook, so failing checks would
|
|
56
|
-
block the merge anyway). Fix anything the merge broke.
|
|
79
|
+
block the merge anyway). Fix anything the merge broke. The runner then checks every
|
|
80
|
+
file that was conflicted for leftover markers (`<<<<<<<`, `=======`, `>>>>>>>`) and
|
|
81
|
+
**fails the run** if any remain — so make sure each conflicted file reads as clean code
|
|
82
|
+
before you finish. (You don't need to `git add`; the runner stages and commits for you.)
|
|
57
83
|
|
|
58
84
|
## Never
|
|
59
85
|
|
|
60
|
-
- Never `git
|
|
61
|
-
|
|
62
|
-
|
|
86
|
+
- Never `git commit`, `git merge --continue`, `git push`, or open a PR — the runner
|
|
87
|
+
stages the resolved tree, finalizes the merge commit, and updates the **existing**
|
|
88
|
+
pull request. A new PR must never be created. (Leaving the files unstaged is fine —
|
|
89
|
+
the runner detects whether you're done by scanning file content for markers, not by
|
|
90
|
+
the index, so don't try to `git merge --continue` to "complete" the merge yourself.)
|
|
63
91
|
- Never leave a conflict marker behind, and never resolve a conflict by discarding one
|
|
64
92
|
side's intent.
|
|
65
93
|
|