@pfdsl/core 0.0.1

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 takasek
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,150 @@
1
+ # @pfdsl/core
2
+
3
+ Core pipeline for the PFDSL process-flow DSL: lex → parse → normalize → build graph → validate → sort → format.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pnpm add @pfdsl/core
9
+ ```
10
+
11
+ Requires Node ≥ 18 (ESM only).
12
+
13
+ ## Quick start
14
+
15
+ ```ts
16
+ import { format } from '@pfdsl/core';
17
+
18
+ const source = `
19
+ [requirement, constraint] >> design -> spec
20
+ spec >>? design
21
+ `;
22
+
23
+ const { output, diagnostics } = format(source);
24
+ const errors = diagnostics.filter(d => d.severity === 'error');
25
+
26
+ if (errors.length === 0) {
27
+ console.log(output);
28
+ }
29
+ ```
30
+
31
+ `format()` is idempotent: `format(format(x).output).output === format(x).output`.
32
+
33
+ ## API
34
+
35
+ ### `format(source: string): FormatResult`
36
+
37
+ Run the full pipeline and return canonical text plus all diagnostics.
38
+
39
+ ```ts
40
+ interface FormatResult {
41
+ output: string; // canonical edge list, one edge per line
42
+ diagnostics: Diagnostic[]; // frontmatter + lex + parse + normalize + validate
43
+ }
44
+ ```
45
+
46
+ ### Stage-by-stage API
47
+
48
+ For tools that need intermediate state (LSP, exporters):
49
+
50
+ ```ts
51
+ import {
52
+ parse, // source → { document, frontmatter, diagnostics }
53
+ normalizeDocument, // document → { edges, nodeKinds, diagnostics }
54
+ buildGraph, // edges → graph (primary + feedback + nodes)
55
+ validateGraph, // graph → diagnostics
56
+ sortEdges, // edges + graph → canonically sorted edges
57
+ formatEdges, // sorted edges → text
58
+ } from '@pfdsl/core';
59
+
60
+ const { document, frontmatter, diagnostics: parseDiags } = parse(source);
61
+ const { edges, nodeKinds } = normalizeDocument(document, frontmatter);
62
+ const graph = buildGraph(edges, nodeKinds);
63
+ const validateDiags = validateGraph(edges, graph, frontmatter);
64
+ const sorted = sortEdges(edges, graph);
65
+ const text = formatEdges(sorted);
66
+ ```
67
+
68
+ All AST / token / diagnostic / graph types are exported as type-only.
69
+
70
+ ## DSL syntax (cheat sheet)
71
+
72
+ ```pfdsl
73
+ --- # optional YAML frontmatter
74
+ artifact:
75
+ spec:
76
+ label: 仕様書
77
+ process:
78
+ design:
79
+ label: 設計
80
+ build:
81
+ label: 実装
82
+ parts: [design] # composition (build is decomposed into design)
83
+ ---
84
+
85
+ # Edges
86
+ A >> P # A is input to process P
87
+ P -> B # P produces artifact B
88
+ A >>? P # feedback edge (semantic only)
89
+
90
+ # Chain
91
+ A >> P -> B >> Q -> C # A→P→B→Q→C, multiple segments
92
+
93
+ # Set notation (Cartesian product)
94
+ [a, b] >> P -> [x, y] # 2 inputs × 2 outputs = 4 edges
95
+
96
+ # Line continuation
97
+ [a, b, c]
98
+ >> P -> result # leading-op continuation OK
99
+ A >> P
100
+ -> B # continuation before -> OK
101
+
102
+ # Comments and blank lines
103
+ # this is a comment
104
+ [a, b] # blank line below would terminate the statement
105
+ >> P -> X
106
+ ```
107
+
108
+ Full grammar and validation rules: see [docs/spec/spec.md](../../docs/spec/spec.md).
109
+
110
+ ## Diagnostics
111
+
112
+ Errors and warnings are returned in `diagnostics` arrays, never thrown.
113
+ Each diagnostic carries:
114
+
115
+ ```ts
116
+ interface Diagnostic {
117
+ severity: 'error' | 'warning' | 'info';
118
+ code: string; // FM001, L001, P005, N002, V003, ...
119
+ message: string;
120
+ range: { start: Position; end: Position };
121
+ }
122
+ ```
123
+
124
+ Code prefixes: `FM` frontmatter, `L` lexer, `P` parser, `N` normalizer, `V` validator.
125
+
126
+ ## Validation rules
127
+
128
+ - **V001** Each artifact must have at most one producing process (single source).
129
+ - **V002 / V003** Every process must have ≥1 input and ≥1 output.
130
+ - **V004 – V006** `parts:` declarations must reference processes, must not self-reference, and must not form cycles.
131
+
132
+ ## Canonical ordering
133
+
134
+ `sortEdges` produces a stable order independent of input ordering:
135
+
136
+ 1. Connected component (by smallest node ID in component)
137
+ 2. Topological rank (longest path from a source artifact)
138
+ 3. Edge kind (`input` < `feedback` < `output`)
139
+ 4. Lexicographic tiebreak
140
+
141
+ This makes `format()` output suitable for diffing and version control.
142
+
143
+ ## Development
144
+
145
+ ```bash
146
+ pnpm install
147
+ pnpm --filter @pfdsl/core build
148
+ pnpm --filter @pfdsl/core test
149
+ pnpm --filter @pfdsl/core typecheck
150
+ ```
@@ -0,0 +1,432 @@
1
+ type TokenType = "ARROW_FEEDBACK" | "ARROW_INPUT" | "ARROW_OUTPUT" | "LBRACKET" | "RBRACKET" | "COMMA" | "SEMICOLON" | "NEWLINE" | "COMMENT" | "ID" | "EOF";
2
+ interface Position {
3
+ line: number;
4
+ column: number;
5
+ offset: number;
6
+ }
7
+ interface Token {
8
+ type: TokenType;
9
+ value: string;
10
+ raw: string;
11
+ start: Position;
12
+ end: Position;
13
+ }
14
+
15
+ type DiagnosticSeverity = "error" | "warning" | "info";
16
+ interface Range {
17
+ start: Position;
18
+ end: Position;
19
+ }
20
+ interface Diagnostic {
21
+ severity: DiagnosticSeverity;
22
+ code: string;
23
+ message: string;
24
+ range: Range;
25
+ }
26
+
27
+ declare const STATUS_VALUES: readonly ["done", "wip", "todo", "blocked"];
28
+ type Status = (typeof STATUS_VALUES)[number];
29
+ declare const STYLE_ATTRS: readonly ["fillcolor", "color", "fontcolor", "style", "penwidth"];
30
+ type StyleAttr = (typeof STYLE_ATTRS)[number];
31
+ type NodeStyle = Partial<Record<StyleAttr, string>>;
32
+ interface ArtifactMeta {
33
+ label?: string;
34
+ description?: string;
35
+ owner?: string;
36
+ externalStakeholders?: string[];
37
+ parts?: string[];
38
+ /** Optional positive-integer node index (pfd-tools D{index}). Namespace independent from processes. */
39
+ index?: number;
40
+ status?: Status;
41
+ tags?: string[];
42
+ group?: string;
43
+ criteria?: string;
44
+ location?: string | string[];
45
+ revises?: string;
46
+ [key: string]: unknown;
47
+ }
48
+ interface ProcessMeta {
49
+ label?: string;
50
+ description?: string;
51
+ owner?: string;
52
+ externalStakeholders?: string[];
53
+ /** Optional positive-integer node index (pfd-tools P{index}). Namespace independent from artifacts. */
54
+ index?: number;
55
+ group?: string;
56
+ tags?: string[];
57
+ command?: string;
58
+ /** Relative path to a child .pfdsl expanded as a subflow view-link (§2.9.3). */
59
+ subflow?: string;
60
+ /** Optional 1:1 boundary rename map (parent id → child id) for a subflow (§2.9.3). */
61
+ boundary?: Record<string, string>;
62
+ [key: string]: unknown;
63
+ }
64
+ interface GroupMeta {
65
+ label?: string;
66
+ color?: string;
67
+ parent?: string;
68
+ [key: string]: unknown;
69
+ }
70
+ interface TagMeta {
71
+ label?: string;
72
+ description?: string;
73
+ style?: NodeStyle;
74
+ [key: string]: unknown;
75
+ }
76
+ interface Frontmatter {
77
+ title?: string;
78
+ version?: string | number;
79
+ dslVersion?: string;
80
+ description?: string;
81
+ tags?: string[];
82
+ layout?: {
83
+ direction?: "LR" | "RL" | "TB" | "BT";
84
+ maxWidth?: number;
85
+ [key: string]: unknown;
86
+ };
87
+ artifact?: Record<string, ArtifactMeta>;
88
+ process?: Record<string, ProcessMeta>;
89
+ group?: Record<string, GroupMeta>;
90
+ tag?: Record<string, TagMeta>;
91
+ statusStyles?: Partial<Record<Status, NodeStyle>>;
92
+ /** Relative path(s) to preset file(s) inherited for presentation keys (§2.9.4). */
93
+ extends?: string | string[];
94
+ [key: string]: unknown;
95
+ }
96
+ interface LoadResult {
97
+ frontmatter: Frontmatter | null;
98
+ body: string;
99
+ bodyStartLine: number;
100
+ diagnostics: Diagnostic[];
101
+ }
102
+
103
+ interface IdNode {
104
+ type: "id";
105
+ value: string;
106
+ raw: string;
107
+ start: Position;
108
+ end: Position;
109
+ }
110
+ interface ArtifactExpr {
111
+ type: "artifact-expr";
112
+ ids: IdNode[];
113
+ start: Position;
114
+ end: Position;
115
+ }
116
+ interface ChainSegment {
117
+ op: ">>" | ">>?";
118
+ process: IdNode;
119
+ /** null when chain ends with bare `>> process` (output defined elsewhere) */
120
+ output: ArtifactExpr | null;
121
+ }
122
+ interface ChainStatement {
123
+ type: "chain";
124
+ head: ArtifactExpr;
125
+ segments: ChainSegment[];
126
+ start: Position;
127
+ end: Position;
128
+ }
129
+ interface InputEdgeStatement {
130
+ type: "input-edge";
131
+ artifact: ArtifactExpr;
132
+ process: IdNode;
133
+ start: Position;
134
+ end: Position;
135
+ }
136
+ interface FeedbackEdgeStatement {
137
+ type: "feedback-edge";
138
+ artifact: ArtifactExpr;
139
+ process: IdNode;
140
+ start: Position;
141
+ end: Position;
142
+ }
143
+ interface OutputEdgeStatement {
144
+ type: "output-edge";
145
+ process: IdNode;
146
+ artifact: ArtifactExpr;
147
+ start: Position;
148
+ end: Position;
149
+ }
150
+ interface NodeDeclStatement {
151
+ type: "node-decl";
152
+ id: IdNode;
153
+ start: Position;
154
+ end: Position;
155
+ }
156
+ type Statement = ChainStatement | InputEdgeStatement | FeedbackEdgeStatement | OutputEdgeStatement | NodeDeclStatement;
157
+ interface Document {
158
+ type: "document";
159
+ statements: Statement[];
160
+ }
161
+
162
+ type NormalizedEdge = {
163
+ kind: "input";
164
+ artifact: string;
165
+ process: string;
166
+ } | {
167
+ kind: "feedback";
168
+ artifact: string;
169
+ process: string;
170
+ } | {
171
+ kind: "output";
172
+ process: string;
173
+ artifact: string;
174
+ };
175
+
176
+ type NodeKind = "artifact" | "process" | "group";
177
+ interface PrimaryEdge {
178
+ from: string;
179
+ to: string;
180
+ kind: "input" | "output";
181
+ }
182
+ interface FeedbackEdge {
183
+ artifact: string;
184
+ process: string;
185
+ }
186
+ interface Graph {
187
+ nodes: Map<string, NodeKind>;
188
+ primaryEdges: PrimaryEdge[];
189
+ feedbackEdges: FeedbackEdge[];
190
+ }
191
+
192
+ interface AuditResult {
193
+ /** Artifacts produced by a process but not consumed by any process */
194
+ terminals: string[];
195
+ /** Artifacts consumed by a process but not produced by any process */
196
+ externalInputs: string[];
197
+ }
198
+ /**
199
+ * Inspect the primary graph for terminal artifacts and external inputs.
200
+ *
201
+ * Feedback edges are ignored: only `input` and `output` edges count as
202
+ * production/consumption in the primary graph.
203
+ *
204
+ * Artifacts with a non-empty `externalStakeholders` list are treated as
205
+ * having an external consumer and are excluded from terminals.
206
+ */
207
+ declare function auditGraph(edges: NormalizedEdge[], nodeKinds: Map<string, NodeKind>, artifactMeta?: Record<string, ArtifactMeta>): AuditResult;
208
+
209
+ declare function formatEdges(sortedEdges: NormalizedEdge[], sortedIsolated?: string[]): string;
210
+ declare function formatAsFlows(sortedEdges: NormalizedEdge[], sortedIsolated?: string[]): string;
211
+
212
+ declare function loadFrontmatter(source: string): LoadResult;
213
+
214
+ declare function buildGraph(edges: NormalizedEdge[], nodeKinds: Map<string, NodeKind>): Graph;
215
+
216
+ interface NormalizeResult {
217
+ edges: NormalizedEdge[];
218
+ nodeKinds: Map<string, "artifact" | "process" | "group">;
219
+ isolatedNodes: Set<string>;
220
+ diagnostics: Diagnostic[];
221
+ }
222
+ declare function normalize(doc: Document, fm: Frontmatter | null): NormalizeResult;
223
+
224
+ declare function sortIsolated(isolatedNodes: Set<string>): string[];
225
+ declare function sortEdges(edges: NormalizedEdge[], graph: Graph): NormalizedEdge[];
226
+
227
+ interface ValidateOptions {
228
+ strict?: boolean;
229
+ source?: string;
230
+ }
231
+ declare function validate(edges: NormalizedEdge[], nodeKinds: Map<string, NodeKind>, fm: Frontmatter | null, options?: ValidateOptions): Diagnostic[];
232
+
233
+ interface DiffReport {
234
+ addedNodes: string[];
235
+ removedNodes: string[];
236
+ changedNodes: string[];
237
+ addedEdges: string[];
238
+ removedEdges: string[];
239
+ addedFeedback: string[];
240
+ removedFeedback: string[];
241
+ }
242
+ declare function diffGraphs(a: Graph, b: Graph, fmA?: Frontmatter | null, fmB?: Frontmatter | null): DiffReport;
243
+
244
+ declare const ID_PATTERN: RegExp;
245
+ interface LexResult {
246
+ tokens: Token[];
247
+ diagnostics: Diagnostic[];
248
+ }
249
+
250
+ interface ParseResult {
251
+ document: Document;
252
+ diagnostics: Diagnostic[];
253
+ }
254
+
255
+ interface IndexChange {
256
+ kind: NodeKind;
257
+ id: string;
258
+ /** Existing index, or null when the node had none. */
259
+ from: number | null;
260
+ to: number;
261
+ }
262
+ interface ReindexResult {
263
+ /** Source with index: assignments applied (unchanged on error). */
264
+ output: string;
265
+ /** Nodes whose index was assigned or changed (unchanged ones omitted). */
266
+ changes: IndexChange[];
267
+ diagnostics: Diagnostic[];
268
+ }
269
+ interface ReindexOptions {
270
+ /** Reassign every node from 1 (default: keep existing, fill only gaps). */
271
+ renumber?: boolean;
272
+ }
273
+ /**
274
+ * Assign integer `index:` values to nodes in topological order, with
275
+ * independent counters for processes and artifacts. Default mode fills only
276
+ * nodes lacking an index; `renumber` reassigns all from 1. Edits are applied
277
+ * surgically to the front matter text to preserve comments and formatting.
278
+ */
279
+ declare function reindex(source: string, opts?: ReindexOptions): ReindexResult;
280
+
281
+ type SortKey = "index" | "topological" | "group" | "id";
282
+ interface SortOptions {
283
+ by: SortKey[];
284
+ }
285
+ interface SortResult {
286
+ output: string;
287
+ changed: boolean;
288
+ diagnostics: Diagnostic[];
289
+ }
290
+ declare function sort(source: string, opts: SortOptions): SortResult;
291
+
292
+ declare function resolveMeta(fm: Frontmatter | null | undefined, kind: "artifact", id: string): ArtifactMeta | undefined;
293
+ declare function resolveMeta(fm: Frontmatter | null | undefined, kind: "process", id: string): ProcessMeta | undefined;
294
+ declare function resolveMeta(fm: Frontmatter | null | undefined, kind: "group", id: string): GroupMeta | undefined;
295
+ declare function resolveMeta(fm: Frontmatter | null | undefined, kind: "artifact" | "process", id: string): ArtifactMeta | ProcessMeta | undefined;
296
+ declare function resolveMeta(fm: Frontmatter | null | undefined, kind: NodeKind, id: string): ArtifactMeta | ProcessMeta | GroupMeta | undefined;
297
+
298
+ /**
299
+ * Result of resolving a cross-file reference (`subflow:` / `extends:`).
300
+ * Relative paths resolve against the containing file's directory (§2.9.2).
301
+ * Absolute paths and URLs are rejected.
302
+ */
303
+ type RefResult = {
304
+ ok: true;
305
+ path: string;
306
+ } | {
307
+ ok: false;
308
+ reason: "absolute" | "url";
309
+ };
310
+ /**
311
+ * Resolve a relative cross-file reference against the containing file (§2.9.2).
312
+ * Absolute paths and URLs (`://`) are not permitted.
313
+ */
314
+ declare function resolveRefPath(fromFile: string, ref: string): RefResult;
315
+ /** A subflow reference: the declaring process id and the child path. */
316
+ interface SubflowRef {
317
+ process: string;
318
+ ref: string;
319
+ }
320
+ /** Collect the `extends:` preset references from a frontmatter, in order (§2.9.4). */
321
+ declare function collectExtendsRefs(fm: Frontmatter): string[];
322
+ /** Collect the `subflow:` references declared by processes (§2.9.3). */
323
+ declare function collectSubflowRefs(fm: Frontmatter): SubflowRef[];
324
+ /** A document with at least its parsed frontmatter (what the loader walks). */
325
+ interface DocWithFrontmatter {
326
+ frontmatter: Frontmatter | null;
327
+ }
328
+ interface LoadedGraph<T> {
329
+ /** Resolved absolute path → loaded document, including the entry. */
330
+ docs: Map<string, T>;
331
+ /** Cross-file diagnostics: missing path (V021), circular subflow (V022). */
332
+ diagnostics: Diagnostic[];
333
+ }
334
+ /**
335
+ * Recursively load an entry .pfdsl and its `subflow:` children (§2.9.3 / §15.11).
336
+ * `load` reads + analyzes a file by absolute path, returning null when absent.
337
+ * Detects self-referential and multi-hop subflow cycles (V022) and missing
338
+ * paths (V021). Shared children reached by multiple parents load once.
339
+ */
340
+ declare function loadSubflowGraph<T extends DocWithFrontmatter>(entryPath: string, load: (path: string) => T | null): LoadedGraph<T>;
341
+ /**
342
+ * Compute the set of "open input" artifacts in a flow:
343
+ * artifacts that appear in the flow but have NO output edge producing them (§15.11).
344
+ */
345
+ declare function computeOpenInputs(edges: NormalizedEdge[]): Set<string>;
346
+ /**
347
+ * Compute the set of "terminal" artifacts in a flow:
348
+ * artifacts that appear in the flow but are consumed by NEITHER `>>` (input) NOR `>>?` (feedback) (§15.11).
349
+ */
350
+ declare function computeTerminals(edges: NormalizedEdge[]): Set<string>;
351
+ /** Context for validating a single subflow boundary (§15.11). */
352
+ interface SubflowBoundaryContext {
353
+ processId: string;
354
+ /** Artifact IDs from parent's `>>` (normal input, NOT feedback) edges into this process. */
355
+ parentNormalInputs: Set<string>;
356
+ /** Artifact IDs from parent's `->` (output) edges from this process. */
357
+ parentOutputs: Set<string>;
358
+ /** boundary: map from frontmatter (parent_id → child_id). Empty object if no boundary. */
359
+ boundaryMap: Record<string, string>;
360
+ childOpenInputs: Set<string>;
361
+ childTerminals: Set<string>;
362
+ }
363
+ /**
364
+ * Validate the boundary between a parent process and its subflow child (§15.11).
365
+ * Returns V025 diagnostics for any violations.
366
+ */
367
+ declare function validateSubflowBoundary(ctx: SubflowBoundaryContext): Diagnostic[];
368
+ /**
369
+ * Recursively load an entry file and its `extends:` preset chain (§2.9.4 / §15.12).
370
+ * `load` reads + analyzes a file by absolute path, returning null when absent.
371
+ * Detects self-referential and multi-hop extends cycles (V027) and missing
372
+ * paths / invalid paths (V026). Diamond-shaped presets (same file reachable via
373
+ * multiple paths) are loaded only once — not treated as a cycle.
374
+ */
375
+ declare function loadExtendsChain<T extends DocWithFrontmatter>(entryPath: string, load: (path: string) => T | null): LoadedGraph<T>;
376
+ /**
377
+ * Validate that a preset file only contains presentation-layer keys (§2.9.5).
378
+ * Returns V028 diagnostics for every forbidden key found.
379
+ */
380
+ declare function validatePresetKeys(path: string, fm: Frontmatter | null): Diagnostic[];
381
+ /** The merged presentation values resolved from an extends chain. */
382
+ interface ResolvedPresentation {
383
+ statusStyles: Frontmatter["statusStyles"];
384
+ tag: Frontmatter["tag"];
385
+ group: Frontmatter["group"];
386
+ }
387
+ /**
388
+ * Merge statusStyles / tag / group from a sequence of frontmatters in order
389
+ * (lowest priority first, local last). Each element's values override the
390
+ * previous at attribute level (§2.9.4 "属性レベル深マージ").
391
+ */
392
+ declare function resolvePresentation(chain: {
393
+ path: string;
394
+ fm: Frontmatter | null;
395
+ }[]): ResolvedPresentation;
396
+
397
+ interface ParseDocResult {
398
+ document: Document;
399
+ frontmatter: Frontmatter | null;
400
+ bodyStartLine: number;
401
+ diagnostics: Diagnostic[];
402
+ }
403
+ interface FormatResult {
404
+ output: string;
405
+ diagnostics: Diagnostic[];
406
+ }
407
+ interface AnalyzeResult {
408
+ document: Document;
409
+ frontmatter: Frontmatter | null;
410
+ bodyStartLine: number;
411
+ edges: NormalizedEdge[];
412
+ nodeKinds: Map<string, NodeKind>;
413
+ isolatedNodes: Set<string>;
414
+ graph: Graph;
415
+ diagnostics: Diagnostic[];
416
+ }
417
+ declare function parse(source: string): ParseDocResult;
418
+
419
+ declare function hasErrors(diags: readonly Diagnostic[]): boolean;
420
+
421
+ interface AnalyzeOptions {
422
+ strict?: boolean;
423
+ }
424
+ declare function analyze(source: string, opts?: AnalyzeOptions): AnalyzeResult;
425
+ interface FormatOptions {
426
+ style?: "flat" | "flows";
427
+ skipValidation?: boolean;
428
+ }
429
+
430
+ declare function format(source: string, opts?: FormatOptions): FormatResult;
431
+
432
+ export { type AnalyzeOptions, type AnalyzeResult, type ArtifactExpr, type ArtifactMeta, type AuditResult, type ChainSegment, type ChainStatement, type Diagnostic, type DiagnosticSeverity, type DiffReport, type DocWithFrontmatter, type Document, type FeedbackEdge, type FeedbackEdgeStatement, type FormatOptions, type FormatResult, type Frontmatter, type Graph, type GroupMeta, ID_PATTERN, type IdNode, type IndexChange, type InputEdgeStatement, type LexResult, type LoadResult, type LoadedGraph, type NodeDeclStatement, type NodeKind, type NodeStyle, type NormalizeResult, type NormalizedEdge, type OutputEdgeStatement, type ParseDocResult, type ParseResult, type Position, type PrimaryEdge, type ProcessMeta, type Range, type ReindexOptions, type ReindexResult, type ResolvedPresentation, STATUS_VALUES, STYLE_ATTRS, type SortKey, type SortOptions, type SortResult, type Statement, type Status, type StyleAttr, type SubflowBoundaryContext, type SubflowRef, type Token, type TokenType, type ValidateOptions, analyze, auditGraph, buildGraph, collectExtendsRefs, collectSubflowRefs, computeOpenInputs, computeTerminals, diffGraphs, format, formatAsFlows, formatEdges, hasErrors, loadExtendsChain, loadFrontmatter, loadSubflowGraph, normalize as normalizeDocument, parse, reindex, resolveMeta, resolvePresentation, resolveRefPath, sort, sortEdges, sortIsolated, validate as validateGraph, validatePresetKeys, validateSubflowBoundary };