@flumecode/runner 0.18.0 → 0.19.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 CHANGED
@@ -188,6 +188,12 @@ import { query } from "@anthropic-ai/claude-agent-sdk";
188
188
  import { randomUUID } from "node:crypto";
189
189
  import { createSdkMcpServer, tool } from "@anthropic-ai/claude-agent-sdk";
190
190
  import { z } from "zod";
191
+
192
+ // src/schema-hints.ts
193
+ var INLINE_CODE_HINT = "Wrap code identifiers (function, variable, type, and file names, commands, and flags) in inline backticks, e.g. `getCodingSessionsForRequest`.";
194
+ var WIDGET_LANGUAGE_HINT = "Write this in the same natural language as the incoming thread (the request body and the user's messages). If the thread is in English, keep it in English; do not switch languages. Keep code identifiers, file paths, and quoted code verbatim.";
195
+
196
+ // src/widgets.ts
191
197
  var SERVER_NAME = "flume_widgets";
192
198
  var SINGLE_SELECT = "single_select";
193
199
  var MULTI_SELECT = "multi_select";
@@ -195,15 +201,15 @@ var WIDGET_TOOL_NAMES = [
195
201
  `mcp__${SERVER_NAME}__${SINGLE_SELECT}`,
196
202
  `mcp__${SERVER_NAME}__${MULTI_SELECT}`
197
203
  ];
198
- var optionsSchema = z.array(z.string().min(1)).min(2).max(8).describe("2\u20138 short, distinct choices for the user to pick from.");
199
- var TAIL = "Do NOT add an 'Other' or 'None of these' catch-all \u2014 the UI always offers an 'Other' free-text option automatically. After calling this, END YOUR TURN and wait: the user's answer arrives as their next message and starts a fresh run.";
204
+ var optionsSchema = z.array(z.string().min(1)).min(2).max(8).describe("2\u20138 short, distinct choices for the user to pick from. " + WIDGET_LANGUAGE_HINT);
205
+ var TAIL = "Do NOT add an 'Other' or 'None of these' catch-all \u2014 the UI always offers an 'Other' free-text option automatically. " + WIDGET_LANGUAGE_HINT + " After calling this, END YOUR TURN and wait: the user's answer arrives as their next message and starts a fresh run.";
200
206
  function createWidgetTooling() {
201
207
  const collected = [];
202
208
  const singleSelect = tool(
203
209
  SINGLE_SELECT,
204
210
  "Ask the user a single-select (radio-button) question \u2014 exactly one answer. Use this for a genuine either/or choice (competing approaches, scope decisions, yes/no) instead of writing the options as prose. " + TAIL,
205
211
  {
206
- question: z.string().min(1).describe("The question to ask the user."),
212
+ question: z.string().min(1).describe("The question to ask the user. " + WIDGET_LANGUAGE_HINT),
207
213
  body: z.string().optional().describe(
208
214
  "Optional markdown shown above the question so the user can read the context they're confirming (e.g. the drafted release notes). Omit for plain questions."
209
215
  ),
@@ -226,7 +232,7 @@ function createWidgetTooling() {
226
232
  MULTI_SELECT,
227
233
  "Ask the user a multi-select (checkbox) question \u2014 they may pick any number of options, including none of the presets if they use 'Other'. Use this for 'select all that apply' questions (which features to include, which files to touch). " + TAIL,
228
234
  {
229
- question: z.string().min(1).describe("The question to ask the user."),
235
+ question: z.string().min(1).describe("The question to ask the user. " + WIDGET_LANGUAGE_HINT),
230
236
  body: z.string().optional().describe(
231
237
  "Optional markdown shown above the question so the user can read the context they're confirming (e.g. the drafted release notes). Omit for plain questions."
232
238
  ),
@@ -288,9 +294,6 @@ function langFromPath(path) {
288
294
  return ext ? EXT_TO_LANG[ext] : void 0;
289
295
  }
290
296
 
291
- // src/schema-hints.ts
292
- var INLINE_CODE_HINT = "Wrap code identifiers (function, variable, type, and file names, commands, and flags) in inline backticks, e.g. `getCodingSessionsForRequest`.";
293
-
294
297
  // src/plan.ts
295
298
  var SERVER_NAME2 = "flume_plan";
296
299
  var SUBMIT_PLAN = "submit_plan";
@@ -773,6 +776,7 @@ function appendRule(lines2, intro, ruleName) {
773
776
  lines2.push("", intro, "", loadRule(ruleName));
774
777
  }
775
778
  var WRITING_INTRO = "These technical-writing guidelines apply to the plan and report prose you author in this run:";
779
+ var LANGUAGE_DIRECTIVE = "First, determine the dominant natural language of the incoming thread (the request title/body and the user's messages). Use that one language for EVERYTHING you author this run - your reply body, any plan or report fields, AND every clarifying question and its widget options. Never mix languages: if the thread is in English, your questions and options must be in English too. Keep code identifiers, file paths, and quoted code verbatim.";
776
780
  function turnHeading(turn, agentName) {
777
781
  if (turn.role === "user") return "User";
778
782
  if (turn.failed) return `${agentName} (this run ended in an error)`;
@@ -796,7 +800,8 @@ function buildPrompt(ctx) {
796
800
  `The repository ${ctx.repo.fullName} is checked out in your current working directory on branch "${ctx.repo.checkoutBranch}" at commit ${ctx.repo.checkoutSha.slice(0, 7)}.`,
797
801
  task,
798
802
  orient,
799
- widgets
803
+ widgets,
804
+ LANGUAGE_DIRECTIVE
800
805
  ];
801
806
  if (ctx.permissionMode !== "plan") {
802
807
  lines2.push(
@@ -828,6 +833,7 @@ function buildRevisePrompt(ctx) {
828
833
  task,
829
834
  orient,
830
835
  widgets,
836
+ LANGUAGE_DIRECTIVE,
831
837
  "",
832
838
  "These coding guidelines apply to all code produced in this run:",
833
839
  "",
@@ -943,6 +949,7 @@ function buildReleasePrompt(ctx, baseChecks) {
943
949
  task,
944
950
  orient,
945
951
  widgets,
952
+ LANGUAGE_DIRECTIVE,
946
953
  "",
947
954
  "These coding guidelines apply to all code produced in this run:",
948
955
  "",
@@ -970,6 +977,14 @@ function buildReleasePrompt(ctx, baseChecks) {
970
977
  "```"
971
978
  );
972
979
  }
980
+ if (ctx.prerelease) {
981
+ lines2.push(
982
+ "",
983
+ "# Pre-release",
984
+ "",
985
+ "This is a PRE-RELEASE. When proposing and applying versions, use a semver pre-release version string (e.g. `0.9.0-beta.1`): take the next stable version you would otherwise pick and append `-beta.N`, where N is the next unused beta number for that version (check existing `v<version>-beta.*` tags). Offer these pre-release strings in the version-confirmation widgets, and write them to package.json, CHANGELOG.md, and the `flumecode:versions` comment as usual."
986
+ );
987
+ }
973
988
  appendThread(lines2, ctx);
974
989
  lines2.push(
975
990
  "",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flumecode/runner",
3
- "version": "0.18.0",
3
+ "version": "0.19.0",
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": {
@@ -16,9 +16,9 @@ This convention applies to all free-text fields in plans and reports: goals, ste
16
16
 
17
17
  ## Output language
18
18
 
19
- Write all free-text prose in the same natural language as the user's request
20
- (Korean in Korean out, English in English out). This applies to every
21
- free-text field you author plan goals/steps/risks, report summaries,
22
- clarifying questions, and push-backs. Keep code identifiers, file paths,
23
- commands, and quoted code/diffs verbatim; only the surrounding prose follows
24
- the request language.
19
+ Before writing anything, determine the dominant natural language of the incoming thread (the
20
+ request title/body and the user's messages). Use that one language for all free-text prose in
21
+ this run your reply body, plan goals/steps/risks, report summaries, clarifying questions,
22
+ widget options, and push-backs. Never switch languages mid-response. Keep code identifiers, file
23
+ paths, commands, and quoted code/diffs verbatim; only the surrounding prose follows the thread
24
+ language.
@@ -183,6 +183,32 @@ version did not change.
183
183
  silence them.
184
184
  - **Never commit, push, or open a PR** — the runner does that.
185
185
 
186
+ ## Pre-release
187
+
188
+ When the prompt contains a `# Pre-release` section, this release uses semver
189
+ pre-release version strings instead of stable ones:
190
+
191
+ - **Compute versions:** take the next stable version you would otherwise propose
192
+ (patch or minor bump), then append `-beta.N`, where N is the next unused beta
193
+ number for that base version. Check existing tags with:
194
+
195
+ ```
196
+ git tag -l --sort=-version:refname 'v<version>-beta.*' | head -1
197
+ ```
198
+
199
+ If no beta tags exist for that base version, start at `-beta.1`.
200
+
201
+ - **Phase 1 (propose):** offer the pre-release version string (e.g.
202
+ `0.9.0-beta.1`) in the version-confirmation widgets instead of the stable
203
+ version.
204
+
205
+ - **Phase 2 (apply):** write the pre-release version string (e.g.
206
+ `0.9.0-beta.1`) to `package.json`, `CHANGELOG.md`, and the
207
+ `<!-- flumecode:versions {...} -->` comment — exactly as you would for a
208
+ stable release, just with the pre-release suffix included.
209
+
210
+ ---
211
+
186
212
  ## Pre-release checks
187
213
 
188
214
  We cannot release code with failing checks. Before this turn, the runner ran the
@@ -108,6 +108,13 @@ own independently-acceptable "Accept as plan" draft. After a plan is accepted th
108
108
  keep commenting to refine it; treat a later turn as a fresh **Plan** phase and call
109
109
  `submit_plan` again with a `plans[]` array containing the revised fields.
110
110
 
111
+ Before adding an entry to `plans[]`, apply this right-sizing checklist — if a plan fails any criterion, split it into separate entries:
112
+
113
+ - **Single, clear outcome** — one bug fixed, one feature increment, one refactor. If the `title` needs "and", consider splitting.
114
+ - **Fits in a sprint comfortably** — if it can't fit in one iteration, it's likely an epic that needs breaking down.
115
+ - **Reviewable PR** — small enough that a reviewer can hold it in their head (often cited as under ~200–400 lines of diff, though this varies).
116
+ - **Testable acceptance criteria** — you can state up front what "done" looks like; use the `acceptanceCriteria` field to capture this.
117
+
111
118
  ## Always
112
119
 
113
120
  - Stay read-only. Propose; do not edit.