@flumecode/runner 0.23.1 → 0.25.0-preview.39

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/mcp-stdio.js CHANGED
@@ -66,6 +66,9 @@ var requirementSchema = z.object({
66
66
  )
67
67
  });
68
68
  var planInputSchema = {
69
+ dependsOn: z.array(z.number().int().positive()).optional().describe(
70
+ "1-based positions of EARLIER plans in this same submission that must be merged or closed before this one. Use ONLY when the work must be strictly serial; omit for independent plans."
71
+ ),
69
72
  title: z.string().min(1).max(120).describe(
70
73
  "A concise, descriptive name for THIS plan. Must be distinct from the request title and from any sibling plans on the same request. Keep it under 120 characters."
71
74
  ),
@@ -187,6 +190,20 @@ function renderPlan(plan) {
187
190
  lines.push(PLAN_MARKER);
188
191
  return lines.join("\n");
189
192
  }
193
+ function validateDependsOnReferences(arr, ctx) {
194
+ for (let i = 0; i < arr.length; i++) {
195
+ const deps = arr[i]?.dependsOn ?? [];
196
+ for (const dep of deps) {
197
+ if (dep > i || dep < 1) {
198
+ ctx.addIssue({
199
+ code: z.ZodIssueCode.custom,
200
+ path: [i, "dependsOn"],
201
+ message: "dependsOn must reference an earlier plan (1-based) in this submission."
202
+ });
203
+ }
204
+ }
205
+ }
206
+ }
190
207
  var submitPlanInputSchema = {
191
208
  plans: z.array(requireAtLeastTwoCriteria(requireRootCauseForFix(z.object(planInputSchema)))).min(1).refine(
192
209
  (arr) => {
@@ -194,7 +211,7 @@ var submitPlanInputSchema = {
194
211
  return new Set(titles).size === titles.length;
195
212
  },
196
213
  { message: "Each plan must have a distinct non-empty title" }
197
- )
214
+ ).superRefine(validateDependsOnReferences)
198
215
  };
199
216
  var submitPlanSchema = z.object(submitPlanInputSchema);
200
217
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flumecode/runner",
3
- "version": "0.23.1",
3
+ "version": "0.25.0-preview.39",
4
4
  "type": "module",
5
5
  "description": "FlumeCode local runner — claims jobs and drives your local Claude Code against a real checkout.",
6
6
  "bin": {
@@ -47,3 +47,4 @@ description: >-
47
47
  ## Documentation
48
48
 
49
49
  - When behavior or conventions change, update the matching project docs (`CLAUDE.md` or rule files) in the same PR.
50
+ - FlumeCode plugin recipes (`.flumecode/plugins/*.json`) record how to install, build, run, or preview the app. If your change invalidates one — you altered the install/build/run/dev-server command, how the port or env is supplied, where the app lives (`appDir`), or which files count as the relevant change — update the matching recipe in the same PR so it doesn't go stale. They are not regenerated automatically; a stale recipe silently breaks the capability (e.g. the UI Preview pass) until someone re-installs.
@@ -1,127 +1,86 @@
1
1
  ---
2
2
  name: preview-ui
3
3
  description: >-
4
- Author an ephemeral fake-data showcase page for changed UI components so the
5
- runner can screenshot them in a headless browser. Use after a UI-touching
6
- implementation, when the runner provides a tmpRoute directory. Writes the
7
- showcase files there and records the URL path in a sentinel file. Never
8
- commits, pushes, or modifies application code outside the tmpRoute directory.
4
+ Author an ephemeral showcase that renders the recently-changed UI with realistic
5
+ fake data, so the runner can screenshot it in a headless browser. Use after a
6
+ UI-touching implementation, when the runner provides a preview recipe (from the
7
+ repo's ui-preview plugin manifest) and a sentinel-file path. Follows the recipe to
8
+ mount a temporary showcase including registering a temporary route for
9
+ server-rendered stacks — and records the showcase URL in the sentinel file. The
10
+ showcase is ephemeral: the runner reverts the working tree afterward, so it never
11
+ reaches the pull request.
9
12
  ---
10
13
 
11
14
  # preview-ui
12
15
 
13
- You author a **temporary showcase page** that imports the recently-changed UI
14
- components and fills them with realistic fake data, so the runner can start the
15
- repo's dev server and take headless screenshots.
16
+ You author a **temporary showcase** that renders the recently-changed UI filled with
17
+ realistic fake data, so the runner can start the app and take headless screenshots.
16
18
 
17
- You write only inside the `<tmpRoute>` directory the runner hands you. You never
18
- modify production code, commit, or push.
19
+ The showcase is **ephemeral**. The runner runs this pass _after_ the implementation is
20
+ already committed, and **reverts the working tree** (tracked and untracked changes) once
21
+ it has captured the screenshots. So you may edit whatever the recipe requires — including
22
+ registering a temporary route in tracked files — and **nothing you write reaches the pull
23
+ request**. Never commit or push.
19
24
 
20
25
  ## What you receive
21
26
 
22
27
  The runner injects these into your prompt:
23
28
 
24
- - **`<tmpRoute>`** an absolute path to an empty temp directory inside the repo
25
- (already git-excluded). Write your showcase files here.
26
- - **Committed UI files** the list of files changed by the implementation, so
27
- you know which components to showcase.
28
-
29
- ## Step 1Detect the framework
30
-
31
- Read the repo's `package.json` (and `package.json` files in workspaces, if any)
32
- to determine the framework:
33
-
34
- | Framework | Key `dependencies` / `devDependencies` |
35
- | ------------- | --------------------------------------- |
36
- | Next.js | `next` |
37
- | Vite + React | `vite` + `react` |
38
- | Vite + Vue | `vite` + `vue` |
39
- | Vite + Svelte | `vite` + `svelte` (no SvelteKit) |
40
- | SvelteKit | `@sveltejs/kit` |
41
- | Nuxt | `nuxt` |
42
- | Astro | `astro` |
43
- | CRA | `react-scripts` |
44
- | Remix | `@remix-run/react` or `@remix-run/node` |
45
-
46
- If the framework is not recognisable or the file list contains no importable
47
- components, write a single plain `<tmpRoute>/index.html` file with a message
48
- like "No supported framework detected" and write `/__flumecode_preview` to
49
- `<tmpRoute>/.showcase-path`. Then stopdo not create a route file.
50
-
51
- ## Step 2 Determine the entry path
52
-
53
- Choose a URL path unlikely to collide with real routes: `/__flumecode_preview`.
54
- Write that string (exactly, no trailing newline) to `<tmpRoute>/.showcase-path`.
55
-
56
- ## Step 3 — Author the showcase entry file
57
-
58
- Create a single route/page file at the correct location under `<tmpRoute>` for
59
- the detected framework:
60
-
61
- | Framework | File to create |
62
- | ---------------------- | ----------------------------------------------------- |
63
- | Next.js (App Router) | `<tmpRoute>/page.tsx` (if the project uses `app/`) |
64
- | Next.js (Pages Router) | `<tmpRoute>/index.tsx` (if the project uses `pages/`) |
65
- | Vite + React | `<tmpRoute>/App.tsx` (or `.jsx`) |
66
- | Vite + Vue | `<tmpRoute>/App.vue` |
67
- | Vite + Svelte | `<tmpRoute>/App.svelte` |
68
- | SvelteKit | `<tmpRoute>/+page.svelte` |
69
- | Nuxt | `<tmpRoute>/index.vue` |
70
- | Astro | `<tmpRoute>/index.astro` |
71
- | CRA | `<tmpRoute>/index.tsx` |
72
- | Remix | `<tmpRoute>/route.tsx` |
73
-
74
- **Next.js App Router note:** The runner mounts the showcase at
75
- `app/__flumecode_preview/page.tsx` by symlinking or copying `<tmpRoute>` to
76
- `app/__flumecode_preview/`. You only need to produce `<tmpRoute>/page.tsx` — the
77
- runner handles the mount.
29
+ - **The preview recipe** from the repo's `.flumecode/plugins/ui-preview.json` manifest
30
+ (written when a repo member initialized the UI Preview plugin). It tells you the app
31
+ directory, the showcase strategy for this stack, and step-by-step instructions for
32
+ where to put the showcase and which URL path it serves at. **Follow it** — it is the
33
+ source of truth for how previews work in this repo. Do not re-detect the framework.
34
+ - **A sentinel file path** an absolute path. Write the showcase's URL path there.
35
+ - **Changed UI files** — the list of files the implementation changed, so you know what
36
+ to showcase.
37
+
38
+ ## Step 1 — Record the URL path first
39
+
40
+ Decide the showcase URL path the recipe specifies (e.g. `/__flumecode_preview`). Write
41
+ that string **exactly** (no trailing newline) to the sentinel file the runner gave you,
42
+ **before** authoring anything else the runner reads it even if a later step fails.
43
+
44
+ ## Step 2 Author the showcase by following the recipe
45
+
46
+ Do exactly what the recipe's instructions say for this repo's stack. The shape differs by
47
+ stack, but the intent is always the same: a single page/route that renders the changed UI
48
+ with hard-coded fake data, reachable at the URL path from Step 1.
49
+
50
+ - **Drop-in file stacks** (e.g. a Next.js/Vite/Svelte route file): create the showcase
51
+ entry file at the location the recipe names, importing the changed components by their
52
+ real relative paths and filling every prop with realistic fake data.
53
+ - **Server-rendered stacks** (e.g. Django, Rails): also register a **temporary route** so
54
+ the page is reachable add the URL/route mapping the recipe describes (e.g. a Django
55
+ `urls.py` entry pointing at a throwaway view + template, a Rails route + controller
56
+ action + view). Editing these tracked files is expected and safe; the runner reverts
57
+ them after capture.
78
58
 
79
59
  ### Content rules
80
60
 
81
- - Import the changed components using their real relative paths (calculate the
82
- path from `<tmpRoute>` to the component's source location).
83
- - Fill every prop with **realistic fake data** use hardcoded literals, not
84
- calls to external APIs or databases.
85
- - If a component requires a provider (React context, Vuex store, Pinia, etc.),
86
- wrap it with a minimal in-file stub provider do not import the real app
87
- store or data layer.
88
- - If a component calls a route handler or fetch endpoint, stub the relevant
89
- function or hook at the top of the file with a mock that returns realistic
90
- hard-coded data. Do NOT import MSW or any test library; keep stubs as plain
91
- module-level overrides.
92
- - Export the showcase page as the default export (except Astro/SvelteKit, which
93
- don't require a default export).
94
- - Keep the file short: one `export default` function that renders all changed
95
- components in a flex column, with a small amount of padding.
96
-
97
- ### What NOT to do
98
-
99
- - Do not call `fetch`, `axios`, `prisma`, `supabase`, or any I/O in the
100
- showcase.
101
- - Do not import from test utilities, MSW, Storybook, or Cypress.
102
- - Do not add new npm dependencies.
103
- - Do not edit any file outside `<tmpRoute>`.
104
- - Do not commit or push.
105
-
106
- ## Step 4 — Verify your output
107
-
108
- Before finishing, confirm:
109
-
110
- 1. `<tmpRoute>/.showcase-path` exists and contains the URL path string.
111
- 2. The showcase entry file exists at the expected path under `<tmpRoute>`.
112
- 3. The file imports only modules that already exist in the repo (no invented
113
- paths).
114
-
115
- If you cannot produce a valid showcase (e.g. the components have complex
116
- dependencies you cannot stub), write only `<tmpRoute>/.showcase-path` with the
117
- URL string and leave the entry file absent — the runner will detect the missing
118
- file and skip the screenshot step gracefully.
61
+ - Fill every prop / template variable with **realistic fake data** — hard-coded literals,
62
+ never live calls to a database, API, or external service.
63
+ - If a component needs a provider/context/store, wrap it with a minimal in-file stub — do
64
+ not import the real app store or data layer.
65
+ - If a component or view calls a fetch/route/query, stub it locally with a mock returning
66
+ realistic hard-coded data. Do NOT pull in MSW, Storybook, Cypress, or any test library.
67
+ - Do not add new dependencies — the manifest already declares everything previews need.
68
+ - Keep it short: render all the changed UI in one simple page with a little padding.
69
+
70
+ ## Step 3 Verify before finishing
71
+
72
+ 1. The sentinel file contains the showcase URL path.
73
+ 2. The showcase entry (and any temporary route registration the stack needs) exists and
74
+ references only modules/paths that already exist in the repo no invented imports.
75
+
76
+ If you cannot produce a valid showcase (e.g. the changed UI has dependencies you cannot
77
+ reasonably stub), leave only the sentinel file with the URL path and stop — the runner
78
+ detects the missing showcase and reports the preview as needing manual setup rather than
79
+ crashing.
119
80
 
120
81
  ## Always
121
82
 
122
- - Write the URL path to `<tmpRoute>/.showcase-path` first, before any other
123
- file the runner reads it even if something else fails.
124
- - These files are ephemeral and git-excluded. They will be deleted by the runner
125
- after screenshots are taken. Never commit or push them.
126
- - Your final reply should be one short sentence confirming what you created (e.g.
127
- "Wrote `<tmpRoute>/page.tsx` showcasing `Button` and `Card` with fake data.").
83
+ - Write the URL path to the sentinel file **first**, before anything else.
84
+ - The showcase is ephemeral and reverted by the runner. **Never commit or push.**
85
+ - Final reply: one short sentence naming what you created and its URL path (e.g.
86
+ "Showcased `Button` and `Card` at `/__flumecode_preview` via a temporary route.").
@@ -89,6 +89,7 @@ Field-by-field guidance:
89
89
  - **`description`** — an array of bullet points that help the reviewer understand the upcoming `pseudoCode` and decide whether the plan and design are correct. Each item is a distinct, self-contained point about what is changing and why — not a single paragraph, and not a line-by-line restatement of the pseudo code. Use concrete file references (`path/to/file.ts`) and name the functions/symbols involved. Apply inline-code formatting to all identifiers.
90
90
  - **`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.
91
91
 
92
+ - **`dependsOn`** — optional. A list of 1-based positions of EARLIER plans in the same `plans[]` call that must be merged or closed before this one can start. Use ONLY when the plans must be worked strictly serially (e.g. a shared refactor that must merge before dependent features can be built on top of it). Omit for independent plans — most plans are independent.
92
93
  - **`risks`** — anything that could change the approach or surface a problem.
93
94
  - **`outOfScope`** — what you are deliberately not doing.
94
95
 
@@ -110,6 +111,12 @@ own independently-acceptable "Accept as plan" draft. After a plan is accepted th
110
111
  keep commenting to refine it; treat a later turn as a fresh **Plan** phase and call
111
112
  `submit_plan` again with a `plans[]` array containing the revised fields.
112
113
 
114
+ When plans must be worked in a strict order (e.g. plan 1 is a shared refactor that plan 2
115
+ builds on), express this with `dependsOn`: plan 2 sets `dependsOn: [1]`. Accepting the plans
116
+ auto-creates the blocking links between their coding sessions — the order of acceptance does
117
+ not matter. Do **not** use `dependsOn` for plans that can safely run in parallel; rely on
118
+ array order only for documentation, not for enforcement.
119
+
113
120
  Before adding an entry to `plans[]`, apply this right-sizing checklist — if a plan fails any criterion, split it into separate entries:
114
121
 
115
122
  - **Single, clear outcome** — one bug fixed, one feature increment, one refactor. If the `title` needs "and", consider splitting.
@@ -0,0 +1,166 @@
1
+ ---
2
+ name: setup-preview
3
+ description: >-
4
+ Set up the FlumeCode UI Preview plugin for a repository. Analyse the app, then
5
+ record how to install it, run its dev server, and mount a temporary showcase page
6
+ into a machine-readable manifest at .flumecode/plugins/ui-preview.json plus a
7
+ human-readable wiki page — and install any packages future previews need. Use when a
8
+ request asks to install/re-initialize the UI Preview plugin. Works for any stack
9
+ (Node, Django, Rails, …): everything
10
+ stack-specific is captured as data in the manifest, so later previews need no
11
+ per-stack code. If previews can't be fully automated, record the manual steps.
12
+ ---
13
+
14
+ # setup-preview
15
+
16
+ You set up the **UI Preview plugin** for this repository: a one-time (re-runnable)
17
+ analysis that records _how to run and preview this app_ so that every later coding
18
+ session can screenshot its UI automatically — for **any** stack, with no per-stack code.
19
+
20
+ You produce two artifacts and commit them (the runner opens the PR):
21
+
22
+ 1. **`.flumecode/plugins/ui-preview.json`** — the machine-readable recipe the per-session
23
+ preview pass executes. Its existence is what marks the plugin "initialized".
24
+ 2. **A wiki record** — a human-readable `.flumecode/wiki/components/ui-preview.md` page,
25
+ linked from the wiki nav map, documenting the detected stack and how previews work,
26
+ with a sync marker.
27
+
28
+ You may also install/scaffold packages the previews genuinely need (these persist in the
29
+ PR). Do **not** otherwise modify application code.
30
+
31
+ ## Step 1 — Understand the app
32
+
33
+ Read the FlumeCode wiki first if it exists (`.flumecode/wiki/README.md`), then confirm
34
+ against the code. Determine:
35
+
36
+ - **The app directory** — the repo root, or a subdirectory / workspace member that holds
37
+ the previewable front-end (e.g. `apps/web`).
38
+ - **The stack** — framework + language (Next.js, Vite, SvelteKit, Django, Rails, …).
39
+ - **Install** — the command(s) that make the app runnable (`pnpm install`,
40
+ `pip install -r requirements.txt`, `bundle install`, …).
41
+ - **Dev server** — the command that serves the app on a port, and how the port is passed.
42
+ - **Hermetic boot** — any env vars needed so the dev server starts without real
43
+ infrastructure (e.g. a throwaway SQLite `DATABASE_URL`, a dummy secret). Previews must
44
+ not depend on production services.
45
+ - **Showcase mounting** — how to add a _temporary_ page that renders arbitrary components
46
+ with fake data, reachable at a URL. For drop-in-file frameworks that's a route file; for
47
+ server-rendered stacks (Django, Rails) it's a temporary route + view + template.
48
+
49
+ ## Step 2 — Write `.flumecode/plugins/ui-preview.json`
50
+
51
+ Write the manifest with these fields (the runner fills sane defaults for omitted optionals,
52
+ but be explicit):
53
+
54
+ | Field | Type | Meaning |
55
+ | ------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
56
+ | `version` | number | Manifest version. Use `1`. |
57
+ | `appDir` | string | App dir relative to repo root (`.` for root). |
58
+ | `install` | string[] | Commands run (in order) before the dev server. Keep idempotent. |
59
+ | `devServer` | string | Dev-server command. Use the token `{PORT}` where the port goes. |
60
+ | `readyPath` | string | Path polled for HTTP readiness once up (usually `/`). |
61
+ | `env` | object (optional) | Extra env for the dev server (hermetic boot). |
62
+ | `uiGlobs` | string[] | Globs that count as a UI change (gates whether a session previews). |
63
+ | `showcase` | object | `{ "kind": "...", "instructions": "..." }` — the recipe the `preview-ui` skill follows each session to author the ephemeral showcase. |
64
+ | `manualSteps` | string (optional) | Set ONLY when you cannot fully automate previews — markdown telling a human what to do. Omit/empty otherwise. |
65
+
66
+ The `showcase.instructions` is the most important field: write **clear, stack-specific,
67
+ step-by-step** instructions a future agent can follow blindly — where to create the
68
+ showcase file(s), which route to register, the exact URL path to serve at, and how to
69
+ import/stub the changed UI. Choose an unlikely URL path such as `/__flumecode_preview`.
70
+
71
+ ### Examples
72
+
73
+ **Next.js (App Router) in a monorepo member:**
74
+
75
+ ```json
76
+ {
77
+ "version": 1,
78
+ "appDir": "apps/web",
79
+ "install": ["pnpm install"],
80
+ "devServer": "pnpm next dev -p {PORT}",
81
+ "readyPath": "/",
82
+ "uiGlobs": ["apps/web/**/*.tsx", "apps/web/**/*.css"],
83
+ "showcase": {
84
+ "kind": "next-app-route",
85
+ "instructions": "Create apps/web/app/__flumecode_preview/page.tsx as a client component. Import the changed components by relative path, render them in a column with fake props, and stub any data hooks inline. Serve at /__flumecode_preview."
86
+ }
87
+ }
88
+ ```
89
+
90
+ **Django:**
91
+
92
+ ```json
93
+ {
94
+ "version": 1,
95
+ "appDir": ".",
96
+ "install": ["pip install -r requirements.txt"],
97
+ "devServer": "python manage.py runserver 127.0.0.1:{PORT}",
98
+ "readyPath": "/",
99
+ "env": { "DJANGO_SETTINGS_MODULE": "myproject.settings", "DATABASE_URL": "sqlite:///preview.db" },
100
+ "uiGlobs": ["**/templates/**/*.html", "**/static/**/*.css"],
101
+ "showcase": {
102
+ "kind": "django-urlconf",
103
+ "instructions": "Add a temporary view that renders the changed template(s) with a hard-coded context, register it at path '__flumecode_preview/' in the project urls.py, and ensure ALLOWED_HOSTS permits localhost. Serve at /__flumecode_preview/."
104
+ }
105
+ }
106
+ ```
107
+
108
+ **Ruby on Rails:**
109
+
110
+ ```json
111
+ {
112
+ "version": 1,
113
+ "appDir": ".",
114
+ "install": ["bundle install"],
115
+ "devServer": "bin/rails server -p {PORT} -b 127.0.0.1",
116
+ "readyPath": "/",
117
+ "env": { "RAILS_ENV": "development" },
118
+ "uiGlobs": ["app/views/**/*.erb", "app/assets/**/*.css"],
119
+ "showcase": {
120
+ "kind": "rails-route",
121
+ "instructions": "Add a temporary controller action that assigns hard-coded instance variables and renders the changed view(s), wire it to get '/__flumecode_preview' in config/routes.rb. Serve at /__flumecode_preview."
122
+ }
123
+ }
124
+ ```
125
+
126
+ ## Step 3 — Write the wiki record
127
+
128
+ Create or update `.flumecode/wiki/components/ui-preview.md` (and add a row for it in the
129
+ wiki nav map in `README.md`). It documents — for humans — the detected stack, the
130
+ install/run/preview commands, and any manual steps. Begin it with a sync marker so a future
131
+ re-init knows what it last synced to:
132
+
133
+ ```
134
+ <!-- preview-plugin-synced-to: <current HEAD SHA> -->
135
+ ```
136
+
137
+ Get the SHA with `git rev-parse HEAD`. Keep the page short and accurate; point at the
138
+ manifest rather than duplicating it.
139
+
140
+ ## Step 4 — Install / scaffold what previews need
141
+
142
+ If the app needs a package or config to be previewable (e.g. a dev dependency, a sample
143
+ env file, a static-build config), add it now — these changes persist in the PR so future
144
+ previews don't re-do them. Do not add anything the app doesn't actually need.
145
+
146
+ ## Step 5 — Best-effort self-verify
147
+
148
+ If you can, verify the recipe end-to-end without real infrastructure: run `install`, start
149
+ the `devServer` on a free port with `env`, author a trivial showcase per your own
150
+ `showcase.instructions`, and confirm the page renders. Then **revert any throwaway showcase
151
+ edits** — only the manifest, wiki record, and genuinely-needed packaging should remain.
152
+
153
+ ## When you cannot fully automate
154
+
155
+ If the app cannot boot for previews without external services (a real database, third-party
156
+ auth, secrets you don't have), do not guess. Set `devServer` to `""` (or still record your
157
+ best attempt) and fill `manualSteps` with concise markdown telling a human exactly what to
158
+ provide. Still write the wiki record. The per-session pass will then report previews as
159
+ needing setup, surfacing your steps, instead of failing opaquely.
160
+
161
+ ## Always
162
+
163
+ - Only create/edit files under `.flumecode/` plus the minimal packaging the previews need.
164
+ Never change application logic.
165
+ - Do not commit or push — the runner does. Reply with a one- or two-line summary: the
166
+ detected stack, the commands you recorded, and any manual steps left for a human.