@llm4ts/shell 0.5.0 → 0.6.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.d.ts.map +1 -1
- package/dist/Cli.js +5 -1
- package/dist/Cli.js.map +1 -1
- package/flows/fixtures/scaffolds/kafka-streams-service/README.md +12 -0
- package/flows/fixtures/scaffolds/kafka-streams-service/pom.xml +49 -0
- package/flows/fixtures/scaffolds/kafka-streams-service/scripts/replay.sh +10 -0
- package/flows/fixtures/scaffolds/kafka-streams-service/src/main/java/com/meridian/scaffold/Application.java +29 -0
- package/flows/fixtures/scaffolds/kafka-streams-service/src/test/java/com/meridian/scaffold/ApplicationTests.java +21 -0
- package/flows/fixtures/scaffolds/kafka-streams-service/src/test/resources/features/.gitkeep +0 -0
- package/flows/fixtures/scaffolds/nextjs-spa/README.md +6 -0
- package/flows/fixtures/scaffolds/nextjs-spa/app/layout.js +11 -0
- package/flows/fixtures/scaffolds/nextjs-spa/app/page.js +7 -0
- package/flows/fixtures/scaffolds/nextjs-spa/docs/specs/.gitkeep +0 -0
- package/flows/fixtures/scaffolds/nextjs-spa/features/.gitkeep +0 -0
- package/flows/fixtures/scaffolds/nextjs-spa/next.config.js +7 -0
- package/flows/fixtures/scaffolds/nextjs-spa/package.json +15 -0
- package/flows/fixtures/scaffolds/nextjs-spa/tests/smoke.test.js +6 -0
- package/flows/fixtures/scaffolds/spring-bff/README.md +9 -0
- package/flows/fixtures/scaffolds/spring-bff/frontend/app/layout.js +11 -0
- package/flows/fixtures/scaffolds/spring-bff/frontend/app/page.js +7 -0
- package/flows/fixtures/scaffolds/spring-bff/frontend/next.config.js +7 -0
- package/flows/fixtures/scaffolds/spring-bff/frontend/package.json +15 -0
- package/flows/fixtures/scaffolds/spring-bff/frontend/tests/smoke.test.js +6 -0
- package/flows/fixtures/scaffolds/spring-bff/pom.xml +57 -0
- package/flows/fixtures/scaffolds/spring-bff/scripts/test.sh +6 -0
- package/flows/fixtures/scaffolds/spring-bff/src/main/java/com/meridian/bff/Application.java +12 -0
- package/flows/fixtures/scaffolds/spring-bff/src/main/resources/application.yaml +12 -0
- package/flows/fixtures/scaffolds/spring-bff/src/test/java/com/meridian/bff/ApplicationTests.java +12 -0
- package/flows/fixtures/scaffolds/spring-bff/src/test/resources/features/.gitkeep +0 -0
- package/flows/fixtures/scaffolds/spring-boot-service/README.md +7 -0
- package/flows/fixtures/scaffolds/spring-boot-service/pom.xml +53 -0
- package/flows/fixtures/scaffolds/spring-boot-service/scripts/replay.sh +9 -0
- package/flows/fixtures/scaffolds/spring-boot-service/src/main/java/com/meridian/scaffold/Application.java +12 -0
- package/flows/fixtures/scaffolds/spring-boot-service/src/main/resources/application.yaml +12 -0
- package/flows/fixtures/scaffolds/spring-boot-service/src/test/java/com/meridian/scaffold/ApplicationTests.java +12 -0
- package/flows/fixtures/scaffolds/spring-boot-service/src/test/resources/features/.gitkeep +0 -0
- package/flows/modernize-bench.ts +10 -4
- package/flows/modernize-extract.ts +17 -8
- package/flows/modernize-implement.ts +13 -6
- package/flows/modernize-review.ts +14 -6
- package/flows/modernize-seed.ts +12 -5
- package/flows/modernize-survey.ts +0 -0
- package/flows/modernize-verify.ts +11 -4
- package/flows/packs/ace-integration/lessons.md +6 -0
- package/flows/packs/ace-integration/pack.md +29 -0
- package/flows/packs/ace-integration/prompts/analysis.md +21 -0
- package/flows/packs/ace-integration/prompts/bdd.md +13 -0
- package/flows/packs/ace-integration/prompts/implement.md +17 -0
- package/flows/packs/ace-integration/prompts/plan.md +12 -0
- package/flows/packs/ace-integration/prompts/review.md +17 -0
- package/flows/packs/ace-integration/prompts/spec.md +29 -0
- package/flows/packs/ace-integration/reviewers/routing-fidelity.md +19 -0
- package/flows/packs/ace-integration/reviewers/traceability.md +13 -0
- package/flows/packs/ace-kafka/lessons.md +6 -0
- package/flows/packs/ace-kafka/pack.md +36 -0
- package/flows/packs/ace-kafka/prompts/analysis.md +21 -0
- package/flows/packs/ace-kafka/prompts/bdd.md +13 -0
- package/flows/packs/ace-kafka/prompts/implement.md +34 -0
- package/flows/packs/ace-kafka/prompts/plan.md +12 -0
- package/flows/packs/ace-kafka/prompts/review.md +17 -0
- package/flows/packs/ace-kafka/prompts/spec.md +31 -0
- package/flows/packs/ace-kafka/prompts/vectors.md +21 -0
- package/flows/packs/ace-kafka/reviewers/event-contracts.md +9 -0
- package/flows/packs/ace-kafka/reviewers/routing-fidelity.md +19 -0
- package/flows/packs/ace-kafka/reviewers/traceability.md +13 -0
- package/flows/packs/cobol-kafka/lessons.md +3 -0
- package/flows/packs/cobol-kafka/pack.md +51 -0
- package/flows/packs/cobol-kafka/patterns/PAT-STREAM-001-record-to-event.md +7 -0
- package/flows/packs/cobol-kafka/patterns/PAT-STREAM-002-job-step-topology.md +6 -0
- package/flows/packs/cobol-kafka/patterns/PAT-STREAM-003-checkpoint-idempotence.md +7 -0
- package/flows/packs/cobol-kafka/patterns/PAT-STREAM-004-eod-totals-window.md +7 -0
- package/flows/packs/cobol-kafka/patterns/PAT-STREAM-005-reject-topic.md +6 -0
- package/flows/packs/cobol-kafka/patterns/PAT-STREAM-006-keyed-state-store.md +7 -0
- package/flows/packs/cobol-kafka/patterns/PAT-STREAM-007-outbox.md +7 -0
- package/flows/packs/cobol-kafka/patterns/PAT-STREAM-008-partition-key.md +7 -0
- package/flows/packs/cobol-kafka/patterns/PAT-STREAM-009-batch-window-cutoff.md +7 -0
- package/flows/packs/cobol-kafka/patterns/PAT-STREAM-010-replay-backfill.md +7 -0
- package/flows/packs/cobol-kafka/prompts/analysis.md +23 -0
- package/flows/packs/cobol-kafka/prompts/bdd.md +15 -0
- package/flows/packs/cobol-kafka/prompts/implement.md +47 -0
- package/flows/packs/cobol-kafka/prompts/plan.md +13 -0
- package/flows/packs/cobol-kafka/prompts/review.md +17 -0
- package/flows/packs/cobol-kafka/prompts/spec.md +28 -0
- package/flows/packs/cobol-kafka/prompts/vectors.md +21 -0
- package/flows/packs/cobol-kafka/reviewers/cobol-fidelity.md +16 -0
- package/flows/packs/cobol-kafka/reviewers/pattern-conformance.md +10 -0
- package/flows/packs/cobol-kafka/reviewers/traceability.md +13 -0
- package/flows/packs/cobol-springboot/lessons.md +3 -0
- package/flows/packs/cobol-springboot/pack.md +51 -0
- package/flows/packs/cobol-springboot/prompts/analysis.md +23 -0
- package/flows/packs/cobol-springboot/prompts/bdd.md +15 -0
- package/flows/packs/cobol-springboot/prompts/implement.md +31 -0
- package/flows/packs/cobol-springboot/prompts/plan.md +13 -0
- package/flows/packs/cobol-springboot/prompts/review.md +17 -0
- package/flows/packs/cobol-springboot/prompts/spec.md +28 -0
- package/flows/packs/cobol-springboot/prompts/vectors.md +22 -0
- package/flows/packs/cobol-springboot/reviewers/cobol-fidelity.md +16 -0
- package/flows/packs/cobol-springboot/reviewers/pattern-conformance.md +10 -0
- package/flows/packs/cobol-springboot/reviewers/traceability.md +13 -0
- package/flows/packs/jsp-bff-nextjs/lessons.md +6 -0
- package/flows/packs/jsp-bff-nextjs/pack.md +30 -0
- package/flows/packs/jsp-bff-nextjs/prompts/analysis.md +20 -0
- package/flows/packs/jsp-bff-nextjs/prompts/bdd.md +10 -0
- package/flows/packs/jsp-bff-nextjs/prompts/implement.md +17 -0
- package/flows/packs/jsp-bff-nextjs/prompts/plan.md +12 -0
- package/flows/packs/jsp-bff-nextjs/prompts/review.md +16 -0
- package/flows/packs/jsp-bff-nextjs/prompts/spec.md +27 -0
- package/flows/packs/jsp-bff-nextjs/reviewers/bff-boundary.md +18 -0
- package/flows/packs/jsp-bff-nextjs/reviewers/traceability.md +13 -0
- package/flows/packs/jsp-nextjs/lessons.md +6 -0
- package/flows/packs/jsp-nextjs/pack.md +29 -0
- package/flows/packs/jsp-nextjs/prompts/analysis.md +21 -0
- package/flows/packs/jsp-nextjs/prompts/bdd.md +12 -0
- package/flows/packs/jsp-nextjs/prompts/implement.md +17 -0
- package/flows/packs/jsp-nextjs/prompts/plan.md +14 -0
- package/flows/packs/jsp-nextjs/prompts/review.md +16 -0
- package/flows/packs/jsp-nextjs/prompts/spec.md +26 -0
- package/flows/packs/jsp-nextjs/reviewers/traceability.md +13 -0
- package/flows/packs/jsp-nextjs/reviewers/ux-fidelity.md +16 -0
- package/flows/patterns/PAT-COBOL-001-comp3-money.md +7 -0
- package/flows/patterns/PAT-COBOL-002-redefines.md +7 -0
- package/flows/patterns/PAT-COBOL-003-88-levels.md +7 -0
- package/flows/patterns/PAT-COBOL-004-perform-thru.md +7 -0
- package/flows/patterns/PAT-COBOL-005-file-status.md +6 -0
- package/flows/patterns/PAT-COBOL-006-sqlcode.md +7 -0
- package/flows/patterns/PAT-COBOL-007-validation-order.md +7 -0
- package/flows/patterns/PAT-COBOL-008-zoned-decimal.md +6 -0
- package/flows/patterns/PAT-COBOL-009-occurs-table.md +6 -0
- package/flows/patterns/PAT-COBOL-010-copybook-record.md +7 -0
- package/flows/patterns/PAT-COBOL-011-batch-counters.md +6 -0
- package/flows/patterns/PAT-COBOL-012-commit-frequency.md +7 -0
- package/flows/patterns/PAT-COBOL-013-abend.md +6 -0
- package/flows/patterns/PAT-COBOL-014-reject-file.md +6 -0
- package/flows/patterns/PAT-COBOL-015-accept-date.md +6 -0
- package/flows/patterns/PAT-COBOL-016-string-building.md +6 -0
- package/flows/patterns/PAT-COBOL-017-cursor-loop.md +6 -0
- package/flows/patterns/PAT-COBOL-018-yn-switches.md +6 -0
- package/flows/patterns/PAT-COBOL-019-shared-accumulators.md +6 -0
- package/flows/patterns/PAT-COBOL-020-tiered-fees.md +7 -0
- package/flows/patterns/PAT-COBOL-021-overdraft-floor.md +7 -0
- package/flows/patterns/PAT-COBOL-022-jcl-job-net.md +6 -0
- package/flows/patterns/PAT-COBOL-023-sort-step.md +6 -0
- package/flows/patterns/PAT-COBOL-024-fixed-width-records.md +6 -0
- package/flows/patterns/PAT-COBOL-025-audit-rows.md +6 -0
- package/package.json +5 -4
- package/src/Cli.ts +10 -1
|
@@ -19,8 +19,9 @@
|
|
|
19
19
|
// `- [ ] Approved` marker in `docs/modernization/README.md`.
|
|
20
20
|
//
|
|
21
21
|
// Pack: LLM4TS_PACK=<dir> (default packs/cobol-springboot, resolved against the
|
|
22
|
-
// launch dir
|
|
23
|
-
//
|
|
22
|
+
// launch dir, then against the flow's own directory — the built-in packs).
|
|
23
|
+
// LLM4TS_WAVE=<name> scopes the run to one wave of the approved plan. Judge
|
|
24
|
+
// context is bounded by LLM4TS_JUDGE_SOURCES_LIMIT (chars).
|
|
24
25
|
import { join } from "node:path"
|
|
25
26
|
import * as Effect from "effect/Effect"
|
|
26
27
|
import { Sample, type EvalResult } from "@llm4ts/core/eval/Eval"
|
|
@@ -29,7 +30,7 @@ import type { JsonSchema } from "@llm4ts/core/Models"
|
|
|
29
30
|
import { FlowAborted, FlowLlmError } from "@llm4ts/flow/FlowError"
|
|
30
31
|
import { Info } from "@llm4ts/flow/FlowEvents"
|
|
31
32
|
import { makeChat } from "@llm4ts/flow/Chat"
|
|
32
|
-
import {
|
|
33
|
+
import type { Pack } from "@llm4ts/flow/Pack"
|
|
33
34
|
import { loadPatternCards, matchingPatternCards } from "@llm4ts/flow/Patterns"
|
|
34
35
|
import { stage } from "@llm4ts/flow/PlanExecution"
|
|
35
36
|
import { defaultPlanInstructions, planFrom } from "@llm4ts/flow/Planner"
|
|
@@ -48,6 +49,7 @@ import { runFlowMain, runNode } from "@llm4ts/runner/FlowRunner"
|
|
|
48
49
|
import { reviewFingerprint } from "@llm4ts/runner/ReviewFingerprint"
|
|
49
50
|
import { nodePlainFileStore } from "@llm4ts/runner/NodePlainFileStore"
|
|
50
51
|
import { makeNodeWorkspace } from "@llm4ts/runner/NodeWorkspace"
|
|
52
|
+
import { loadUniversalPatternCards, openPack } from "@llm4ts/runner/Packs"
|
|
51
53
|
|
|
52
54
|
const ModDir = "docs/modernization"
|
|
53
55
|
const MaxRounds = 3
|
|
@@ -202,7 +204,6 @@ const program = Effect.gen(function* () {
|
|
|
202
204
|
const input = yield* resolveFlowInput(
|
|
203
205
|
"Extract the complete behavioural spec pack for this legacy estate"
|
|
204
206
|
)
|
|
205
|
-
const packDir = process.env.LLM4TS_PACK ?? "packs/cobol-springboot"
|
|
206
207
|
const coder = coderFromEnv(process.env)
|
|
207
208
|
const files = nodePlainFileStore
|
|
208
209
|
const modDirAbs = join(input.workDir, ModDir)
|
|
@@ -218,9 +219,17 @@ const program = Effect.gen(function* () {
|
|
|
218
219
|
},
|
|
219
220
|
(context) =>
|
|
220
221
|
Effect.gen(function* () {
|
|
221
|
-
const launchWorkspace = yield* makeNodeWorkspace(input.workspace)
|
|
222
222
|
const repo = yield* makeNodeWorkspace(input.workDir)
|
|
223
|
-
const
|
|
223
|
+
const opened = yield* stage(
|
|
224
|
+
context.events,
|
|
225
|
+
"pack",
|
|
226
|
+
openPack({
|
|
227
|
+
environment: process.env,
|
|
228
|
+
launchDir: input.workspace,
|
|
229
|
+
flowDir: import.meta.dirname
|
|
230
|
+
})
|
|
231
|
+
)
|
|
232
|
+
const pack = opened.pack
|
|
224
233
|
yield* stage(
|
|
225
234
|
context.events,
|
|
226
235
|
"branch",
|
|
@@ -273,8 +282,8 @@ const program = Effect.gen(function* () {
|
|
|
273
282
|
// Pattern cards are selected deterministically from the SOURCE, never by
|
|
274
283
|
// the model: implementation later injects exactly the cards cited here.
|
|
275
284
|
const cards = [
|
|
276
|
-
...(yield* loadPatternCards(
|
|
277
|
-
...(yield*
|
|
285
|
+
...(yield* loadPatternCards(opened.workspace, `${opened.dir}/patterns`)),
|
|
286
|
+
...(yield* loadUniversalPatternCards([input.workspace, import.meta.dirname]))
|
|
278
287
|
]
|
|
279
288
|
|
|
280
289
|
// One structured analyst call per program, resumable per program: a rerun
|
|
@@ -25,7 +25,6 @@ import { judge } from "@llm4ts/core/eval/Judge"
|
|
|
25
25
|
import { makeChat } from "@llm4ts/flow/Chat"
|
|
26
26
|
import { FlowAborted, FlowLlmError, type FlowError } from "@llm4ts/flow/FlowError"
|
|
27
27
|
import { Info } from "@llm4ts/flow/FlowEvents"
|
|
28
|
-
import { loadPack } from "@llm4ts/flow/Pack"
|
|
29
28
|
import { loadPatternCards, taggedPatternIds } from "@llm4ts/flow/Patterns"
|
|
30
29
|
import { makePlanStore } from "@llm4ts/flow/Persistence"
|
|
31
30
|
import { implementTaskLoop, stage } from "@llm4ts/flow/PlanExecution"
|
|
@@ -44,6 +43,7 @@ import { runFlowMain, runNode } from "@llm4ts/runner/FlowRunner"
|
|
|
44
43
|
import { nodePlainFileStore } from "@llm4ts/runner/NodePlainFileStore"
|
|
45
44
|
import { nodeProcessExecutor } from "@llm4ts/runner/NodeProcessExecutor"
|
|
46
45
|
import { makeNodeWorkspace } from "@llm4ts/runner/NodeWorkspace"
|
|
46
|
+
import { loadUniversalPatternCards, openPack } from "@llm4ts/runner/Packs"
|
|
47
47
|
|
|
48
48
|
const ModDir = "docs/modernization"
|
|
49
49
|
|
|
@@ -87,7 +87,6 @@ const issueText = (issues: ReadonlyArray<ReviewIssue>): string =>
|
|
|
87
87
|
|
|
88
88
|
const program = Effect.gen(function* () {
|
|
89
89
|
const input = yield* resolveFlowInput("Implement the seeded modernization plan")
|
|
90
|
-
const packDir = process.env.LLM4TS_PACK ?? "packs/cobol-springboot"
|
|
91
90
|
const coder = coderFromEnv(process.env)
|
|
92
91
|
const files = nodePlainFileStore
|
|
93
92
|
const planPath = join(input.workDir, ModDir, "plan.md")
|
|
@@ -104,9 +103,17 @@ const program = Effect.gen(function* () {
|
|
|
104
103
|
},
|
|
105
104
|
(context) =>
|
|
106
105
|
Effect.gen(function* () {
|
|
107
|
-
const launchWorkspace = yield* makeNodeWorkspace(input.workspace)
|
|
108
106
|
const target = yield* makeNodeWorkspace(input.workDir)
|
|
109
|
-
const
|
|
107
|
+
const opened = yield* stage(
|
|
108
|
+
context.events,
|
|
109
|
+
"pack",
|
|
110
|
+
openPack({
|
|
111
|
+
environment: process.env,
|
|
112
|
+
launchDir: input.workspace,
|
|
113
|
+
flowDir: import.meta.dirname
|
|
114
|
+
})
|
|
115
|
+
)
|
|
116
|
+
const pack = opened.pack
|
|
110
117
|
|
|
111
118
|
yield* stage(
|
|
112
119
|
context.events,
|
|
@@ -161,8 +168,8 @@ const program = Effect.gen(function* () {
|
|
|
161
168
|
// ids, and only the cited cards reach the brief.
|
|
162
169
|
const specText = yield* gatherSpecs(target, pack.specsDir)
|
|
163
170
|
const cards = [
|
|
164
|
-
...(yield* loadPatternCards(
|
|
165
|
-
...(yield*
|
|
171
|
+
...(yield* loadPatternCards(opened.workspace, `${opened.dir}/patterns`)),
|
|
172
|
+
...(yield* loadUniversalPatternCards([input.workspace, import.meta.dirname]))
|
|
166
173
|
]
|
|
167
174
|
const cited = new Set(taggedPatternIds(specText))
|
|
168
175
|
const playbook = cards.filter((card) => cited.has(card.id))
|
|
@@ -22,7 +22,7 @@ import { judge } from "@llm4ts/core/eval/Judge"
|
|
|
22
22
|
import type { JsonSchema } from "@llm4ts/core/Models"
|
|
23
23
|
import { FlowAborted, FlowLlmError } from "@llm4ts/flow/FlowError"
|
|
24
24
|
import { Info } from "@llm4ts/flow/FlowEvents"
|
|
25
|
-
import { appendPackLesson,
|
|
25
|
+
import { appendPackLesson, type Pack } from "@llm4ts/flow/Pack"
|
|
26
26
|
import { makePlanStore } from "@llm4ts/flow/Persistence"
|
|
27
27
|
import { Plan, Task } from "@llm4ts/flow/Plan"
|
|
28
28
|
import { stage } from "@llm4ts/flow/PlanExecution"
|
|
@@ -40,6 +40,7 @@ import { resolveFlowInput } from "@llm4ts/runner/FlowArgs"
|
|
|
40
40
|
import { runFlowMain, runNode } from "@llm4ts/runner/FlowRunner"
|
|
41
41
|
import { nodePlainFileStore } from "@llm4ts/runner/NodePlainFileStore"
|
|
42
42
|
import { makeNodeWorkspace } from "@llm4ts/runner/NodeWorkspace"
|
|
43
|
+
import { openPack } from "@llm4ts/runner/Packs"
|
|
43
44
|
|
|
44
45
|
const ModDir = "docs/modernization"
|
|
45
46
|
|
|
@@ -146,7 +147,6 @@ const distillPrompt = (
|
|
|
146
147
|
|
|
147
148
|
const program = Effect.gen(function* () {
|
|
148
149
|
const input = yield* resolveFlowInput("Review the modernization increment against its spec pack")
|
|
149
|
-
const packDir = process.env.LLM4TS_PACK ?? "packs/cobol-springboot"
|
|
150
150
|
const coder = coderFromEnv(process.env)
|
|
151
151
|
const files = nodePlainFileStore
|
|
152
152
|
const planPath = join(input.workDir, ModDir, "plan.md")
|
|
@@ -163,9 +163,17 @@ const program = Effect.gen(function* () {
|
|
|
163
163
|
},
|
|
164
164
|
(context) =>
|
|
165
165
|
Effect.gen(function* () {
|
|
166
|
-
const launchWorkspace = yield* makeNodeWorkspace(input.workspace)
|
|
167
166
|
const target = yield* makeNodeWorkspace(input.workDir)
|
|
168
|
-
const
|
|
167
|
+
const opened = yield* stage(
|
|
168
|
+
context.events,
|
|
169
|
+
"pack",
|
|
170
|
+
openPack({
|
|
171
|
+
environment: process.env,
|
|
172
|
+
launchDir: input.workspace,
|
|
173
|
+
flowDir: import.meta.dirname
|
|
174
|
+
})
|
|
175
|
+
)
|
|
176
|
+
const pack = opened.pack
|
|
169
177
|
const reviewService = context.reviewers[0] ?? context.reasoning
|
|
170
178
|
|
|
171
179
|
yield* stage(
|
|
@@ -307,12 +315,12 @@ const program = Effect.gen(function* () {
|
|
|
307
315
|
)
|
|
308
316
|
}
|
|
309
317
|
for (const lesson of outcome.lessons) {
|
|
310
|
-
yield* appendPackLesson(
|
|
318
|
+
yield* appendPackLesson(opened.workspace, opened.dir, lesson)
|
|
311
319
|
}
|
|
312
320
|
yield* context.events.publish(
|
|
313
321
|
Info.make({
|
|
314
322
|
message:
|
|
315
|
-
`${outcome.lessons.length} lesson(s) appended to ${
|
|
323
|
+
`${outcome.lessons.length} lesson(s) appended to ${opened.dir}/lessons.md — ` +
|
|
316
324
|
"review and commit the pack change"
|
|
317
325
|
})
|
|
318
326
|
)
|
package/flows/modernize-seed.ts
CHANGED
|
@@ -24,7 +24,6 @@ import * as Schema from "effect/Schema"
|
|
|
24
24
|
import { FlowAborted, PersistenceError } from "@llm4ts/flow/FlowError"
|
|
25
25
|
import { Info } from "@llm4ts/flow/FlowEvents"
|
|
26
26
|
import { packageVersion } from "@llm4ts/flow/Package"
|
|
27
|
-
import { loadPack } from "@llm4ts/flow/Pack"
|
|
28
27
|
import { parsePlan } from "@llm4ts/flow/Plan"
|
|
29
28
|
import { stage } from "@llm4ts/flow/PlanExecution"
|
|
30
29
|
import { Provenance, makeProvenanceStore } from "@llm4ts/flow/Provenance"
|
|
@@ -36,6 +35,7 @@ import { resolveFlowInput } from "@llm4ts/runner/FlowArgs"
|
|
|
36
35
|
import { runFlowMain, runNode } from "@llm4ts/runner/FlowRunner"
|
|
37
36
|
import { nodePlainFileStore } from "@llm4ts/runner/NodePlainFileStore"
|
|
38
37
|
import { makeNodeWorkspace } from "@llm4ts/runner/NodeWorkspace"
|
|
38
|
+
import { openPack } from "@llm4ts/runner/Packs"
|
|
39
39
|
|
|
40
40
|
const ModDir = "docs/modernization"
|
|
41
41
|
const skipped = new Set([".git", "target", "node_modules", "dist"])
|
|
@@ -84,7 +84,6 @@ const copyFile = Effect.fn("modernize-seed.copyFile")(function* (
|
|
|
84
84
|
|
|
85
85
|
const program = Effect.gen(function* () {
|
|
86
86
|
const input = yield* resolveFlowInput("Seed the target repository from the approved spec pack")
|
|
87
|
-
const packDir = process.env.LLM4TS_PACK ?? "packs/cobol-springboot"
|
|
88
87
|
const legacyRepo = process.env.LLM4TS_LEGACY_REPO?.trim()
|
|
89
88
|
const files = nodePlainFileStore
|
|
90
89
|
|
|
@@ -106,10 +105,18 @@ const program = Effect.gen(function* () {
|
|
|
106
105
|
"set LLM4TS_LEGACY_REPO to the legacy repository holding the approved spec pack"
|
|
107
106
|
})
|
|
108
107
|
}
|
|
109
|
-
const launchWorkspace = yield* makeNodeWorkspace(input.workspace)
|
|
110
108
|
const legacy = yield* makeNodeWorkspace(legacyRepo)
|
|
111
109
|
const target = yield* makeNodeWorkspace(input.workDir)
|
|
112
|
-
const
|
|
110
|
+
const opened = yield* stage(
|
|
111
|
+
context.events,
|
|
112
|
+
"pack",
|
|
113
|
+
openPack({
|
|
114
|
+
environment: process.env,
|
|
115
|
+
launchDir: input.workspace,
|
|
116
|
+
flowDir: import.meta.dirname
|
|
117
|
+
})
|
|
118
|
+
)
|
|
119
|
+
const pack = opened.pack
|
|
113
120
|
const specPackRoot = join(legacyRepo, ModDir)
|
|
114
121
|
|
|
115
122
|
yield* stage(
|
|
@@ -138,7 +145,7 @@ const program = Effect.gen(function* () {
|
|
|
138
145
|
}
|
|
139
146
|
// The scaffold path is relative to the pack directory.
|
|
140
147
|
const scaffoldRoot = join(pack.dir, pack.scaffold)
|
|
141
|
-
const scaffold = yield* makeNodeWorkspace(join(
|
|
148
|
+
const scaffold = yield* makeNodeWorkspace(join(opened.workspace.root, scaffoldRoot))
|
|
142
149
|
const paths = (yield* scaffold.discover()).filter((path) => !isLitter(path))
|
|
143
150
|
for (const path of paths) {
|
|
144
151
|
yield* target.write(path, yield* scaffold.read(path))
|
|
Binary file
|
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
import { renderEquivReport, VectorVerdict } from "@llm4ts/flow/EquivReport"
|
|
35
35
|
import { FlowAborted, FlowLlmError, PlanParseError } from "@llm4ts/flow/FlowError"
|
|
36
36
|
import { Info } from "@llm4ts/flow/FlowEvents"
|
|
37
|
-
import {
|
|
37
|
+
import type { Pack } from "@llm4ts/flow/Pack"
|
|
38
38
|
import { makePlanStore } from "@llm4ts/flow/Persistence"
|
|
39
39
|
import { stage } from "@llm4ts/flow/PlanExecution"
|
|
40
40
|
import { Plan, Task } from "@llm4ts/flow/Plan"
|
|
@@ -49,6 +49,7 @@ import { runFlowMain, runNode } from "@llm4ts/runner/FlowRunner"
|
|
|
49
49
|
import { nodePlainFileStore } from "@llm4ts/runner/NodePlainFileStore"
|
|
50
50
|
import { nodeProcessExecutor } from "@llm4ts/runner/NodeProcessExecutor"
|
|
51
51
|
import { makeNodeWorkspace } from "@llm4ts/runner/NodeWorkspace"
|
|
52
|
+
import { openPack } from "@llm4ts/runner/Packs"
|
|
52
53
|
|
|
53
54
|
const ModDir = "docs/modernization"
|
|
54
55
|
|
|
@@ -278,7 +279,6 @@ const specPrograms = Effect.fn("modernize-verify.specPrograms")(function* (
|
|
|
278
279
|
|
|
279
280
|
const program = Effect.gen(function* () {
|
|
280
281
|
const input = yield* resolveFlowInput("Prove the implementation equivalent to its spec pack")
|
|
281
|
-
const packDir = process.env.LLM4TS_PACK ?? "packs/cobol-springboot"
|
|
282
282
|
const coder = coderFromEnv(process.env)
|
|
283
283
|
const files = nodePlainFileStore
|
|
284
284
|
const planPath = join(input.workDir, ModDir, "plan.md")
|
|
@@ -295,9 +295,16 @@ const program = Effect.gen(function* () {
|
|
|
295
295
|
},
|
|
296
296
|
(context) =>
|
|
297
297
|
Effect.gen(function* () {
|
|
298
|
-
const launchWorkspace = yield* makeNodeWorkspace(input.workspace)
|
|
299
298
|
const target = yield* makeNodeWorkspace(input.workDir)
|
|
300
|
-
const pack = yield* stage(
|
|
299
|
+
const { pack } = yield* stage(
|
|
300
|
+
context.events,
|
|
301
|
+
"pack",
|
|
302
|
+
openPack({
|
|
303
|
+
environment: process.env,
|
|
304
|
+
launchDir: input.workspace,
|
|
305
|
+
flowDir: import.meta.dirname
|
|
306
|
+
})
|
|
307
|
+
)
|
|
301
308
|
|
|
302
309
|
yield* stage(
|
|
303
310
|
context.events,
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
- ESQL routing ladders are business policy tables in disguise: extract them into the
|
|
2
|
+
spec AS TABLES and keep them as declarative data in the target service — once they
|
|
3
|
+
dissolve into nested ifs, nobody can verify them against the source again.
|
|
4
|
+
- MQ failure terminals and reject queues are part of the contract: every failure
|
|
5
|
+
path in the msgflow needs a spec rule and a scenario, or it silently disappears in
|
|
6
|
+
the port.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Pack: ace-integration
|
|
2
|
+
|
|
3
|
+
source: ace
|
|
4
|
+
scaffold: ../../fixtures/scaffolds/spring-boot-service
|
|
5
|
+
sources: .*\.(msgflow|esql)
|
|
6
|
+
specs-dir: docs/specs
|
|
7
|
+
features-dir: src/test/resources/features
|
|
8
|
+
|
|
9
|
+
## Gates
|
|
10
|
+
|
|
11
|
+
- build: mvn -q -B test-compile
|
|
12
|
+
- test: mvn -q -B test
|
|
13
|
+
- verify: mvn -q -B verify
|
|
14
|
+
|
|
15
|
+
## Judge
|
|
16
|
+
|
|
17
|
+
- completeness (0..2): Every node in the message flow, every routing rule, validation, reject code, queue interface, message mapping, and threshold/flag in the msgflow/ESQL source is captured in the specs and BDD scenarios; the traceability matrix accounts for every flow node and ESQL module. Score 2 only if nothing material is missing.
|
|
18
|
+
- faithfulness (0..2): Every statement is grounded in the source: reject codes, routing predicates, currency lists, thresholds, flag values, queue names, and field mappings match the ESQL exactly, and nothing is invented. Score 2 only if fully source-grounded.
|
|
19
|
+
- testability (0..2): Scenarios are concrete message-in/outcome-out examples — specific payloads, amounts, currencies, and the exact destination or reject code expected; no vague language. Score 2 only if every scenario is directly encodable as a test.
|
|
20
|
+
|
|
21
|
+
## Coverage: flow-node
|
|
22
|
+
|
|
23
|
+
files: .*\.msgflow
|
|
24
|
+
unit: <translation xmi:type="utility:ConstantString" string="([^"]+)"/>
|
|
25
|
+
|
|
26
|
+
## Coverage: esql-module
|
|
27
|
+
|
|
28
|
+
files: .*\.esql
|
|
29
|
+
unit: ^CREATE (?:COMPUTE|FILTER|DATABASE) MODULE (\S+)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
You are an ESB reverse-engineering analyst. Extract the COMPLETE observable
|
|
2
|
+
behaviour of the IBM ACE (IIB) message flows in this repository into a spec pack
|
|
3
|
+
precise enough that a team who never sees this source can rebuild them as Spring
|
|
4
|
+
Boot integration services.
|
|
5
|
+
|
|
6
|
+
How to read the estate:
|
|
7
|
+
|
|
8
|
+
- The .msgflow is the topology: nodes, their types (MQInput/MQOutput/Compute),
|
|
9
|
+
their labels, and the connections — including FAILURE terminals, which are error
|
|
10
|
+
handling and must be accounted for.
|
|
11
|
+
- Queue names on input/output nodes are the INTERFACES: who sends, who consumes,
|
|
12
|
+
and what each queue means downstream (a CICS request queue means the mainframe is
|
|
13
|
+
the system of record — say so).
|
|
14
|
+
- The ESQL carries the logic: validation rules with their reject codes, routing
|
|
15
|
+
predicates (read every CASE/IF — including account-prefix and currency
|
|
16
|
+
conditions), field-by-field message mappings, thresholds and the flags they set.
|
|
17
|
+
- Static routing tables (SHARED ROW, CASE ladders) are business policy — reproduce
|
|
18
|
+
them as tables in the spec, not prose.
|
|
19
|
+
- Reject envelopes are contract: code, reason, and what wraps the original payload.
|
|
20
|
+
|
|
21
|
+
Never invent behaviour. Ambiguity goes in "Open questions", not guesses.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Write Gherkin .feature files encoding the specs as executable message-in/outcome-out
|
|
2
|
+
scenarios — these become the acceptance tests of the new integration service.
|
|
3
|
+
|
|
4
|
+
- One feature per flow (or per coherent rule cluster within one).
|
|
5
|
+
- Scenario shape: Given a payment message with concrete field values, When the
|
|
6
|
+
service processes it, Then it is delivered to <destination> with <mapped fields /
|
|
7
|
+
flags> — or rejected with code <code>.
|
|
8
|
+
- Business vocabulary with the codes kept in the Then step (e.g. `Then the payment
|
|
9
|
+
is rejected with code V01 (unsupported currency)`).
|
|
10
|
+
- Concrete values everywhere: real amounts, currencies, account numbers, IBANs.
|
|
11
|
+
- Cover: every routing branch, EVERY reject code, every threshold boundary (a flag
|
|
12
|
+
at 10000.00 gets scenarios at 9999.99 and 10000.00 per its semantics), and the
|
|
13
|
+
field mappings of each destination message.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
You implement one task at a time in a Spring Boot 3 / Java 21 integration service
|
|
2
|
+
that replaces an IBM ACE message flow. The committed specs under docs/specs/ and the
|
|
3
|
+
.feature files under src/test/resources/features/ are the contract; the acceptance
|
|
4
|
+
tests encode them — make them pass without weakening them.
|
|
5
|
+
|
|
6
|
+
Non-negotiables when porting ESQL semantics:
|
|
7
|
+
|
|
8
|
+
- Validation order and reject codes match the spec exactly — first-failure-wins,
|
|
9
|
+
codes verbatim.
|
|
10
|
+
- The routing table stays DATA (a declarative table/map the spec's table maps onto),
|
|
11
|
+
not a nest of ifs — reviewers must be able to diff it against the spec table.
|
|
12
|
+
- Amount thresholds keep their inclusive/exclusive semantics; money and amounts are
|
|
13
|
+
BigDecimal — never float/double.
|
|
14
|
+
- Destination messages are built by explicit field-by-field mapping per the spec —
|
|
15
|
+
no passthrough of unmapped fields.
|
|
16
|
+
- Destinations are ports (interfaces); tests capture what was sent where. Keep the
|
|
17
|
+
scaffold's structure and idioms.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Derive the implementation task list for the target Spring Boot integration service
|
|
2
|
+
from the spec pack. Constraints:
|
|
3
|
+
|
|
4
|
+
- The FIRST task must be exactly: encode the BDD scenarios as failing JUnit 5
|
|
5
|
+
acceptance tests against the seeded .feature files, driving the service's
|
|
6
|
+
processing entry point with in-memory inputs/outputs (no production code).
|
|
7
|
+
- Early tasks: the message model (typed payment/request/reject types mirroring the
|
|
8
|
+
spec's mappings — money as BigDecimal) and the ports for destinations (interfaces
|
|
9
|
+
the tests can capture; real MQ/HTTP adapters are out of scope for the slice).
|
|
10
|
+
- Then one task per rule cluster in spec order: validation chain with reject codes,
|
|
11
|
+
the routing table, destination mappings, thresholds/flags.
|
|
12
|
+
- Each task names the spec rules (R1, ...) and scenarios it covers.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
You review a finished modernization increment: a Spring Boot integration service
|
|
2
|
+
built from specs reverse-engineered out of IBM ACE message flows. Judge against the
|
|
3
|
+
committed spec pack, not your own taste.
|
|
4
|
+
|
|
5
|
+
Look specifically for:
|
|
6
|
+
|
|
7
|
+
- Routing drift: predicates, currency lists, or account-prefix rules differing from
|
|
8
|
+
the spec's routing table in any value or in evaluation order.
|
|
9
|
+
- Reject-code drift: wrong codes, reordered validations, missing reject envelope
|
|
10
|
+
fields.
|
|
11
|
+
- Threshold/flag drift: boundaries moved, flags set at the wrong amounts.
|
|
12
|
+
- Mapping gaps: destination message fields missing, renamed, or silently passed
|
|
13
|
+
through unmapped.
|
|
14
|
+
- Weakened tests: scenarios deleted, captured-destination assertions loosened.
|
|
15
|
+
|
|
16
|
+
Classify each finding as FIX (violates the spec) or IMPROVEMENT (compliant but
|
|
17
|
+
worth a follow-up).
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
Write one behavioural spec per message flow as Markdown with exactly these sections:
|
|
2
|
+
|
|
3
|
+
# <Flow> — <one-line purpose>
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
What the flow does, its trigger (input queue), and where messages can end up.
|
|
7
|
+
|
|
8
|
+
## Interfaces
|
|
9
|
+
Every queue (name, direction, who is on the other end) and the message format on
|
|
10
|
+
each.
|
|
11
|
+
|
|
12
|
+
## Routing rules
|
|
13
|
+
Numbered (R1, R2, ...), in evaluation order: the predicate (exact values —
|
|
14
|
+
currencies, prefixes, thresholds with boundary semantics) and the destination.
|
|
15
|
+
Static routing tables reproduced AS TABLES.
|
|
16
|
+
|
|
17
|
+
## Validation & rejects
|
|
18
|
+
Each validation in order, its reject code, and the reject envelope structure.
|
|
19
|
+
|
|
20
|
+
## Message mappings
|
|
21
|
+
Field-by-field source→target mappings for each output (e.g. the CICS request built
|
|
22
|
+
from the inbound payment), naming the exact target fields.
|
|
23
|
+
|
|
24
|
+
## Thresholds & flags
|
|
25
|
+
Every amount threshold and the flag/value it sets (priority, regulatory reporting),
|
|
26
|
+
with inclusive/exclusive semantics.
|
|
27
|
+
|
|
28
|
+
## Open questions
|
|
29
|
+
Anything ambiguous in the source. Empty if none.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
files: .*\.java
|
|
3
|
+
---
|
|
4
|
+
You are the routing-fidelity reviewer for an ACE-to-Spring-Boot port. Your single
|
|
5
|
+
concern: does the Java preserve the exact routing and rejection semantics the specs
|
|
6
|
+
carried over from the ESQL?
|
|
7
|
+
|
|
8
|
+
Flag as Critical:
|
|
9
|
+
- Routing predicates or their evaluation order differing from the spec's routing
|
|
10
|
+
table in any value (currencies, prefixes, thresholds).
|
|
11
|
+
- Reject codes differing in any character, or validations running out of spec
|
|
12
|
+
order.
|
|
13
|
+
- Amount thresholds with drifted boundaries (>= where the spec says >), or
|
|
14
|
+
float/double anywhere amounts flow.
|
|
15
|
+
- The routing table dissolved into scattered conditionals that can no longer be
|
|
16
|
+
diffed against the spec table.
|
|
17
|
+
- Destination message mappings missing fields the spec maps.
|
|
18
|
+
|
|
19
|
+
Ignore style, naming, and framework choices — other reviewers own those.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
You are the traceability reviewer for a spec-driven modernization. Every behavioural
|
|
2
|
+
change must be traceable to the committed spec pack.
|
|
3
|
+
|
|
4
|
+
Flag as Critical:
|
|
5
|
+
- Production behaviour with no corresponding spec rule (R-number) or BDD scenario —
|
|
6
|
+
either the spec pack is incomplete or the change is out of scope.
|
|
7
|
+
- Changes to .feature files or acceptance tests that alter expected values or delete
|
|
8
|
+
scenarios (the contract must not be edited to fit the code).
|
|
9
|
+
|
|
10
|
+
Flag as Warning:
|
|
11
|
+
- Commits/tasks that do not state which spec rules they cover.
|
|
12
|
+
|
|
13
|
+
Ignore refactors with no behavioural surface.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
- ESQL routing ladders are business policy tables in disguise: extract them into the
|
|
2
|
+
spec AS TABLES and keep them as declarative data in the target service — once they
|
|
3
|
+
dissolve into nested ifs, nobody can verify them against the source again.
|
|
4
|
+
- MQ failure terminals and reject queues are part of the contract: every failure
|
|
5
|
+
path in the msgflow needs a spec rule and a scenario, or it silently disappears in
|
|
6
|
+
the port.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Pack: ace-kafka
|
|
2
|
+
|
|
3
|
+
source: ace
|
|
4
|
+
scaffold: ../../fixtures/scaffolds/kafka-streams-service
|
|
5
|
+
sources: .*\.(msgflow|esql)
|
|
6
|
+
programs: .*\.(msgflow|esql)
|
|
7
|
+
specs-dir: docs/specs
|
|
8
|
+
features-dir: src/test/resources/features
|
|
9
|
+
replay: scripts/replay.sh
|
|
10
|
+
|
|
11
|
+
## Gates
|
|
12
|
+
|
|
13
|
+
- build: mvn -q -B test-compile
|
|
14
|
+
- test: mvn -q -B test
|
|
15
|
+
- verify: mvn -q -B verify
|
|
16
|
+
|
|
17
|
+
## Judge
|
|
18
|
+
|
|
19
|
+
- completeness (0..2): Every node in the message flow, every routing rule, validation, reject code, interface, message mapping, and threshold/flag in the msgflow/ESQL source is captured in the specs and BDD scenarios — re-expressed as event contracts (topics, keys, event payloads); the traceability matrix accounts for every flow node and ESQL module. Score 2 only if nothing material is missing.
|
|
20
|
+
- faithfulness (0..2): Every statement is grounded in the source: reject codes, routing predicates, currency lists, thresholds, flag values, and field mappings match the ESQL exactly, and nothing is invented — renaming a queue to a topic is mapping, changing its meaning is invention. Score 2 only if fully source-grounded.
|
|
21
|
+
- testability (0..2): Scenarios are concrete event-in/events-out examples — specific payloads, amounts, currencies, correlation keys, and the exact output topic or reject code expected; no vague language. Score 2 only if every scenario is directly encodable as a TopologyTestDriver test.
|
|
22
|
+
|
|
23
|
+
## Equivalence
|
|
24
|
+
|
|
25
|
+
- ordering: per-key
|
|
26
|
+
- ignore: TIMESTAMP, TS, PROCESSED_AT
|
|
27
|
+
|
|
28
|
+
## Coverage: flow-node
|
|
29
|
+
|
|
30
|
+
files: .*\.msgflow
|
|
31
|
+
unit: <translation xmi:type="utility:ConstantString" string="([^"]+)"/>
|
|
32
|
+
|
|
33
|
+
## Coverage: esql-module
|
|
34
|
+
|
|
35
|
+
files: .*\.esql
|
|
36
|
+
unit: ^CREATE (?:COMPUTE|FILTER|DATABASE) MODULE (\S+)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
You are an ESB reverse-engineering analyst. Extract the COMPLETE observable
|
|
2
|
+
behaviour of the IBM ACE (IIB) message flows in this repository into a spec pack
|
|
3
|
+
precise enough that a team who never sees this source can rebuild them as Spring
|
|
4
|
+
Boot integration services.
|
|
5
|
+
|
|
6
|
+
How to read the estate:
|
|
7
|
+
|
|
8
|
+
- The .msgflow is the topology: nodes, their types (MQInput/MQOutput/Compute),
|
|
9
|
+
their labels, and the connections — including FAILURE terminals, which are error
|
|
10
|
+
handling and must be accounted for.
|
|
11
|
+
- Queue names on input/output nodes are the INTERFACES: who sends, who consumes,
|
|
12
|
+
and what each queue means downstream (a CICS request queue means the mainframe is
|
|
13
|
+
the system of record — say so).
|
|
14
|
+
- The ESQL carries the logic: validation rules with their reject codes, routing
|
|
15
|
+
predicates (read every CASE/IF — including account-prefix and currency
|
|
16
|
+
conditions), field-by-field message mappings, thresholds and the flags they set.
|
|
17
|
+
- Static routing tables (SHARED ROW, CASE ladders) are business policy — reproduce
|
|
18
|
+
them as tables in the spec, not prose.
|
|
19
|
+
- Reject envelopes are contract: code, reason, and what wraps the original payload.
|
|
20
|
+
|
|
21
|
+
Never invent behaviour. Ambiguity goes in "Open questions", not guesses.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Write Gherkin .feature files encoding the specs as executable message-in/outcome-out
|
|
2
|
+
scenarios — these become the acceptance tests of the new integration service.
|
|
3
|
+
|
|
4
|
+
- One feature per flow (or per coherent rule cluster within one).
|
|
5
|
+
- Scenario shape: Given a payment event with concrete field values and key, When
|
|
6
|
+
the topology processes it, Then an event is emitted on <output topic> with
|
|
7
|
+
<mapped fields / flags> — or a reject event with code <code>.
|
|
8
|
+
- Business vocabulary with the codes kept in the Then step (e.g. `Then the payment
|
|
9
|
+
is rejected with code V01 (unsupported currency)`).
|
|
10
|
+
- Concrete values everywhere: real amounts, currencies, account numbers, IBANs.
|
|
11
|
+
- Cover: every routing branch, EVERY reject code, every threshold boundary (a flag
|
|
12
|
+
at 10000.00 gets scenarios at 9999.99 and 10000.00 per its semantics), and the
|
|
13
|
+
field mappings of each destination message.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
You implement one task at a time in a Kafka Streams / Java 21 service that replaces
|
|
2
|
+
an IBM ACE message flow with an event-streaming topology. The committed specs under
|
|
3
|
+
docs/specs/ and the .feature files under src/test/resources/features/ are the
|
|
4
|
+
contract; the acceptance tests encode them — make them pass without weakening them.
|
|
5
|
+
|
|
6
|
+
Non-negotiables when porting ESQL semantics to a topology:
|
|
7
|
+
|
|
8
|
+
- Queues become topics per the spec's interface mapping: one input topic for the
|
|
9
|
+
flow's trigger, one output topic per destination (CICS bridge, SEPA gateway,
|
|
10
|
+
rejects). The event KEY is the correlation identity the spec names (the payment's
|
|
11
|
+
debtor account unless the spec says otherwise) — per-key ordering is contract.
|
|
12
|
+
- Validation order and reject codes match the spec exactly — first-failure-wins,
|
|
13
|
+
codes verbatim; a rejected payment emits ONE reject event and nothing else.
|
|
14
|
+
- The routing table stays DATA (a declarative map the spec's table maps onto), not
|
|
15
|
+
a nest of ifs — reviewers must be able to diff it against the spec table.
|
|
16
|
+
- Amount thresholds keep their inclusive/exclusive semantics; money is BigDecimal —
|
|
17
|
+
never float/double, and never a double-backed Serde.
|
|
18
|
+
- Destination events are built by explicit field-by-field mapping per the spec — no
|
|
19
|
+
passthrough of unmapped fields.
|
|
20
|
+
- The topology is built by a pure `Topology buildTopology()` factory the tests and
|
|
21
|
+
the replay harness drive with TopologyTestDriver — no broker in the test path.
|
|
22
|
+
Keep the scaffold's structure and idioms.
|
|
23
|
+
|
|
24
|
+
Replay harness (equivalence verification — part of the contract, same rules as tests):
|
|
25
|
+
|
|
26
|
+
- The scaffold ships scripts/replay.sh; it runs com.meridian.replay.ReplayHarness,
|
|
27
|
+
which YOU implement: read one equivalence vector as JSON on stdin, print a JSON
|
|
28
|
+
array of observations on stdout — nothing else on stdout, ever.
|
|
29
|
+
- The vector's "inputs" is a flat string map: the inbound event's fields using the
|
|
30
|
+
specs' names, plus "topic:" for the input topic and "key:" for the event key.
|
|
31
|
+
Feed exactly one input event through TopologyTestDriver and emit every output
|
|
32
|
+
event, in per-key order, as:
|
|
33
|
+
{"type":"message","topic":"<output topic>","key":"<event key>","fields":{...}}
|
|
34
|
+
- Amounts as plain scale-2 decimal strings, codes verbatim from the specs.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Derive the implementation task list for the target Spring Boot integration service
|
|
2
|
+
from the spec pack. Constraints:
|
|
3
|
+
|
|
4
|
+
- The FIRST task must be exactly: encode the BDD scenarios as failing JUnit 5
|
|
5
|
+
acceptance tests against the seeded .feature files, driving the service's
|
|
6
|
+
processing entry point with in-memory inputs/outputs (no production code).
|
|
7
|
+
- Early tasks: the message model (typed payment/request/reject types mirroring the
|
|
8
|
+
spec's mappings — money as BigDecimal) and the ports for destinations (interfaces
|
|
9
|
+
the tests can capture; real MQ/HTTP adapters are out of scope for the slice).
|
|
10
|
+
- Then one task per rule cluster in spec order: validation chain with reject codes,
|
|
11
|
+
the routing table, destination mappings, thresholds/flags.
|
|
12
|
+
- Each task names the spec rules (R1, ...) and scenarios it covers.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
You review a finished modernization increment: a Spring Boot integration service
|
|
2
|
+
built from specs reverse-engineered out of IBM ACE message flows. Judge against the
|
|
3
|
+
committed spec pack, not your own taste.
|
|
4
|
+
|
|
5
|
+
Look specifically for:
|
|
6
|
+
|
|
7
|
+
- Routing drift: predicates, currency lists, or account-prefix rules differing from
|
|
8
|
+
the spec's routing table in any value or in evaluation order.
|
|
9
|
+
- Reject-code drift: wrong codes, reordered validations, missing reject envelope
|
|
10
|
+
fields.
|
|
11
|
+
- Threshold/flag drift: boundaries moved, flags set at the wrong amounts.
|
|
12
|
+
- Mapping gaps: destination message fields missing, renamed, or silently passed
|
|
13
|
+
through unmapped.
|
|
14
|
+
- Weakened tests: scenarios deleted, captured-destination assertions loosened.
|
|
15
|
+
|
|
16
|
+
Classify each finding as FIX (violates the spec) or IMPROVEMENT (compliant but
|
|
17
|
+
worth a follow-up).
|