@llm4ts/shell 2.24.0 → 2.25.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/flows/lib/epic-stories.js +9 -1
- package/flows/modernize-implement.js +3 -0
- package/kits/j2ee-nextjs/README.md +12 -0
- package/kits/j2ee-nextjs/fixtures/demo-bank/RUNBOOK.md +15 -4
- package/kits/j2ee-nextjs/fixtures/demo-bank/nextjs/.nvmrc +1 -0
- package/kits/j2ee-nextjs/fixtures/demo-bank/nextjs/package.json +3 -0
- package/kits/j2ee-nextjs/fixtures/demo-bank/preflight.mjs +6 -1
- package/kits/j2ee-nextjs/flows/lib/convert.js +3 -0
- package/kits/j2ee-nextjs/scaffolds/nextjs-spa/.nvmrc +1 -0
- package/kits/j2ee-nextjs/scaffolds/nextjs-spa/package.json +3 -0
- package/package.json +4 -4
|
@@ -15,6 +15,7 @@ import { parseEpicBrief, renderEpicBrief, unanswered } from "@llm4ts/flow/EpicBr
|
|
|
15
15
|
import { structuredAndPublish } from "@llm4ts/flow/Flow";
|
|
16
16
|
import { EpicBriefInvalid, EpicBriefNotApproved, EpicCheckoutDirty, LandingFailed, RefineRefused } from "@llm4ts/flow/FlowError";
|
|
17
17
|
import { Info } from "@llm4ts/flow/FlowEvents";
|
|
18
|
+
import { nodePreflight } from "@llm4ts/flow/NodePreflight";
|
|
18
19
|
import { statusPaths } from "@llm4ts/flow/GitTool";
|
|
19
20
|
import { EpicLanded, EpicLandedVersion, landedPath } from "@llm4ts/flow/Landing";
|
|
20
21
|
import { RefineProposal, assembleRound, countNotPlanned, earlierStories, refineProposalJsonSchema, renderNotPlanned, roundPrefix, roundRepair, runAction } from "@llm4ts/flow/RefineRound";
|
|
@@ -1025,7 +1026,8 @@ export const storyContextChars = (environment) => {
|
|
|
1025
1026
|
/** Today's story judge: the rubric judge over the four dimensions. */
|
|
1026
1027
|
export const rubricStoryJudge = (context) => (story, diff, seats, subject) => judgeStory(
|
|
1027
1028
|
// The story's own seat, not the run's: its time counts for the story.
|
|
1028
|
-
|
|
1029
|
+
// And the judge seat, never the writing reasoner: a judge reads.
|
|
1030
|
+
seats.context.roster?.forRole("judge") ?? seats.context.judge ?? seats.context.reasoning, story, diff, context.budget, context.plan, subject);
|
|
1029
1031
|
/** The runner options the two flags above add; empty when neither is set. */
|
|
1030
1032
|
export const epicRunnerOptions = Effect.fn("epic-stories.runnerOptions")(function* (options, environment) {
|
|
1031
1033
|
const judgment = options.judgmentFromEnvironment === true
|
|
@@ -1237,6 +1239,12 @@ export const runEpicStories = (options) => Effect.gen(function* () {
|
|
|
1237
1239
|
? "gates: none (the app defines none of typecheck, lint, test, build; set LLM4TS_GATES)"
|
|
1238
1240
|
: `gates: ${commands.map((command) => command.join(" ")).join(" · ")}`
|
|
1239
1241
|
}));
|
|
1242
|
+
// The Node the gates would run on is the one on PATH, not the one
|
|
1243
|
+
// the application pins; a mismatch is a red first story that says
|
|
1244
|
+
// nothing about Node. Ask now, and name both.
|
|
1245
|
+
if (commands.length > 0) {
|
|
1246
|
+
yield* nodePreflight(nodeProcessExecutor, files, events, join(input.workDir, appDir), process.env);
|
|
1247
|
+
}
|
|
1240
1248
|
if (flags.land !== undefined) {
|
|
1241
1249
|
const landed = yield* landEpic(context, {
|
|
1242
1250
|
plan,
|
|
@@ -29,6 +29,7 @@ import { judgeAllPrograms } from "@llm4ts/flow/ProgramJudge";
|
|
|
29
29
|
import { Provenance, makeProvenanceStore } from "@llm4ts/flow/Provenance";
|
|
30
30
|
import { ApprovedMarker, DraftApprovalMarker, requireApproval } from "@llm4ts/flow/Approval";
|
|
31
31
|
import { loadPatternCards, taggedPatternIds } from "@llm4ts/flow/Patterns";
|
|
32
|
+
import { nodePreflight } from "@llm4ts/flow/NodePreflight";
|
|
32
33
|
import { ReviewIssue } from "@llm4ts/flow/Review";
|
|
33
34
|
import { checkWall, wallBreachMessage } from "@llm4ts/flow/Wall";
|
|
34
35
|
import { parseDecisions } from "@llm4ts/flow/Decisions";
|
|
@@ -194,6 +195,8 @@ const program = Effect.gen(function* () {
|
|
|
194
195
|
message: `no plan at ${planPath} — run modernize-seed first`
|
|
195
196
|
});
|
|
196
197
|
}
|
|
198
|
+
// The pack's gates run on the node on PATH: check it against the target's pin first.
|
|
199
|
+
yield* nodePreflight(nodeProcessExecutor, files, context.events, input.workDir, process.env);
|
|
197
200
|
const gate = (name) => {
|
|
198
201
|
const command = pack.gate(name);
|
|
199
202
|
return command === undefined
|
|
@@ -28,3 +28,15 @@ LLM4TS_LEGACY_REPO=/path/to/legacy-estate llm4ts run convert-page --pack j2ee-ne
|
|
|
28
28
|
|
|
29
29
|
The convert flows default to `j2ee-nextjs-spa`; `kits/test/packs.test.ts`
|
|
30
30
|
shows what the flows require of a manifest.
|
|
31
|
+
|
|
32
|
+
## Node for the gates
|
|
33
|
+
|
|
34
|
+
The Next.js scaffold pins Node 22 (`.nvmrc`, `package.json` `engines`). The
|
|
35
|
+
pack's gates run on the `node` on the PATH of the shell that launches
|
|
36
|
+
`llm4ts`, so `convert-*`, `modernize-implement` and `epic-stories` check it
|
|
37
|
+
against the target's pin before the first gate and stop, naming both, when
|
|
38
|
+
they disagree; `llm4ts doctor` reports the same under `gates:`. Switch Node
|
|
39
|
+
(`nvm use` / `fnm use`), or uncomment `use-node-version` in the target's
|
|
40
|
+
`.npmrc` so pnpm runs the pinned Node itself, or give the pack gates a
|
|
41
|
+
version-manager wrapper (`fnm exec --using=.nvmrc pnpm lint`). Set
|
|
42
|
+
`LLM4TS_NODE_CHECK=off` to run anyway.
|
|
@@ -18,10 +18,10 @@ node kits/j2ee-nextjs/fixtures/demo-bank/preflight.mjs
|
|
|
18
18
|
```
|
|
19
19
|
|
|
20
20
|
Preflight seeds both fixtures into a temp dir, runs their smoke checks, and
|
|
21
|
-
verifies git, pnpm, the `claude` CLI, and that the installed
|
|
22
|
-
the `j2ee-nextjs` kit with its `j2ee-nextjs-spa` pack
|
|
23
|
-
0.18.0 or newer). Fix anything red before continuing. Then
|
|
24
|
-
demo estate (pick a short path you can type on stage):
|
|
21
|
+
verifies git, Node 22 on PATH, pnpm, the `claude` CLI, and that the installed
|
|
22
|
+
`llm4ts` ships the `j2ee-nextjs` kit with its `j2ee-nextjs-spa` pack
|
|
23
|
+
(`@llm4ts/shell` 0.18.0 or newer). Fix anything red before continuing. Then
|
|
24
|
+
materialize the demo estate (pick a short path you can type on stage):
|
|
25
25
|
|
|
26
26
|
```bash
|
|
27
27
|
node kits/j2ee-nextjs/fixtures/demo-bank/reset-demo.mjs ~/demo
|
|
@@ -32,6 +32,17 @@ warms the target's node_modules from the pnpm store (documented offline
|
|
|
32
32
|
strategy: the lockfile is committed; run it once on hotel wifi, never on
|
|
33
33
|
stage). Finally: `cd ~/demo/nextjs && pnpm test` must be green.
|
|
34
34
|
|
|
35
|
+
**Node for the gates.** The target pins Node 22 (`.nvmrc`, `package.json`
|
|
36
|
+
`engines`). Gates run on the `node` found on the PATH of the shell that
|
|
37
|
+
launches `llm4ts`, so every gated flow checks that node against the pin
|
|
38
|
+
before its first gate and stops with both versions named when they
|
|
39
|
+
disagree (`llm4ts doctor` shows the same line under `gates:`). On a machine
|
|
40
|
+
whose Node you cannot switch (`nvm use 22` / `fnm use 22`), uncomment
|
|
41
|
+
`use-node-version` in the target's `.npmrc` so pnpm fetches and runs that
|
|
42
|
+
Node itself (one download, then offline), or wrap the pack's gate commands
|
|
43
|
+
in a version manager (`fnm exec --using=.nvmrc pnpm lint` works as a gate
|
|
44
|
+
line, since gates are plain argv). `LLM4TS_NODE_CHECK=off` skips the check.
|
|
45
|
+
|
|
35
46
|
Timing bounds for the day (set in the environment you run flows from):
|
|
36
47
|
|
|
37
48
|
```bash
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
22
|
|
@@ -23,7 +23,12 @@ const tool = (label, command, args) =>
|
|
|
23
23
|
check(label, () => execFileSync(command, args, { stdio: "pipe" }))
|
|
24
24
|
|
|
25
25
|
tool("git available", "git", ["--version"])
|
|
26
|
-
|
|
26
|
+
check("node >= 22 (the fixtures pin it in .nvmrc and engines)", () => {
|
|
27
|
+
const version = execFileSync("node", ["--version"], { encoding: "utf8" }).trim()
|
|
28
|
+
if (Number(version.replace(/^v/, "").split(".")[0]) < 22) {
|
|
29
|
+
throw new Error(`${version} on PATH; the gates need Node 22 (nvm use 22 / fnm use 22)`)
|
|
30
|
+
}
|
|
31
|
+
})
|
|
27
32
|
tool("pnpm available", "pnpm", ["--version"])
|
|
28
33
|
tool("claude CLI available (the coder seat)", "claude", ["--version"])
|
|
29
34
|
check("llm4ts CLI available", () => execFileSync("llm4ts", ["--version"], { stdio: "pipe" }))
|
|
@@ -14,6 +14,7 @@ import { budget, capped } from "@llm4ts/flow/Context";
|
|
|
14
14
|
import { Decisions, parseDecisions } from "@llm4ts/flow/Decisions";
|
|
15
15
|
import { navigationOrder, parseDomains } from "@llm4ts/flow/Domains";
|
|
16
16
|
import { FlowEvents } from "@llm4ts/flow/FlowEvents";
|
|
17
|
+
import { nodePreflight } from "@llm4ts/flow/NodePreflight";
|
|
17
18
|
import { openApiFor, openApiForFeature, parsePageSpec, renderPageSpec } from "@llm4ts/flow/PageSpec";
|
|
18
19
|
import { loadPatternCards, matchingPatternCards } from "@llm4ts/flow/Patterns";
|
|
19
20
|
import { Task } from "@llm4ts/flow/Plan";
|
|
@@ -554,6 +555,8 @@ export const setupConversion = Effect.fn("convert.setup")(function* (context, in
|
|
|
554
555
|
};
|
|
555
556
|
const legacy = yield* makeNodeWorkspace(legacyDir, workspaceLimitsFromEnv(environment, legacySourceWorkspaceLimits));
|
|
556
557
|
const target = yield* makeNodeWorkspace(input.workDir);
|
|
558
|
+
// The pack's gates run on the node on PATH: check it against the target's pin first.
|
|
559
|
+
yield* nodePreflight(nodeProcessExecutor, nodePlainFileStore, context.events, input.workDir, environment);
|
|
557
560
|
const opened = yield* stage(context.events, "pack", openPack({
|
|
558
561
|
environment: {
|
|
559
562
|
...environment,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
22
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@llm4ts/shell",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.25.0",
|
|
4
4
|
"description": "Interactive shell and CLI for llm4ts: flow discovery, run-a-flow, and view",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -52,9 +52,9 @@
|
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"@effect/platform-node": "4.0.0",
|
|
54
54
|
"@effect/platform-node-shared": "4.0.0",
|
|
55
|
-
"@llm4ts/core": "2.
|
|
56
|
-
"@llm4ts/flow": "2.
|
|
57
|
-
"@llm4ts/runner": "2.
|
|
55
|
+
"@llm4ts/core": "2.25.0",
|
|
56
|
+
"@llm4ts/flow": "2.25.0",
|
|
57
|
+
"@llm4ts/runner": "2.25.0"
|
|
58
58
|
},
|
|
59
59
|
"peerDependencies": {
|
|
60
60
|
"effect": "4.0.0"
|