@sprig-and-prose/sprig-universe 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 (45) hide show
  1. package/PHILOSOPHY.md +201 -0
  2. package/README.md +168 -0
  3. package/REFERENCE.md +355 -0
  4. package/biome.json +24 -0
  5. package/package.json +30 -0
  6. package/repositories/sprig-repository-github/index.js +29 -0
  7. package/src/ast.js +257 -0
  8. package/src/cli.js +1510 -0
  9. package/src/graph.js +950 -0
  10. package/src/index.js +46 -0
  11. package/src/ir.js +121 -0
  12. package/src/parser.js +1656 -0
  13. package/src/scanner.js +255 -0
  14. package/src/scene-manifest.js +856 -0
  15. package/src/util/span.js +46 -0
  16. package/src/util/text.js +126 -0
  17. package/src/validator.js +862 -0
  18. package/src/validators/mysql/connection.js +154 -0
  19. package/src/validators/mysql/schema.js +209 -0
  20. package/src/validators/mysql/type-compat.js +219 -0
  21. package/src/validators/mysql/validator.js +332 -0
  22. package/test/fixtures/amaranthine-mini.prose +53 -0
  23. package/test/fixtures/conflicting-universes-a.prose +8 -0
  24. package/test/fixtures/conflicting-universes-b.prose +8 -0
  25. package/test/fixtures/duplicate-names.prose +20 -0
  26. package/test/fixtures/first-line-aware.prose +32 -0
  27. package/test/fixtures/indented-describe.prose +18 -0
  28. package/test/fixtures/multi-file-universe-a.prose +15 -0
  29. package/test/fixtures/multi-file-universe-b.prose +15 -0
  30. package/test/fixtures/multi-file-universe-conflict-desc.prose +12 -0
  31. package/test/fixtures/multi-file-universe-conflict-title.prose +4 -0
  32. package/test/fixtures/multi-file-universe-with-title.prose +10 -0
  33. package/test/fixtures/named-document.prose +17 -0
  34. package/test/fixtures/named-duplicate.prose +22 -0
  35. package/test/fixtures/named-reference.prose +17 -0
  36. package/test/fixtures/relates-errors.prose +38 -0
  37. package/test/fixtures/relates-tier1.prose +14 -0
  38. package/test/fixtures/relates-tier2.prose +16 -0
  39. package/test/fixtures/relates-tier3.prose +21 -0
  40. package/test/fixtures/sprig-meta-mini.prose +62 -0
  41. package/test/fixtures/unresolved-relates.prose +15 -0
  42. package/test/fixtures/using-in-references.prose +35 -0
  43. package/test/fixtures/using-unknown.prose +8 -0
  44. package/test/universe-basic.test.js +804 -0
  45. package/tsconfig.json +15 -0
package/PHILOSOPHY.md ADDED
@@ -0,0 +1,201 @@
1
+ # 🌱 Why sprig exists
2
+
3
+ Modern systems are hard to understand — not because they’re poorly built, but because they’re *alive*.
4
+
5
+ They grow over time.
6
+ They accumulate history.
7
+ They reflect decisions made by different people, under different constraints, at different moments.
8
+
9
+ Most tooling assumes the opposite.
10
+
11
+ Most tooling assumes:
12
+
13
+ * there is a single source of truth
14
+ * that truth is owned
15
+ * and the primary goal is to *enforce* it
16
+
17
+ sprig starts from a different premise.
18
+
19
+ ---
20
+
21
+ ## sprig exists to help people **understand systems as they are**
22
+
23
+ sprig is not an ORM.
24
+ It is not a schema language.
25
+ It is not a framework that asks to be “in charge.”
26
+
27
+ Instead, sprig is an ecosystem for **describing**, **grounding**, and **gently interacting with** real systems over time.
28
+
29
+ It is designed to be useful:
30
+
31
+ * before execution
32
+ * before adoption is complete
33
+ * before certainty exists
34
+
35
+ Sometimes even *before intent exists*.
36
+
37
+ ---
38
+
39
+ ## Nouns before verbs
40
+
41
+ sprig favors **nouns over verbs**.
42
+
43
+ You describe:
44
+
45
+ * what exists
46
+ * how things relate
47
+ * what shape reality seems to have
48
+ * what identifiers appear to matter
49
+
50
+ You do not start by declaring:
51
+
52
+ * how things must change
53
+ * who owns enforcement
54
+ * or what actions are allowed
55
+
56
+ Verbs — migrations, transformations, ownership — are optional, explicit, and unlockable later.
57
+
58
+ This keeps sprig readable, calm, and safe to approach.
59
+
60
+ ---
61
+
62
+ ## Fuzzy first, precise later
63
+
64
+ Real systems are rarely known all at once.
65
+
66
+ sprig is designed for:
67
+
68
+ * partial knowledge
69
+ * evolving understanding
70
+ * incremental refinement
71
+
72
+ You can begin with:
73
+
74
+ * rough shapes
75
+ * optional fields
76
+ * multiple perspectives
77
+ * incomplete grounding
78
+
79
+ And move toward:
80
+
81
+ * tighter validation
82
+ * clearer identities
83
+ * stronger guarantees
84
+
85
+ Without losing information along the way.
86
+
87
+ sprig is **lossless by design**.
88
+
89
+ ---
90
+
91
+ ## Description is valuable on its own
92
+
93
+ A core belief of sprig is that **description has intrinsic value**.
94
+
95
+ Even without validation.
96
+ Even without execution.
97
+ Even without enforcement.
98
+
99
+ The Universe layer exists to support this:
100
+
101
+ * human-first modeling
102
+ * narrative structure
103
+ * exploration and orientation
104
+ * shared language across experience levels
105
+
106
+ New engineers learn faster.
107
+ Experienced engineers continue learning safely.
108
+
109
+ sprig helps systems be *read*.
110
+
111
+ ---
112
+
113
+ ## Grounding, not control
114
+
115
+ When sprig touches reality, it does so gently.
116
+
117
+ Scenes describe how abstract concepts appear in the real world:
118
+
119
+ * files
120
+ * databases
121
+ * tables
122
+ * shapes
123
+ * identifiers
124
+
125
+ Validation observes reality and reports back — calmly.
126
+
127
+ It does not punish.
128
+ It does not assume ownership.
129
+ It does not demand compliance.
130
+
131
+ Errors are grouped, contextualized, and human.
132
+
133
+ sprig doesn’t say *“this is wrong.”*
134
+ It says *“this is what I see.”*
135
+
136
+ ---
137
+
138
+ ## Sensing before changing
139
+
140
+ sprig’s natural evolution is:
141
+
142
+ **description → grounding → sensing → care**
143
+
144
+ Before systems change, they should be *felt*:
145
+
146
+ * row counts
147
+ * file counts
148
+ * freshness
149
+ * drift
150
+ * validation status
151
+
152
+ Observability is not a bolt-on feature — it is a continuation of grounding.
153
+
154
+ Only after sensing does it make sense to talk about:
155
+
156
+ * evolution helpers
157
+ * migrations
158
+ * safety analysis
159
+ * slowly unlocked verbs
160
+
161
+ Even then, everything remains optional.
162
+
163
+ ---
164
+
165
+ ## sprig is local-first and non-invasive
166
+
167
+ sprig runs where your systems live.
168
+
169
+ It reads files.
170
+ It connects locally.
171
+ It links to repositories without owning them.
172
+
173
+ You can adopt sprig:
174
+
175
+ * per directory
176
+ * per entity
177
+ * per scene
178
+ * per moment in time
179
+
180
+ There is no cliff.
181
+ There is no rewrite.
182
+ There is no lock-in.
183
+
184
+ sprig should *touch* systems — not dominate them.
185
+
186
+ ---
187
+
188
+ ## The goal
189
+
190
+ sprig exists to make systems:
191
+
192
+ * more legible
193
+ * more humane
194
+ * easier to learn
195
+ * safer to evolve
196
+
197
+ It is a companion, not a commander.
198
+
199
+ A field guide, not a rulebook.
200
+
201
+ 🌱
package/README.md ADDED
@@ -0,0 +1,168 @@
1
+ # sprig-universe
2
+
3
+ A minimal parser for the universe layer of Sprig, a declarative language for describing systems.
4
+
5
+ ## What it does
6
+
7
+ `sprig-universe` parses Sprig `.prose` files and extracts the universe structure, producing a JSON representation (`UniverseGraph`) that includes:
8
+
9
+ **v0 Simplification:**
10
+ - Automatic discovery: finds `universe.prose` marker and loads all prose files
11
+ - Dead simple defaults: no configuration required
12
+ - Single universe rule: exactly one universe declaration required across all files
13
+
14
+ - **Nodes**: Universe, series, book, and chapter declarations with their relationships
15
+ - **Edges**: `relates` declarations connecting concepts
16
+ - **Describe blocks**: Freeform text preserved exactly as authored
17
+ - **Unknown blocks**: Blocks like `references` and `documentation` are preserved with their raw content
18
+ - **Source spans**: File, line, column, and offset information for all nodes and blocks
19
+ - **Diagnostics**: Warnings for duplicate names and unresolved references
20
+
21
+ ## Installation
22
+
23
+ ```bash
24
+ npm install
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ ### CLI
30
+
31
+ #### Compile (v0 - Recommended)
32
+
33
+ The `compile` command uses automatic discovery to find and compile all prose files:
34
+
35
+ ```bash
36
+ sprig-universe compile
37
+ ```
38
+
39
+ **Discovery behavior:**
40
+ - Walks upward from the current directory to find `universe.prose` marker file
41
+ - Loads all `**/*.prose` files under the discovered root
42
+ - Automatically excludes: `.sprig/**`, `dist/**`, `node_modules/**`, `.git/**`
43
+ - Requires exactly one `universe` declaration across all files
44
+
45
+ **Options:**
46
+ - `--root <path>` - Override discovery start path (default: current directory)
47
+ - `--quiet` - Suppress observable header output
48
+ - `--config <path>` - Path to `sprig.config.json` (optional, uses defaults if not found)
49
+
50
+ **Observable header** (shown unless `--quiet`):
51
+ ```
52
+ Universe: <Name> (root: /path/to/root)
53
+ Loaded: <N> prose files
54
+ Ignored: .sprig/**, dist/**, node_modules/**, .git/**
55
+ ```
56
+
57
+ **Other commands:**
58
+ - `sprig-universe watch` - Watch files and recompile on change
59
+ - `sprig-universe check:references` - Validate repository references
60
+ - `sprig-universe validate` - Validate scene sources
61
+
62
+ #### Parse (Legacy)
63
+
64
+ Parse a single file:
65
+
66
+ ```bash
67
+ sprig-universe parse path/to/file.prose
68
+ ```
69
+
70
+ Parse a directory (recursively finds all `*.prose` files):
71
+
72
+ ```bash
73
+ sprig-universe parse path/to/directory
74
+ ```
75
+
76
+ Output to a file:
77
+
78
+ ```bash
79
+ sprig-universe parse path/to/file.prose --out output.json
80
+ ```
81
+
82
+ The CLI exits with a non-zero code if there are any error-level diagnostics.
83
+
84
+ ### Programmatic API
85
+
86
+ ```javascript
87
+ import { parseFiles, parseText } from './src/index.js';
88
+
89
+ // Parse a single text string
90
+ const ast = parseText(sourceText, 'filename.prose');
91
+
92
+ // Parse multiple files into a single graph
93
+ const graph = parseFiles([
94
+ { file: 'file1.prose', text: sourceText1 },
95
+ { file: 'file2.prose', text: sourceText2 },
96
+ ]);
97
+ ```
98
+
99
+ ## Supported Syntax
100
+
101
+ The parser supports the universe layer of Sprig:
102
+
103
+ - `universe <Name> { ... }` - Top-level universe declaration
104
+ - `series <Name> { ... }` - Series within a universe
105
+ - `book <Name> in <ParentName> { ... }` - Book within a series or book
106
+ - `chapter <Name> in <ParentName> { ... }` - Chapter within a book
107
+ - `relates <A> and <B> { ... }` - Relationship between concepts
108
+ - `describe { ... }` - Freeform text block (preserves raw content including braces)
109
+ - Unknown blocks (e.g., `references { ... }`, `documentation { ... }`) - Preserved as-is
110
+
111
+ Comments start with `--` and continue to the end of the line.
112
+
113
+ ## Output Format
114
+
115
+ The parser produces a `UniverseGraph` JSON structure:
116
+
117
+ ```json
118
+ {
119
+ "version": 1,
120
+ "universes": {
121
+ "UniverseName": {
122
+ "name": "UniverseName",
123
+ "root": "UniverseName:universe:UniverseName"
124
+ }
125
+ },
126
+ "nodes": {
127
+ "UniverseName:series:SeriesName": {
128
+ "id": "UniverseName:series:SeriesName",
129
+ "kind": "series",
130
+ "name": "SeriesName",
131
+ "parent": "UniverseName:universe:UniverseName",
132
+ "children": [],
133
+ "describe": { "raw": "...", "source": {...} },
134
+ "source": {...}
135
+ }
136
+ },
137
+ "edges": {
138
+ "UniverseName:relates:A--B:0": {
139
+ "id": "UniverseName:relates:A--B:0",
140
+ "kind": "relates",
141
+ "a": { "text": "A", "target": "..." },
142
+ "b": { "text": "B", "target": "..." },
143
+ "source": {...}
144
+ }
145
+ },
146
+ "diagnostics": []
147
+ }
148
+ ```
149
+
150
+ ## Development
151
+
152
+ ```bash
153
+ # Format code
154
+ npm run format
155
+
156
+ # Lint code
157
+ npm run lint
158
+
159
+ # Type check (JSDoc types)
160
+ npm run typecheck
161
+
162
+ # Run tests
163
+ npm test
164
+ ```
165
+
166
+ ## License
167
+
168
+ ISC
package/REFERENCE.md ADDED
@@ -0,0 +1,355 @@
1
+ # 🌱 sprig Universe Prose — Quick Reference
2
+
3
+ *A compact guide to the universe layer of prose.*
4
+
5
+ ---
6
+
7
+ ## What the Universe layer is for
8
+
9
+ Use the Universe layer to:
10
+
11
+ * describe **what exists**
12
+ * name **concepts and domains**
13
+ * express **relationships and perspectives**
14
+ * provide **human-first orientation**
15
+ * link concepts to real artifacts (repos, paths, docs)
16
+
17
+ The Universe layer is:
18
+
19
+ * read-first
20
+ * plural by convention
21
+ * non-executable
22
+ * safe to explore without intent to change anything
23
+
24
+ ### String literals
25
+
26
+ All string literals in prose use **single quotes (`'`)**, not double quotes.
27
+
28
+ Single quotes are intentionally chosen to read as static, descriptive values,
29
+ not dynamic or interpolated strings.
30
+
31
+ In practice, this is not a usability burden:
32
+ most writing in prose happens inside `describe`, `note`, and `documentation`
33
+ blocks, which do not require quoting at all.
34
+
35
+ ---
36
+
37
+ ## Core blocks
38
+
39
+ ### `universe`
40
+
41
+ Top-level container for a body of knowledge.
42
+
43
+ ```sprig
44
+ universe GameWorld {
45
+ describe {
46
+ A high-level model of the game’s systems and domains.
47
+ }
48
+ }
49
+ ```
50
+
51
+ * Usually singular and conceptual
52
+ * Holds series, books, or entities directly
53
+
54
+ ---
55
+
56
+ ### `series`
57
+
58
+ Groups related books or topics.
59
+
60
+ ```sprig
61
+ series Items {
62
+ describe {
63
+ Everything related to items and inventories.
64
+ }
65
+ }
66
+ ```
67
+
68
+ * Optional
69
+ * Useful for large domains
70
+ * Named in the plural
71
+
72
+ ---
73
+
74
+ ### `book`
75
+
76
+ A readable unit of knowledge about a domain.
77
+
78
+ ```sprig
79
+ book Items {
80
+ describe {
81
+ Items represent objects that can exist in the world.
82
+ }
83
+ }
84
+ ```
85
+
86
+ * Plural by convention
87
+ * Think “a book about X”
88
+ * Can contain chapters and relationships
89
+
90
+ ---
91
+
92
+ ### `chapter`
93
+
94
+ A subsection within a book.
95
+
96
+ ```sprig
97
+ chapter Quality {
98
+ describe {
99
+ Item quality affects rarity and behavior.
100
+ }
101
+ }
102
+ ```
103
+
104
+ * Optional
105
+ * Use for structure and scannability
106
+ * Reads like documentation, not schema
107
+
108
+ ---
109
+
110
+ ## Relationships
111
+
112
+ ### `relates A and B`
113
+
114
+ Declares a relationship between two universe entities.
115
+
116
+ ```sprig
117
+ relates Items and Skills {
118
+ from Items {
119
+ relationships { 'can grant' }
120
+ }
121
+
122
+ from Skills {
123
+ relationships { 'can be granted by' }
124
+ }
125
+
126
+ describe {
127
+ Certain items grant skills when equipped or consumed.
128
+ }
129
+ }
130
+ ```
131
+
132
+ Key points:
133
+
134
+ * Relationships are **plural**
135
+ * Perspectives are symmetric but labeled differently
136
+ * `describe` provides narrative context
137
+ * No directionality is enforced — this is about understanding
138
+
139
+ ---
140
+
141
+ ## Documentation blocks
142
+
143
+ ### `describe`
144
+
145
+ Human explanation. The most important block.
146
+
147
+ ```sprig
148
+ describe {
149
+ Items can be stored, consumed, equipped, or traded.
150
+ }
151
+ ```
152
+
153
+ * Freeform text
154
+ * Encouraged everywhere
155
+ * No required format
156
+ * Calm, explanatory tone preferred
157
+
158
+ ---
159
+
160
+ ### `title`
161
+
162
+ Entities are automatically converted into title-case, but sometimes that's not enough.
163
+
164
+ ```sprig
165
+ chapter TimeBasedEffects {
166
+ title { Time-Based Effects }
167
+ }
168
+ ```
169
+
170
+ * Follows the same rules as `describe`
171
+
172
+ ### `note`
173
+
174
+ Notes are developer artifacts. They shouldn't be rendered, but they should be parsed and preserved for posterity. They are not intended for end-user documentation.
175
+
176
+ ```sprig
177
+ chapter CodeMonsters {
178
+ note {
179
+ Remember to write about that one time I accidentally hard-deleted 400,000 documents.
180
+ }
181
+ }
182
+ ```
183
+
184
+ * Follows the same rules as `describe`
185
+
186
+ ### `documentation`
187
+
188
+ Longer-form or structured explanation.
189
+
190
+ ```sprig
191
+ documentation {
192
+ document DocumentName {
193
+ kind { 'internal' }
194
+ path { '/docs/items/document-name.md' }
195
+ describe {
196
+ This document contains additional details about documents.
197
+ }
198
+ }
199
+
200
+ document {
201
+ ...
202
+ }
203
+ }
204
+ ```
205
+
206
+ * Optional
207
+ * Use when `describe` isn’t enough
208
+ * May render differently in UI later
209
+
210
+ ---
211
+
212
+ ### `references`
213
+
214
+ Links to real-world artifacts.
215
+
216
+ ```sprig
217
+ references {
218
+ reference {
219
+ describe {
220
+ These files contain information about references.
221
+ }
222
+
223
+ repository { 'repo-name' }
224
+ paths {
225
+ '/data/references.yaml',
226
+ '/data/references.json',
227
+ }
228
+ }
229
+
230
+ reference {
231
+ repository { 'repo-name' }
232
+ paths { '/src/routers/references.js' }
233
+ }
234
+ }
235
+ ```
236
+
237
+ You can also reuse named references defined at the universe scope:
238
+
239
+ ```sprig
240
+ references {
241
+ reference {
242
+ repository { 'repo-name' }
243
+ paths { '/src/helpers.ts' }
244
+ }
245
+
246
+ using { ItemRouter, PlayerRouter }
247
+ }
248
+ ```
249
+
250
+ * Non-owning
251
+ * Informational only
252
+ * Used for navigation and grounding
253
+ * `paths` may contain one or more file paths
254
+ * Mix inline `reference { ... }` entries with `using { Name }` to reuse named references
255
+
256
+ ---
257
+
258
+ ## Named artifacts
259
+
260
+ ### Named references
261
+
262
+ Define reusable references at the universe scope:
263
+
264
+ ```sprig
265
+ universe GameWorld {
266
+ reference ItemRouter {
267
+ repository { 'amaranthine-backend' }
268
+ paths { '/src/routers/items.ts' }
269
+ describe { Routes that implement item endpoints. }
270
+ }
271
+
272
+ reference PlayerRouter {
273
+ repository { 'amaranthine-backend' }
274
+ paths { '/src/routers/players.ts' }
275
+ }
276
+
277
+ series Items {
278
+ references {
279
+ using { ItemRouter }
280
+ }
281
+ }
282
+ }
283
+ ```
284
+
285
+ * Named references are defined at universe scope
286
+ * Can be reused via `using { Name }` inside `references` blocks
287
+ * Useful for common references shared across multiple entities
288
+ * Each name must be unique within a universe
289
+
290
+ ### Named documents
291
+
292
+ Define reusable documents at the universe scope:
293
+
294
+ ```sprig
295
+ universe GameWorld {
296
+ document ItemsDesignDoc {
297
+ kind { 'internal' }
298
+ path { '/docs/items/overview.md' }
299
+ describe { High-level items design notes. }
300
+ }
301
+
302
+ series Items {
303
+ documentation {
304
+ document {
305
+ kind { 'internal' }
306
+ path { '/docs/items/details.md' }
307
+ }
308
+ }
309
+ }
310
+ }
311
+ ```
312
+
313
+ * Named documents are defined at universe scope
314
+ * Can be referenced later (future: via `using { Name }` in `documentation` blocks)
315
+ * Useful for shared documentation artifacts
316
+ * Each name must be unique within a universe
317
+
318
+ ---
319
+
320
+ ## Naming conventions (recommended)
321
+
322
+ | Context | Convention | Rationale |
323
+ | ----------------- | ------------------ | ------------------------------ |
324
+ | Universe entities | **Plural** | You are reading about a domain |
325
+ | Books / series | **Plural** | Bodies of knowledge |
326
+ | Chapters | Singular or plural | Natural language |
327
+ | Relationships | Plural | Express populations |
328
+ | Scenes / actors | **Singular** | Describe one participant |
329
+
330
+ These are conventions, not enforcement.
331
+
332
+ ---
333
+
334
+ ## What Universe prose does *not* do
335
+
336
+ * No validation
337
+ * No execution
338
+ * No ownership
339
+ * No enforcement
340
+ * No “correctness” guarantees
341
+
342
+ Universe prose exists to be:
343
+
344
+ * read
345
+ * explored
346
+ * understood
347
+ * evolved over time
348
+
349
+ ---
350
+
351
+ ## Mental model
352
+
353
+ > Universe prose is closer to a field guide than a schema.
354
+ > It tells you what kinds of things exist and how they relate —
355
+ > not what you must do with them.