melusine 0.1.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.
Files changed (41) hide show
  1. package/README.md +249 -0
  2. package/SPEC.md +145 -0
  3. package/dist/catalog.d.ts +104 -0
  4. package/dist/cli.d.ts +27 -0
  5. package/dist/compile.d.ts +1 -0
  6. package/dist/generate.d.ts +11 -0
  7. package/dist/index.d.ts +23 -0
  8. package/dist/parse.d.ts +27 -0
  9. package/dist/run.d.ts +54 -0
  10. package/dist/scaffold.d.ts +18 -0
  11. package/dist/types.d.ts +542 -0
  12. package/dist/validate.d.ts +28 -0
  13. package/dist/walk.d.ts +24 -0
  14. package/examples/README.md +21 -0
  15. package/examples/onboarding/README.md +16 -0
  16. package/examples/onboarding/catalog.js +29 -0
  17. package/examples/onboarding/generated/onboarding.test.mjs +15 -0
  18. package/examples/onboarding/journey.md +18 -0
  19. package/examples/onboarding/onboarding-session.mjs +21 -0
  20. package/examples/order-fulfillment/README.md +16 -0
  21. package/examples/order-fulfillment/catalog.js +59 -0
  22. package/examples/order-fulfillment/generated/order-fulfillment.test.mjs +15 -0
  23. package/examples/order-fulfillment/journey.md +32 -0
  24. package/examples/order-fulfillment/order-workflow.mjs +48 -0
  25. package/examples/vending/README.md +16 -0
  26. package/examples/vending/catalog.js +32 -0
  27. package/examples/vending/generated/vending.test.mjs +15 -0
  28. package/examples/vending/journey.md +21 -0
  29. package/examples/vending/vending-machine.mjs +16 -0
  30. package/package.json +39 -0
  31. package/src/catalog.js +485 -0
  32. package/src/cli.js +331 -0
  33. package/src/compile.js +3 -0
  34. package/src/generate.js +52 -0
  35. package/src/index.js +28 -0
  36. package/src/parse.js +263 -0
  37. package/src/run.js +258 -0
  38. package/src/scaffold.js +142 -0
  39. package/src/types.js +330 -0
  40. package/src/validate.js +171 -0
  41. package/src/walk.js +57 -0
package/README.md ADDED
@@ -0,0 +1,249 @@
1
+ # melusine
2
+
3
+ `melusine` runs Mermaid journey charts as tests.
4
+
5
+ You write:
6
+
7
+ 1. A Markdown file with YAML frontmatter and a Mermaid flowchart.
8
+ 2. A reusable JavaScript catalog with `task(...)` and `scorer(...)` functions.
9
+
10
+ Melusine parses the chart, validates the graph, runs the catalog functions in graph order, passes task results through context, records gaps, and reports whether the journey passed.
11
+
12
+ ## Install
13
+
14
+ ```sh
15
+ npm install --save-dev melusine
16
+ ```
17
+
18
+ For this repository:
19
+
20
+ ```sh
21
+ npm install
22
+ npm test
23
+ ```
24
+
25
+ ## Start a Project
26
+
27
+ Create starter files in an existing JS/Node project:
28
+
29
+ ```sh
30
+ npx melusine init
31
+ ```
32
+
33
+ This creates:
34
+
35
+ - `melusine.catalog.js`
36
+ - `journeys/example.journey.md`
37
+ - `melusine:validate` and `melusine:test` package scripts when `package.json` exists
38
+
39
+ Run the starter:
40
+
41
+ ```sh
42
+ npm run melusine:validate
43
+ npm run melusine:test
44
+ ```
45
+
46
+ ## Build a Journey
47
+
48
+ Save this as `checkout.journey.md`:
49
+
50
+ ````markdown
51
+ ---
52
+ journey: checkout-happy-path
53
+ nodes:
54
+ start:
55
+ as: checkout
56
+ addItem:
57
+ args: ["book", 1]
58
+ pay:
59
+ args: ["card"]
60
+ ---
61
+
62
+ # Checkout happy path
63
+
64
+ ```mermaid
65
+ graph TD
66
+ start(["Customer opens checkout"]) --> addItem
67
+ addItem["Add item"] --> payable
68
+ payable{"Cart is payable?"}
69
+ payable -->|yes| pay
70
+ payable -->|no| blocked
71
+ pay["Pay"] --> paid
72
+ paid(["Order paid"])
73
+ blocked(["Payment blocked"])
74
+ ```
75
+ ````
76
+
77
+ GitHub and GitLab can render Mermaid diagrams in Markdown. Useful Mermaid links:
78
+
79
+ - [Mermaid docs](https://mermaid.js.org/)
80
+ - [Flowchart syntax](https://mermaid.js.org/syntax/flowchart.html)
81
+ - [Syntax reference](https://mermaid.js.org/intro/syntax-reference.html)
82
+
83
+ ## Write a Catalog
84
+
85
+ Save this as `checkout.catalog.js`:
86
+
87
+ ```js
88
+ import { scorer, task } from 'melusine';
89
+ import { Checkout } from './checkout.js';
90
+
91
+ export default {
92
+ start: task(() => new Checkout(), { as: 'checkout' }),
93
+
94
+ addItem: task(({ args, context }) => {
95
+ context.checkout.addItem(args[0], args[1]);
96
+ }, { requiredArgs: 2 }),
97
+
98
+ payable: scorer(({ context }) => context.checkout.total > 0),
99
+
100
+ pay: task(({ args, context }) => {
101
+ context.checkout.pay(args[0]);
102
+ }, { requiredArgs: 1 }),
103
+
104
+ paid: scorer(({ context }) => ({
105
+ pass: context.checkout.status === 'paid',
106
+ actual: context.checkout.status,
107
+ expected: 'paid',
108
+ message: 'checkout should be paid',
109
+ })),
110
+
111
+ blocked: scorer(() => ({
112
+ pass: false,
113
+ message: 'checkout should have been payable',
114
+ })),
115
+ };
116
+ ```
117
+
118
+ Catalog entries are reusable. Multiple journey files can reference the same `addItem`, `pay`, and `paid` entries by node id.
119
+
120
+ ## Frontmatter
121
+
122
+ Frontmatter is the YAML block at the top of the journey file.
123
+
124
+ ```yaml
125
+ ---
126
+ journey: checkout-happy-path
127
+ nodes:
128
+ start:
129
+ as: checkout
130
+ addItem:
131
+ args: ["book", 1]
132
+ alternateAdd:
133
+ use: addItem
134
+ args: ["pen", 2]
135
+ ---
136
+ ```
137
+
138
+ `nodes` is keyed by Mermaid node id.
139
+
140
+ - `args` becomes `input.args` for the catalog function.
141
+ - `as` stores a task result under that context key.
142
+ - `use` points one node at a different catalog key.
143
+ - Extra fields become `input.config.options`.
144
+
145
+ Everything outside `nodes` becomes `input.meta`.
146
+
147
+ ## Graph Rules
148
+
149
+ Use a Mermaid `graph` or `flowchart` block:
150
+
151
+ ```mermaid
152
+ graph TD
153
+ start(["Start"]) --> step
154
+ step["Do something"] --> decision
155
+ decision{"Choose?"}
156
+ decision -->|yes| done
157
+ decision -->|no| failed
158
+ done(["Done"])
159
+ failed(["Failed"])
160
+ ```
161
+
162
+ Supported in v1:
163
+
164
+ | Shape | Example | Meaning |
165
+ | --- | --- | --- |
166
+ | Terminal | `start(["Start"])` | Start or final outcome |
167
+ | Process | `step["Do something"]` | Task |
168
+ | Decision | `ok{"Ready?"}` | Branch scorer |
169
+ | Edge | `A --> B` | Next node |
170
+ | Labeled edge | `A -->|yes| B` | Decision branch |
171
+
172
+ Rules:
173
+
174
+ - There must be one start node: a terminal with no incoming edges.
175
+ - Process nodes must map to tasks.
176
+ - Decision nodes must map to scorers.
177
+ - Final terminal nodes must map to scorers.
178
+ - Every completed path needs an outcome scorer by default.
179
+ - Branches cannot merge back together in v1.
180
+ - Only `-->` edges are supported.
181
+
182
+ ## CLI
183
+
184
+ ```sh
185
+ melusine validate <journey.md> [--catalog <catalog.js>] [--export <name>] [--json]
186
+ melusine test <journey.md> --catalog <catalog.js> [--export <name>] [--json]
187
+ melusine compile <journey.md> --catalog <catalog.js> [--export <name>] --out <file>
188
+ melusine init [--force]
189
+ ```
190
+
191
+ Common workflow:
192
+
193
+ ```sh
194
+ npx melusine validate checkout.journey.md --catalog checkout.catalog.js
195
+ npx melusine test checkout.journey.md --catalog checkout.catalog.js
196
+ npx melusine compile checkout.journey.md --catalog checkout.catalog.js --out checkout.test.mjs
197
+ node --test checkout.test.mjs
198
+ ```
199
+
200
+ `test` runs the journey directly. `compile` writes a small `node:test` wrapper that reads the journey file, imports the catalog, and calls the same runner.
201
+
202
+ ## Library API
203
+
204
+ ```js
205
+ import { parse, runText, scorer, task } from 'melusine';
206
+
207
+ const result = await runText(markdown, catalog);
208
+ ```
209
+
210
+ Important exports:
211
+
212
+ - `task(fn, options)` defines a reusable action.
213
+ - `scorer(fn, options)` defines a reusable check.
214
+ - `runText(text, catalog)` parses and executes a journey.
215
+ - `parse(text)` returns the graph, frontmatter, and diagnostics.
216
+ - `generateTest(options)` creates a generated wrapper string.
217
+
218
+ Scorers can return:
219
+
220
+ ```js
221
+ true
222
+ false
223
+ { pass: true, message: 'ok', actual, expected }
224
+ 0.8
225
+ { score: 0.8, threshold: 0.7 }
226
+ ```
227
+
228
+ Numeric scores pass when `score >= threshold`. The default threshold is `1`.
229
+
230
+ ## Examples
231
+
232
+ The `examples/` directory has complete runnable examples:
233
+
234
+ - `examples/onboarding/` shows a linear flow.
235
+ - `examples/vending/` shows one decision branch.
236
+ - `examples/order-fulfillment/` shows nested decisions.
237
+
238
+ Run all examples:
239
+
240
+ ```sh
241
+ npm run generate:examples
242
+ node --test examples/*/generated/*.test.mjs
243
+ ```
244
+
245
+ ## Gaps
246
+
247
+ A catalog entry can return `todo(reason)` or `hole(reason)`. Melusine also creates a `hole` when a required arg or option is missing.
248
+
249
+ Gaps make the run fail and appear in `result.gaps`. They are never converted into passing assertions.
package/SPEC.md ADDED
@@ -0,0 +1,145 @@
1
+ # Melusine Catalog Mode Spec
2
+
3
+ Melusine is a standalone npm package that runs human-readable Mermaid flowchart journeys as tests. The package owns graph structure: Markdown parsing, Mermaid subset parsing, structural validation, catalog validation, deterministic traversal, branch selection, context passing, scoring, diagnostics, and gap aggregation.
4
+
5
+ Users own project meaning through reusable ESM JavaScript catalog entries created with `task(...)` and `scorer(...)`.
6
+
7
+ ## Package Rules
8
+
9
+ - Source is plain ESM JavaScript with `// @ts-check` and JSDoc.
10
+ - Generated `.d.ts` files come from TypeScript as a dev-only declaration generator.
11
+ - Node target is `>=20`.
12
+ - `yaml` is the only runtime dependency.
13
+ - The Mermaid parser is handwritten.
14
+
15
+ ## Journey Input
16
+
17
+ A journey is Markdown with optional YAML frontmatter and the first Mermaid fence.
18
+
19
+ ````markdown
20
+ ---
21
+ journey: vending-purchase
22
+ nodes:
23
+ start: { as: machine }
24
+ insert: { args: [150] }
25
+ dispense: { args: ["cola"] }
26
+ ---
27
+
28
+ ```mermaid
29
+ graph TD
30
+ start(["Start"]) --> insert
31
+ insert["Insert coins"] --> enough
32
+ enough{"Enough credit?"}
33
+ enough -->|yes| dispense
34
+ enough -->|no| fail
35
+ dispense["Dispense cola"] --> gotCola
36
+ gotCola(["Got cola"])
37
+ fail(["Insufficient credit"])
38
+ ```
39
+ ````
40
+
41
+ Frontmatter rules:
42
+
43
+ - `nodes` is keyed by Mermaid node id.
44
+ - `use` points a node to a different catalog key.
45
+ - `args` becomes the catalog call's positional args.
46
+ - `as` chooses where a task result is stored in execution context.
47
+ - Extra fields become `config.options`.
48
+ - Frontmatter outside `nodes` becomes `meta`.
49
+
50
+ ## Supported Mermaid Subset
51
+
52
+ - Headers: `graph TD`, `graph LR`, `flowchart TD`, `flowchart LR`.
53
+ - Process nodes: `id["label"]` or `id[label]`.
54
+ - Decision nodes: `id{"label"}` or `id{label}`.
55
+ - Terminal nodes: `id(["label"])` or `id([label])`.
56
+ - Edges: `A --> B` and `A -->|label| B`.
57
+ - Comments beginning with `%%` and blank lines are ignored.
58
+ - Unsupported edge operators produce warnings and are ignored.
59
+ - Bare node references default to process nodes with an info diagnostic.
60
+
61
+ Structural errors are diagnostics, not thrown exceptions.
62
+
63
+ ## Catalog Semantics
64
+
65
+ ```js
66
+ import { scorer, task } from 'melusine';
67
+
68
+ export default {
69
+ start: task(() => new Subject(), { as: 'subject' }),
70
+ act: task(({ context, args }) => context.subject.act(args[0]), { requiredArgs: 1 }),
71
+ done: scorer(({ context }) => context.subject.done === true),
72
+ };
73
+ ```
74
+
75
+ Role rules:
76
+
77
+ - The unique start terminal expects a task.
78
+ - Process nodes expect tasks.
79
+ - Decision nodes expect scorers.
80
+ - Non-start terminal nodes expect scorers.
81
+ - Mermaid shape wins over catalog wrapper role.
82
+
83
+ Catalog functions receive one object containing:
84
+
85
+ - `args`
86
+ - `context`
87
+ - `meta`
88
+ - `node`
89
+ - `previous`
90
+ - `config`
91
+ - `key`
92
+
93
+ Task return values are stored in context under `frontmatter.as`, then task default `as`, then node id.
94
+
95
+ ## Scoring
96
+
97
+ Scorers are project-owned. Melusine does not infer correctness from labels or shapes.
98
+
99
+ Accepted scorer returns:
100
+
101
+ - `boolean`
102
+ - `{ pass, message?, actual?, expected? }`
103
+ - `number`
104
+ - `{ score, threshold?, message?, actual?, expected? }`
105
+
106
+ Numeric score results pass when `score >= threshold`. The default threshold is `1`.
107
+
108
+ Decision scorer pass/fail selects a branch. `yes` and `no` labels are preferred; source order is the deterministic fallback. Outcome scorers determine whether the journey passes.
109
+
110
+ By default, every completed start-to-terminal path must include an outcome scorer. Counting decision scorers for this rule is configurable.
111
+
112
+ ## Gaps
113
+
114
+ Unresolved work must stay visible.
115
+
116
+ - `todo(reason)` marks known unfinished project work.
117
+ - `hole(reason)` marks missing human-supplied input.
118
+ - Missing required args or options create holes.
119
+
120
+ Gaps make a run fail and are returned in `gaps[]`. They must not become passing assertions.
121
+
122
+ ## CLI
123
+
124
+ - `melusine validate <journey.md> [--catalog <catalog.js>]`
125
+ - `melusine test <journey.md> --catalog <catalog.js>`
126
+ - `melusine compile <journey.md> --catalog <catalog.js> --out <file>`
127
+ - `melusine init`
128
+
129
+ `test` is the primary command and executes directly. `compile` writes a thin `node:test` wrapper that imports Melusine and the catalog, reads the journey file, and calls the same runner. Generated tests must not inline catalog function source.
130
+
131
+ ## Public API
132
+
133
+ Core exports:
134
+
135
+ - `parse`
136
+ - `task`
137
+ - `scorer`
138
+ - `todo`
139
+ - `hole`
140
+ - `run`
141
+ - `runText`
142
+ - `formatRunFailure`
143
+ - `generateTest`
144
+
145
+ Renderer hooks are not part of the catalog-mode public API.
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Wrap a reusable project action for use by one or more journeys.
3
+ *
4
+ * @param {import('./types.js').TaskHandler} handler Function to run.
5
+ * @param {TaskOptions} [options] Task metadata and requirements.
6
+ * @returns {import('./types.js').TaskEntry}
7
+ */
8
+ export function task(handler: import("./types.js").TaskHandler, options?: TaskOptions): import("./types.js").TaskEntry;
9
+ /**
10
+ * Wrap a reusable project scorer for use by one or more journeys.
11
+ *
12
+ * @param {import('./types.js').ScorerHandler} handler Function to score.
13
+ * @param {ScorerOptions} [options] Scorer metadata and requirements.
14
+ * @returns {import('./types.js').ScorerEntry}
15
+ */
16
+ export function scorer(handler: import("./types.js").ScorerHandler, options?: ScorerOptions): import("./types.js").ScorerEntry;
17
+ /**
18
+ * Create an explicit unresolved task/scorer result.
19
+ *
20
+ * @param {string} reason Why the step is pending.
21
+ * @returns {GapSignal}
22
+ */
23
+ export function todo(reason: string): GapSignal;
24
+ /**
25
+ * Create an explicit missing-input result.
26
+ *
27
+ * @param {string} reason What input is missing.
28
+ * @returns {GapSignal}
29
+ */
30
+ export function hole(reason: string): GapSignal;
31
+ /**
32
+ * Validate catalog references and graph/catalog role compatibility.
33
+ *
34
+ * @param {JourneyGraph} graph Parsed graph.
35
+ * @param {Map<string, Binding>} bindings Node id to frontmatter config.
36
+ * @param {Catalog} catalog Catalog object.
37
+ * @param {RunOptions} [options] Validation options.
38
+ * @returns {Diagnostic[]}
39
+ */
40
+ export function validateCatalog(graph: JourneyGraph, bindings: Map<string, Binding>, catalog: Catalog, options?: RunOptions): Diagnostic[];
41
+ /**
42
+ * Read one node's frontmatter binding into the catalog config model.
43
+ *
44
+ * @param {Binding | undefined} binding Raw frontmatter binding.
45
+ * @param {string} nodeId Source node id.
46
+ * @param {Diagnostic[]} [diagnostics] Diagnostics sink.
47
+ * @returns {NodeConfig}
48
+ */
49
+ export function readNodeConfig(binding: Binding | undefined, nodeId: string, diagnostics?: Diagnostic[]): NodeConfig;
50
+ /**
51
+ * Resolve one catalog entry and validate its shape.
52
+ *
53
+ * @param {Catalog} catalog Catalog object.
54
+ * @param {string} key Catalog key.
55
+ * @returns {CatalogEntry}
56
+ */
57
+ export function getCatalogEntry(catalog: Catalog, key: string): CatalogEntry;
58
+ /**
59
+ * @param {unknown} value
60
+ * @returns {value is GapSignal}
61
+ */
62
+ export function isGapSignal(value: unknown): value is GapSignal;
63
+ /**
64
+ * Normalize a scorer return value into Melusine's result model.
65
+ *
66
+ * @param {unknown} value Raw scorer return.
67
+ * @param {number | undefined} entryThreshold Default threshold from scorer metadata.
68
+ * @returns {ScoreResult}
69
+ */
70
+ export function normalizeScoreResult(value: unknown, entryThreshold: number | undefined): ScoreResult;
71
+ /**
72
+ * @param {Node} node
73
+ * @param {string} start
74
+ * @returns {'task' | 'scorer'}
75
+ */
76
+ export function expectedRole(node: Node, start: string): "task" | "scorer";
77
+ /**
78
+ * @param {CatalogEntry} entry
79
+ * @param {NodeConfig} config
80
+ * @param {string} nodeId
81
+ * @returns {GapSignal | undefined}
82
+ */
83
+ export function missingRequiredInput(entry: CatalogEntry, config: NodeConfig, nodeId: string): GapSignal | undefined;
84
+ /**
85
+ * @param {CatalogEntry} entry
86
+ * @param {NodeConfig} config
87
+ * @param {Node} node
88
+ * @returns {string}
89
+ */
90
+ export function storageKeyFor(entry: CatalogEntry, config: NodeConfig, node: Node): string;
91
+ export type Binding = import("./types.js").Binding;
92
+ export type Catalog = import("./types.js").Catalog;
93
+ export type CatalogEntry = import("./types.js").CatalogEntry;
94
+ export type Diagnostic = import("./types.js").Diagnostic;
95
+ export type GapSignal = import("./types.js").GapSignal;
96
+ export type JourneyGraph = import("./types.js").JourneyGraph;
97
+ export type Node = import("./types.js").Node;
98
+ export type NodeConfig = import("./types.js").NodeConfig;
99
+ export type NumericScore = import("./types.js").NumericScore;
100
+ export type RunOptions = import("./types.js").RunOptions;
101
+ export type ScoreResult = import("./types.js").ScoreResult;
102
+ export type ScorerOptions = import("./types.js").ScorerOptions;
103
+ export type StructuredScore = import("./types.js").StructuredScore;
104
+ export type TaskOptions = import("./types.js").TaskOptions;
package/dist/cli.d.ts ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CLI entrypoint.
4
+ *
5
+ * @param {string[]} argv Raw process arguments.
6
+ * @param {{ cwd?: string, stdout?: NodeJS.WritableStream, stderr?: NodeJS.WritableStream }} [io]
7
+ * @returns {Promise<number>} Process exit code.
8
+ */
9
+ export function main(argv?: string[], io?: {
10
+ cwd?: string;
11
+ stdout?: NodeJS.WritableStream;
12
+ stderr?: NodeJS.WritableStream;
13
+ }): Promise<number>;
14
+ export type ParsedArgs = {
15
+ positionals: string[];
16
+ flags: {
17
+ catalog?: string;
18
+ exportName?: string;
19
+ out?: string;
20
+ force: boolean;
21
+ json: boolean;
22
+ };
23
+ };
24
+ export type Catalog = import("./types.js").Catalog;
25
+ export type Diagnostic = import("./types.js").Diagnostic;
26
+ export type Gap = import("./types.js").Gap;
27
+ export type RunResult = import("./types.js").RunResult;
@@ -0,0 +1 @@
1
+ export { run as compile, runText as compileText } from "./run.js";
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @typedef {import('./types.js').GenerateOptions} GenerateOptions
3
+ */
4
+ /**
5
+ * Generate a small node:test wrapper that calls Melusine's direct runner.
6
+ *
7
+ * @param {GenerateOptions} options Generation options.
8
+ * @returns {string}
9
+ */
10
+ export function generateTest(options: GenerateOptions): string;
11
+ export type GenerateOptions = import("./types.js").GenerateOptions;
@@ -0,0 +1,23 @@
1
+ export { parse } from "./parse.js";
2
+ export { generateTest } from "./generate.js";
3
+ export * from "./types.js";
4
+ export type NodeKind = import("./types.js").NodeKind;
5
+ export type Node = import("./types.js").Node;
6
+ export type Edge = import("./types.js").Edge;
7
+ export type JourneyGraph = import("./types.js").JourneyGraph;
8
+ export type Binding = import("./types.js").Binding;
9
+ export type Diagnostic = import("./types.js").Diagnostic;
10
+ export type ParseResult = import("./types.js").ParseResult;
11
+ export type NodeConfig = import("./types.js").NodeConfig;
12
+ export type CatalogCall = import("./types.js").CatalogCall;
13
+ export type TaskEntry = import("./types.js").TaskEntry;
14
+ export type ScorerEntry = import("./types.js").ScorerEntry;
15
+ export type CatalogEntry = import("./types.js").CatalogEntry;
16
+ export type Catalog = import("./types.js").Catalog;
17
+ export type ScoreResult = import("./types.js").ScoreResult;
18
+ export type Gap = import("./types.js").Gap;
19
+ export type RunResult = import("./types.js").RunResult;
20
+ export type RunOptions = import("./types.js").RunOptions;
21
+ export { task, scorer, todo, hole, normalizeScoreResult, validateCatalog } from "./catalog.js";
22
+ export { run, runText, formatRunFailure } from "./run.js";
23
+ export { compile, compileText } from "./compile.js";
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Parse Markdown containing optional YAML frontmatter and the first Mermaid
3
+ * flowchart fence into the journey IR.
4
+ *
5
+ * Author mistakes are reported as diagnostics. This function only throws for
6
+ * ordinary JavaScript programmer errors outside the supported input contract.
7
+ *
8
+ * @param {string} text Markdown journey text.
9
+ * @returns {ParseResult}
10
+ */
11
+ export function parse(text: string): ParseResult;
12
+ export type ParsedTerm = {
13
+ id: string;
14
+ node?: Node;
15
+ };
16
+ export type ParsedEdge = {
17
+ from: ParsedTerm;
18
+ to: ParsedTerm;
19
+ label?: string;
20
+ };
21
+ export type Binding = import("./types.js").Binding;
22
+ export type Diagnostic = import("./types.js").Diagnostic;
23
+ export type Edge = import("./types.js").Edge;
24
+ export type JourneyGraph = import("./types.js").JourneyGraph;
25
+ export type Node = import("./types.js").Node;
26
+ export type NodeKind = import("./types.js").NodeKind;
27
+ export type ParseResult = import("./types.js").ParseResult;
package/dist/run.d.ts ADDED
@@ -0,0 +1,54 @@
1
+ /**
2
+ * @typedef {import('./types.js').Catalog} Catalog
3
+ * @typedef {import('./types.js').Diagnostic} Diagnostic
4
+ * @typedef {import('./types.js').ExecutedStep} ExecutedStep
5
+ * @typedef {import('./types.js').Gap} Gap
6
+ * @typedef {import('./types.js').GapSignal} GapSignal
7
+ * @typedef {import('./types.js').Node} Node
8
+ * @typedef {import('./types.js').ParseResult} ParseResult
9
+ * @typedef {import('./types.js').RunError} RunError
10
+ * @typedef {import('./types.js').RunOptions} RunOptions
11
+ * @typedef {import('./types.js').RunResult} RunResult
12
+ * @typedef {import('./types.js').ScoreStep} ScoreStep
13
+ */
14
+ /**
15
+ * Execute a parsed journey directly against a reusable catalog.
16
+ *
17
+ * Structural and catalog validation errors short-circuit before catalog
18
+ * functions run. Programmer errors in catalog definitions or scorer return
19
+ * shapes throw.
20
+ *
21
+ * @param {ParseResult} parsed Parsed journey.
22
+ * @param {Catalog} catalog Reusable catalog.
23
+ * @param {RunOptions} [options] Run options.
24
+ * @returns {Promise<RunResult>}
25
+ */
26
+ export function run(parsed: ParseResult, catalog: Catalog, options?: RunOptions): Promise<RunResult>;
27
+ /**
28
+ * Parse and execute a journey directly against a reusable catalog.
29
+ *
30
+ * @param {string} text Markdown journey text.
31
+ * @param {Catalog} catalog Reusable catalog.
32
+ * @param {RunOptions} [options] Run options.
33
+ * @returns {Promise<RunResult>}
34
+ */
35
+ export function runText(text: string, catalog: Catalog, options?: RunOptions): Promise<RunResult>;
36
+ /**
37
+ * Format diagnostics, gaps, runtime errors, and failed outcome scores for CLI
38
+ * output and generated node:test assertions.
39
+ *
40
+ * @param {RunResult} result Run result.
41
+ * @returns {string}
42
+ */
43
+ export function formatRunFailure(result: RunResult): string;
44
+ export type Catalog = import("./types.js").Catalog;
45
+ export type Diagnostic = import("./types.js").Diagnostic;
46
+ export type ExecutedStep = import("./types.js").ExecutedStep;
47
+ export type Gap = import("./types.js").Gap;
48
+ export type GapSignal = import("./types.js").GapSignal;
49
+ export type Node = import("./types.js").Node;
50
+ export type ParseResult = import("./types.js").ParseResult;
51
+ export type RunError = import("./types.js").RunError;
52
+ export type RunOptions = import("./types.js").RunOptions;
53
+ export type RunResult = import("./types.js").RunResult;
54
+ export type ScoreStep = import("./types.js").ScoreStep;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @typedef {object} InitOptions
3
+ * @property {boolean} [force] Overwrite starter files when they already exist.
4
+ */
5
+ /**
6
+ * Create a project-local Melusine starter.
7
+ *
8
+ * @param {string} cwd Target project directory.
9
+ * @param {InitOptions} [options] Init options.
10
+ * @returns {Promise<string[]>} Files written or updated.
11
+ */
12
+ export function initProject(cwd: string, options?: InitOptions): Promise<string[]>;
13
+ export type InitOptions = {
14
+ /**
15
+ * Overwrite starter files when they already exist.
16
+ */
17
+ force?: boolean | undefined;
18
+ };