bonescript-compiler 0.2.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 (146) hide show
  1. package/LICENSE +21 -0
  2. package/dist/algorithm_catalog.d.ts +32 -0
  3. package/dist/algorithm_catalog.js +323 -0
  4. package/dist/algorithm_catalog.js.map +1 -0
  5. package/dist/ast.d.ts +244 -0
  6. package/dist/ast.js +8 -0
  7. package/dist/ast.js.map +1 -0
  8. package/dist/cli.d.ts +4 -0
  9. package/dist/cli.js +605 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/emit_batch.d.ts +7 -0
  12. package/dist/emit_batch.js +133 -0
  13. package/dist/emit_batch.js.map +1 -0
  14. package/dist/emit_capability.d.ts +7 -0
  15. package/dist/emit_capability.js +376 -0
  16. package/dist/emit_capability.js.map +1 -0
  17. package/dist/emit_composition.d.ts +22 -0
  18. package/dist/emit_composition.js +184 -0
  19. package/dist/emit_composition.js.map +1 -0
  20. package/dist/emit_deploy.d.ts +9 -0
  21. package/dist/emit_deploy.js +191 -0
  22. package/dist/emit_deploy.js.map +1 -0
  23. package/dist/emit_events.d.ts +14 -0
  24. package/dist/emit_events.js +305 -0
  25. package/dist/emit_events.js.map +1 -0
  26. package/dist/emit_extras.d.ts +12 -0
  27. package/dist/emit_extras.js +234 -0
  28. package/dist/emit_extras.js.map +1 -0
  29. package/dist/emit_full.d.ts +13 -0
  30. package/dist/emit_full.js +273 -0
  31. package/dist/emit_full.js.map +1 -0
  32. package/dist/emit_maintenance.d.ts +16 -0
  33. package/dist/emit_maintenance.js +442 -0
  34. package/dist/emit_maintenance.js.map +1 -0
  35. package/dist/emit_runtime.d.ts +13 -0
  36. package/dist/emit_runtime.js +691 -0
  37. package/dist/emit_runtime.js.map +1 -0
  38. package/dist/emit_sourcemap.d.ts +29 -0
  39. package/dist/emit_sourcemap.js +123 -0
  40. package/dist/emit_sourcemap.js.map +1 -0
  41. package/dist/emit_tests.d.ts +15 -0
  42. package/dist/emit_tests.js +185 -0
  43. package/dist/emit_tests.js.map +1 -0
  44. package/dist/emit_websocket.d.ts +6 -0
  45. package/dist/emit_websocket.js +223 -0
  46. package/dist/emit_websocket.js.map +1 -0
  47. package/dist/emitter.d.ts +25 -0
  48. package/dist/emitter.js +511 -0
  49. package/dist/emitter.js.map +1 -0
  50. package/dist/extension_manager.d.ts +38 -0
  51. package/dist/extension_manager.js +170 -0
  52. package/dist/extension_manager.js.map +1 -0
  53. package/dist/formatter.d.ts +34 -0
  54. package/dist/formatter.js +317 -0
  55. package/dist/formatter.js.map +1 -0
  56. package/dist/index.d.ts +42 -0
  57. package/dist/index.js +113 -0
  58. package/dist/index.js.map +1 -0
  59. package/dist/ir.d.ts +168 -0
  60. package/dist/ir.js +10 -0
  61. package/dist/ir.js.map +1 -0
  62. package/dist/lexer.d.ts +195 -0
  63. package/dist/lexer.js +619 -0
  64. package/dist/lexer.js.map +1 -0
  65. package/dist/lowering.d.ts +25 -0
  66. package/dist/lowering.js +500 -0
  67. package/dist/lowering.js.map +1 -0
  68. package/dist/module_loader.d.ts +25 -0
  69. package/dist/module_loader.js +126 -0
  70. package/dist/module_loader.js.map +1 -0
  71. package/dist/optimizer.d.ts +26 -0
  72. package/dist/optimizer.js +158 -0
  73. package/dist/optimizer.js.map +1 -0
  74. package/dist/parse_decls.d.ts +13 -0
  75. package/dist/parse_decls.js +442 -0
  76. package/dist/parse_decls.js.map +1 -0
  77. package/dist/parse_decls2.d.ts +13 -0
  78. package/dist/parse_decls2.js +295 -0
  79. package/dist/parse_decls2.js.map +1 -0
  80. package/dist/parse_expr.d.ts +7 -0
  81. package/dist/parse_expr.js +197 -0
  82. package/dist/parse_expr.js.map +1 -0
  83. package/dist/parse_types.d.ts +6 -0
  84. package/dist/parse_types.js +51 -0
  85. package/dist/parse_types.js.map +1 -0
  86. package/dist/parser.d.ts +10 -0
  87. package/dist/parser.js +62 -0
  88. package/dist/parser.js.map +1 -0
  89. package/dist/parser_base.d.ts +19 -0
  90. package/dist/parser_base.js +50 -0
  91. package/dist/parser_base.js.map +1 -0
  92. package/dist/parser_recovery.d.ts +26 -0
  93. package/dist/parser_recovery.js +140 -0
  94. package/dist/parser_recovery.js.map +1 -0
  95. package/dist/scaffold.d.ts +13 -0
  96. package/dist/scaffold.js +376 -0
  97. package/dist/scaffold.js.map +1 -0
  98. package/dist/solver.d.ts +26 -0
  99. package/dist/solver.js +281 -0
  100. package/dist/solver.js.map +1 -0
  101. package/dist/typechecker.d.ts +52 -0
  102. package/dist/typechecker.js +534 -0
  103. package/dist/typechecker.js.map +1 -0
  104. package/dist/types.d.ts +38 -0
  105. package/dist/types.js +85 -0
  106. package/dist/types.js.map +1 -0
  107. package/dist/verifier.d.ts +46 -0
  108. package/dist/verifier.js +307 -0
  109. package/dist/verifier.js.map +1 -0
  110. package/package.json +52 -0
  111. package/src/algorithm_catalog.ts +345 -0
  112. package/src/ast.ts +334 -0
  113. package/src/cli.ts +624 -0
  114. package/src/emit_batch.ts +140 -0
  115. package/src/emit_capability.ts +436 -0
  116. package/src/emit_composition.ts +196 -0
  117. package/src/emit_deploy.ts +190 -0
  118. package/src/emit_events.ts +307 -0
  119. package/src/emit_extras.ts +240 -0
  120. package/src/emit_full.ts +309 -0
  121. package/src/emit_maintenance.ts +459 -0
  122. package/src/emit_runtime.ts +731 -0
  123. package/src/emit_sourcemap.ts +140 -0
  124. package/src/emit_tests.ts +205 -0
  125. package/src/emit_websocket.ts +229 -0
  126. package/src/emitter.ts +566 -0
  127. package/src/extension_manager.ts +187 -0
  128. package/src/formatter.ts +297 -0
  129. package/src/index.ts +88 -0
  130. package/src/ir.ts +215 -0
  131. package/src/lexer.ts +630 -0
  132. package/src/lowering.ts +556 -0
  133. package/src/module_loader.ts +114 -0
  134. package/src/optimizer.ts +196 -0
  135. package/src/parse_decls.ts +409 -0
  136. package/src/parse_decls2.ts +244 -0
  137. package/src/parse_expr.ts +197 -0
  138. package/src/parse_types.ts +54 -0
  139. package/src/parser.ts +64 -0
  140. package/src/parser_base.ts +57 -0
  141. package/src/parser_recovery.ts +153 -0
  142. package/src/scaffold.ts +375 -0
  143. package/src/solver.ts +330 -0
  144. package/src/typechecker.ts +591 -0
  145. package/src/types.ts +122 -0
  146. package/src/verifier.ts +348 -0
@@ -0,0 +1,376 @@
1
+ "use strict";
2
+ /**
3
+ * BoneScript Project Scaffolder — `bone init`
4
+ * Creates a new BoneScript project with sensible defaults for a chosen domain.
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || function (mod) {
23
+ if (mod && mod.__esModule) return mod;
24
+ var result = {};
25
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
26
+ __setModuleDefault(result, mod);
27
+ return result;
28
+ };
29
+ Object.defineProperty(exports, "__esModule", { value: true });
30
+ exports.scaffold = void 0;
31
+ const fs = __importStar(require("fs"));
32
+ const path = __importStar(require("path"));
33
+ const TEMPLATES = {
34
+ multiplayer_game: `system MyGame {
35
+ domain: multiplayer_game
36
+
37
+ entity Player {
38
+ owns: [
39
+ username: string,
40
+ score: uint
41
+ ]
42
+ constraints: [
43
+ username.unique,
44
+ username.length in 3..32,
45
+ score >= 0
46
+ ]
47
+ states: active -> suspended | deleted
48
+ auth: jwt
49
+ }
50
+
51
+ capability award_points(player: Player, points: uint) {
52
+ requires: [points > 0, player.state == "active"]
53
+ effects: [player.score += points]
54
+ sync: eventual
55
+ }
56
+
57
+ store PlayerStore {
58
+ engine: postgresql
59
+ schema: {
60
+ id: uuid,
61
+ username: string,
62
+ score: uint,
63
+ state: string
64
+ }
65
+ }
66
+
67
+ channel game_lobby {
68
+ transport: websocket
69
+ ordering: causal
70
+ participants: set<Player>
71
+ persistence: last_100
72
+ }
73
+ }
74
+ `,
75
+ saas_platform: `system MySaaS {
76
+ domain: saas_platform
77
+
78
+ entity Tenant {
79
+ owns: [
80
+ name: string,
81
+ plan: string,
82
+ active: bool
83
+ ]
84
+ constraints: [
85
+ name.length in 1..100,
86
+ plan in ["free", "pro", "enterprise"]
87
+ ]
88
+ states: trialing -> active -> suspended | cancelled
89
+ auth: oauth2
90
+ }
91
+
92
+ entity User {
93
+ owns: [
94
+ email: string,
95
+ tenant_id: uuid,
96
+ role: string
97
+ ]
98
+ constraints: [
99
+ email.unique,
100
+ role in ["admin", "member", "viewer"]
101
+ ]
102
+ auth: oauth2
103
+ }
104
+
105
+ capability invite_user(tenant: Tenant, email: string, role: string) {
106
+ requires: [tenant.state == "active", role in ["admin", "member", "viewer"]]
107
+ effects: []
108
+ emits: UserInvited
109
+ sync: transactional
110
+ }
111
+
112
+ event UserInvited {
113
+ payload: {
114
+ tenant_id: uuid,
115
+ email: string,
116
+ role: string,
117
+ invited_at: timestamp
118
+ }
119
+ delivery: at_least_once
120
+ ttl: 7d
121
+ }
122
+
123
+ store TenantStore {
124
+ engine: postgresql
125
+ schema: {
126
+ id: uuid,
127
+ name: string,
128
+ plan: string,
129
+ active: bool,
130
+ state: string
131
+ }
132
+ }
133
+ }
134
+ `,
135
+ iot_system: `system MyIoT {
136
+ domain: iot_system
137
+
138
+ entity Device {
139
+ owns: [
140
+ serial: string,
141
+ firmware_version: string,
142
+ last_seen: timestamp,
143
+ battery: uint
144
+ ]
145
+ constraints: [
146
+ serial.unique,
147
+ battery <= 100
148
+ ]
149
+ states: online -> offline -> retired
150
+ auth: apikey
151
+ }
152
+
153
+ entity Reading {
154
+ owns: [
155
+ device_id: uuid,
156
+ sensor: string,
157
+ value: float,
158
+ recorded_at: timestamp
159
+ ]
160
+ }
161
+
162
+ capability ingest_reading(device: Device, sensor: string, value: float) {
163
+ requires: [device.state == "online"]
164
+ effects: [device.last_seen = now()]
165
+ emits: ReadingRecorded
166
+ sync: eventual
167
+ }
168
+
169
+ event ReadingRecorded {
170
+ payload: {
171
+ device_id: uuid,
172
+ sensor: string,
173
+ value: float
174
+ }
175
+ delivery: at_least_once
176
+ ttl: 1d
177
+ }
178
+
179
+ store DeviceStore {
180
+ engine: dynamodb
181
+ schema: {
182
+ id: uuid,
183
+ serial: string,
184
+ firmware_version: string,
185
+ battery: uint,
186
+ state: string
187
+ }
188
+ }
189
+ }
190
+ `,
191
+ social_network: `system MySocial {
192
+ domain: social_network
193
+
194
+ entity User {
195
+ owns: [
196
+ handle: string,
197
+ display_name: string,
198
+ followers: set<uuid>,
199
+ following: set<uuid>
200
+ ]
201
+ constraints: [
202
+ handle.unique,
203
+ handle.length in 3..30
204
+ ]
205
+ auth: oauth2
206
+ }
207
+
208
+ entity Post {
209
+ owns: [
210
+ author_id: uuid,
211
+ content: string,
212
+ likes: uint
213
+ ]
214
+ constraints: [
215
+ content.length in 1..500
216
+ ]
217
+ }
218
+
219
+ capability follow_user(follower: User, target: User) {
220
+ requires: [follower != target]
221
+ effects: [
222
+ follower.following += target.id,
223
+ target.followers += follower.id
224
+ ]
225
+ sync: eventual
226
+ }
227
+
228
+ channel feed {
229
+ transport: websocket
230
+ ordering: causal
231
+ participants: set<User>
232
+ persistence: last_100
233
+ }
234
+ }
235
+ `,
236
+ marketplace: `system MyMarket {
237
+ domain: marketplace
238
+
239
+ entity Listing {
240
+ owns: [
241
+ seller_id: uuid,
242
+ title: string,
243
+ price: uint,
244
+ stock: uint
245
+ ]
246
+ constraints: [
247
+ title.length in 1..200,
248
+ price > 0,
249
+ stock >= 0
250
+ ]
251
+ states: draft -> active -> sold_out | archived
252
+ auth: oauth2
253
+ }
254
+
255
+ entity Order {
256
+ owns: [
257
+ buyer_id: uuid,
258
+ listing_id: uuid,
259
+ quantity: uint,
260
+ total: uint
261
+ ]
262
+ states: pending -> paid -> shipped -> delivered | cancelled
263
+ }
264
+
265
+ capability purchase(buyer: User, listing: Listing, qty: uint) {
266
+ requires: [
267
+ listing.state == "active",
268
+ listing.stock >= qty
269
+ ]
270
+ effects: [
271
+ listing.stock -= qty
272
+ ]
273
+ emits: OrderCreated
274
+ sync: transactional
275
+ }
276
+
277
+ event OrderCreated {
278
+ payload: {
279
+ order_id: uuid,
280
+ buyer_id: uuid,
281
+ listing_id: uuid,
282
+ total: uint
283
+ }
284
+ delivery: exactly_once
285
+ ttl: 30d
286
+ }
287
+ }
288
+ `,
289
+ realtime_collaboration: `system MyCollab {
290
+ domain: realtime_collaboration
291
+
292
+ entity Document {
293
+ owns: [
294
+ title: string,
295
+ owner_id: uuid,
296
+ content: json,
297
+ version: uint
298
+ ]
299
+ constraints: [
300
+ version >= 1
301
+ ]
302
+ auth: jwt
303
+ }
304
+
305
+ entity Cursor {
306
+ owns: [
307
+ document_id: uuid,
308
+ user_id: uuid,
309
+ position: uint,
310
+ color: string
311
+ ]
312
+ }
313
+
314
+ capability apply_change(doc: Document, user: User, change: json) {
315
+ requires: [doc.owner_id == user.id or doc.collaborators contains user.id]
316
+ effects: [
317
+ doc.version += 1,
318
+ doc.content = change
319
+ ]
320
+ emits: DocumentChanged
321
+ sync: realtime
322
+ }
323
+
324
+ channel doc_session {
325
+ transport: websocket
326
+ ordering: causal
327
+ participants: set<User>
328
+ persistence: last_1000
329
+ }
330
+
331
+ event DocumentChanged {
332
+ payload: {
333
+ document_id: uuid,
334
+ user_id: uuid,
335
+ version: uint
336
+ }
337
+ delivery: at_least_once
338
+ ttl: 1d
339
+ }
340
+ }
341
+ `,
342
+ };
343
+ function scaffold(opts) {
344
+ const created = [];
345
+ if (!fs.existsSync(opts.outDir)) {
346
+ fs.mkdirSync(opts.outDir, { recursive: true });
347
+ }
348
+ // Main .bone file
349
+ const mainFile = path.join(opts.outDir, `${opts.name}.bone`);
350
+ let content = TEMPLATES[opts.domain];
351
+ // Replace placeholder system name with provided name
352
+ content = content.replace(/^system \w+ \{/, `system ${pascalCase(opts.name)} {`);
353
+ fs.writeFileSync(mainFile, content, "utf-8");
354
+ created.push(mainFile);
355
+ // README
356
+ const readmePath = path.join(opts.outDir, "README.md");
357
+ fs.writeFileSync(readmePath, `# ${opts.name}
358
+
359
+ BoneScript project (domain: ${opts.domain}).
360
+
361
+ ## Compile
362
+
363
+ \`\`\`bash
364
+ bone compile ${opts.name}.bone
365
+ \`\`\`
366
+
367
+ The output will be written to \`./output/\` as a complete Node.js project.
368
+ `, "utf-8");
369
+ created.push(readmePath);
370
+ return { created };
371
+ }
372
+ exports.scaffold = scaffold;
373
+ function pascalCase(s) {
374
+ return s.replace(/(^|[-_\s])(\w)/g, (_, __, c) => c.toUpperCase());
375
+ }
376
+ //# sourceMappingURL=scaffold.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,uCAAyB;AACzB,2CAA6B;AAU7B,MAAM,SAAS,GAAmC;IAChD,gBAAgB,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwCnB;IAEC,aAAa,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2DhB;IAEC,UAAU,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuDb;IAEC,cAAc,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4CjB;IAEC,WAAW,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoDd;IAEC,sBAAsB,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoDzB;CACA,CAAC;AAQF,SAAgB,QAAQ,CAAC,IAAqB;IAC5C,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QAChC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACjD,CAAC;IAED,kBAAkB;IAClB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,OAAO,CAAC,CAAC;IAC7D,IAAI,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACrC,qDAAqD;IACrD,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,gBAAgB,EAAE,UAAU,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjF,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC7C,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAEvB,SAAS;IACT,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACvD,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,KAAK,IAAI,CAAC,IAAI;;8BAEf,IAAI,CAAC,MAAM;;;;;eAK1B,IAAI,CAAC,IAAI;;;;CAIvB,EAAE,OAAO,CAAC,CAAC;IACV,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAEzB,OAAO,EAAE,OAAO,EAAE,CAAC;AACrB,CAAC;AAhCD,4BAgCC;AAED,SAAS,UAAU,CAAC,CAAS;IAC3B,OAAO,CAAC,CAAC,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AACrE,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * BoneScript Constraint Solver — Stage 5 of the compilation pipeline.
3
+ * Implements spec/06_CONSTRAINT_SOLVER.md.
4
+ *
5
+ * Resolves all underspecified aspects of the IR into concrete decisions.
6
+ * Uses ONLY: ontology implication rules, domain defaults, structural necessity.
7
+ * NO heuristics. NO probabilistic matching.
8
+ *
9
+ * Phases:
10
+ * 1. Collect — gather all constraints
11
+ * 2. Normalize — canonical form
12
+ * 3. Propagate — unit propagation
13
+ * 4. Check — verify consistency
14
+ * 5. Complete — fill remaining with defaults
15
+ * 6. Verify — final pass
16
+ */
17
+ import * as IR from "./ir";
18
+ export interface SolverResult {
19
+ resolution: Record<string, string>;
20
+ assumptions: string[];
21
+ warnings: string[];
22
+ errors: string[];
23
+ }
24
+ export declare class ConstraintSolver {
25
+ solve(system: IR.IRSystem): SolverResult;
26
+ }
package/dist/solver.js ADDED
@@ -0,0 +1,281 @@
1
+ "use strict";
2
+ /**
3
+ * BoneScript Constraint Solver — Stage 5 of the compilation pipeline.
4
+ * Implements spec/06_CONSTRAINT_SOLVER.md.
5
+ *
6
+ * Resolves all underspecified aspects of the IR into concrete decisions.
7
+ * Uses ONLY: ontology implication rules, domain defaults, structural necessity.
8
+ * NO heuristics. NO probabilistic matching.
9
+ *
10
+ * Phases:
11
+ * 1. Collect — gather all constraints
12
+ * 2. Normalize — canonical form
13
+ * 3. Propagate — unit propagation
14
+ * 4. Check — verify consistency
15
+ * 5. Complete — fill remaining with defaults
16
+ * 6. Verify — final pass
17
+ */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.ConstraintSolver = void 0;
20
+ const DOMAIN_DEFAULTS = {
21
+ multiplayer_game: {
22
+ auth: "jwt",
23
+ engine: "postgresql",
24
+ session_engine: "redis",
25
+ sync: "realtime",
26
+ channel_transport: "websocket",
27
+ channel_ordering: "causal",
28
+ channel_persistence: "last_100",
29
+ session_ttl_ms: 3600000,
30
+ max_connections: 10000,
31
+ rate_limit: 1000,
32
+ },
33
+ saas_platform: {
34
+ auth: "oauth2",
35
+ engine: "postgresql",
36
+ session_engine: "redis",
37
+ sync: "eventual",
38
+ channel_transport: "sse",
39
+ channel_ordering: "fifo",
40
+ channel_persistence: "full",
41
+ session_ttl_ms: 86400000,
42
+ max_connections: 5000,
43
+ rate_limit: 500,
44
+ },
45
+ iot_system: {
46
+ auth: "apikey",
47
+ engine: "dynamodb",
48
+ session_engine: "redis",
49
+ sync: "eventual",
50
+ channel_transport: "grpc_stream",
51
+ channel_ordering: "fifo",
52
+ channel_persistence: "last_1000",
53
+ session_ttl_ms: 7200000,
54
+ max_connections: 100000,
55
+ rate_limit: 10000,
56
+ },
57
+ social_network: {
58
+ auth: "oauth2",
59
+ engine: "postgresql",
60
+ session_engine: "redis",
61
+ sync: "eventual",
62
+ channel_transport: "websocket",
63
+ channel_ordering: "causal",
64
+ channel_persistence: "last_100",
65
+ session_ttl_ms: 86400000,
66
+ max_connections: 50000,
67
+ rate_limit: 2000,
68
+ },
69
+ marketplace: {
70
+ auth: "oauth2",
71
+ engine: "postgresql",
72
+ session_engine: "redis",
73
+ sync: "transactional",
74
+ channel_transport: "sse",
75
+ channel_ordering: "fifo",
76
+ channel_persistence: "full",
77
+ session_ttl_ms: 3600000,
78
+ max_connections: 10000,
79
+ rate_limit: 1000,
80
+ },
81
+ realtime_collaboration: {
82
+ auth: "jwt",
83
+ engine: "postgresql",
84
+ session_engine: "redis",
85
+ sync: "realtime",
86
+ channel_transport: "websocket",
87
+ channel_ordering: "causal",
88
+ channel_persistence: "full",
89
+ session_ttl_ms: 7200000,
90
+ max_connections: 10000,
91
+ rate_limit: 5000,
92
+ },
93
+ };
94
+ const FALLBACK_DEFAULTS = {
95
+ auth: "jwt",
96
+ engine: "postgresql",
97
+ session_engine: "redis",
98
+ sync: "eventual",
99
+ channel_transport: "websocket",
100
+ channel_ordering: "fifo",
101
+ channel_persistence: "none",
102
+ session_ttl_ms: 3600000,
103
+ max_connections: 10000,
104
+ rate_limit: 1000,
105
+ };
106
+ // ─── Solver ──────────────────────────────────────────────────────────────────
107
+ class ConstraintSolver {
108
+ solve(system) {
109
+ const resolution = {};
110
+ const assumptions = [];
111
+ const warnings = [];
112
+ const errors = [];
113
+ const defaults = DOMAIN_DEFAULTS[system.domain || ""] || FALLBACK_DEFAULTS;
114
+ if (!system.domain) {
115
+ assumptions.push("No domain specified. Using fallback defaults.");
116
+ }
117
+ else {
118
+ assumptions.push(`Domain '${system.domain}' selected. Applying domain defaults.`);
119
+ }
120
+ // ─── Phase 1: Collect ────────────────────────────────────────────────────
121
+ // Collect all unresolved variables from modules
122
+ const unresolvedVars = new Map();
123
+ for (const mod of system.modules) {
124
+ const prefix = `${mod.name}`;
125
+ if (mod.kind === "data_store") {
126
+ const engine = mod.config["engine"];
127
+ if (!engine) {
128
+ unresolvedVars.set(`${prefix}.engine`, null);
129
+ }
130
+ else {
131
+ resolution[`${prefix}.engine`] = engine;
132
+ }
133
+ if (mod.config["replicas"] === undefined) {
134
+ unresolvedVars.set(`${prefix}.replicas`, null);
135
+ }
136
+ }
137
+ if (mod.kind === "api_service") {
138
+ const authMethod = mod.config["auth_method"];
139
+ if (!authMethod || authMethod === "none") {
140
+ unresolvedVars.set(`${prefix}.auth_method`, null);
141
+ }
142
+ else {
143
+ resolution[`${prefix}.auth_method`] = authMethod;
144
+ }
145
+ }
146
+ if (mod.kind === "realtime_service") {
147
+ const transport = mod.config["transport"];
148
+ if (!transport)
149
+ unresolvedVars.set(`${prefix}.transport`, null);
150
+ else
151
+ resolution[`${prefix}.transport`] = transport;
152
+ const ordering = mod.config["ordering"];
153
+ if (!ordering)
154
+ unresolvedVars.set(`${prefix}.ordering`, null);
155
+ else
156
+ resolution[`${prefix}.ordering`] = ordering;
157
+ const persistence = mod.config["persistence"];
158
+ if (!persistence || persistence === "none") {
159
+ unresolvedVars.set(`${prefix}.persistence`, null);
160
+ }
161
+ else {
162
+ resolution[`${prefix}.persistence`] = persistence;
163
+ }
164
+ }
165
+ if (mod.kind === "gateway") {
166
+ if (!mod.config["rate_limit"]) {
167
+ unresolvedVars.set(`${prefix}.rate_limit`, null);
168
+ }
169
+ }
170
+ }
171
+ // ─── Phase 2: Normalize ──────────────────────────────────────────────────
172
+ // (constraints are already in canonical form from the IR)
173
+ // ─── Phase 3: Propagate ──────────────────────────────────────────────────
174
+ // Apply domain defaults to unresolved variables
175
+ for (const [varName] of unresolvedVars) {
176
+ const parts = varName.split(".");
177
+ const prop = parts[parts.length - 1];
178
+ switch (prop) {
179
+ case "engine":
180
+ resolution[varName] = defaults.engine;
181
+ assumptions.push(`${varName} = ${defaults.engine} (domain default)`);
182
+ break;
183
+ case "auth_method":
184
+ resolution[varName] = defaults.auth;
185
+ assumptions.push(`${varName} = ${defaults.auth} (domain default)`);
186
+ break;
187
+ case "transport":
188
+ resolution[varName] = defaults.channel_transport;
189
+ assumptions.push(`${varName} = ${defaults.channel_transport} (domain default)`);
190
+ break;
191
+ case "ordering":
192
+ resolution[varName] = defaults.channel_ordering;
193
+ assumptions.push(`${varName} = ${defaults.channel_ordering} (domain default)`);
194
+ break;
195
+ case "persistence":
196
+ resolution[varName] = defaults.channel_persistence;
197
+ assumptions.push(`${varName} = ${defaults.channel_persistence} (domain default)`);
198
+ break;
199
+ case "rate_limit":
200
+ resolution[varName] = String(defaults.rate_limit);
201
+ assumptions.push(`${varName} = ${defaults.rate_limit} (domain default)`);
202
+ break;
203
+ case "replicas":
204
+ resolution[varName] = "1";
205
+ assumptions.push(`${varName} = 1 (minimum default)`);
206
+ break;
207
+ default:
208
+ warnings.push(`Unresolved variable '${varName}' has no default.`);
209
+ }
210
+ }
211
+ // ─── Implication Rules ───────────────────────────────────────────────────
212
+ // Rule: If any module has auth != none, system needs a session store
213
+ const hasAuth = system.modules.some(m => m.config["authenticated"] === true || (m.config["auth_method"] && m.config["auth_method"] !== "none"));
214
+ if (hasAuth) {
215
+ const hasSessionStore = system.modules.some(m => m.kind === "data_store" && (m.name.toLowerCase().includes("session") || m.config["engine"] === "redis"));
216
+ if (!hasSessionStore) {
217
+ resolution["implied.session_store"] = "required";
218
+ resolution["implied.session_store.engine"] = defaults.session_engine;
219
+ resolution["implied.session_store.ttl_ms"] = String(defaults.session_ttl_ms);
220
+ assumptions.push(`Auth detected → session store required (${defaults.session_engine}, TTL=${defaults.session_ttl_ms}ms)`);
221
+ }
222
+ }
223
+ // Rule: If any realtime_service exists, event_bus is implied
224
+ const hasRealtime = system.modules.some(m => m.kind === "realtime_service");
225
+ if (hasRealtime) {
226
+ resolution["implied.event_bus"] = "required";
227
+ resolution["implied.event_bus.engine"] = "redis_pubsub";
228
+ assumptions.push("Realtime service detected → event bus required (redis_pubsub)");
229
+ }
230
+ // Rule: If events exist with delivery=exactly_once, transactional outbox is implied
231
+ const hasExactlyOnce = system.events.some(e => e.delivery === "exactly_once");
232
+ if (hasExactlyOnce) {
233
+ resolution["implied.outbox"] = "required";
234
+ resolution["implied.outbox.engine"] = defaults.engine;
235
+ assumptions.push("exactly_once delivery detected → transactional outbox required");
236
+ }
237
+ // Rule: If flows exist, saga coordinator is implied
238
+ if (system.flows.length > 0) {
239
+ resolution["implied.saga_coordinator"] = "required";
240
+ assumptions.push("Flow declarations detected → saga coordinator required");
241
+ }
242
+ // ─── Phase 4: Check Consistency ──────────────────────────────────────────
243
+ // Check: total ordering + polling is invalid
244
+ for (const mod of system.modules) {
245
+ if (mod.kind === "realtime_service") {
246
+ const transport = resolution[`${mod.name}.transport`] || mod.config["transport"];
247
+ const ordering = resolution[`${mod.name}.ordering`] || mod.config["ordering"];
248
+ if (ordering === "total" && transport === "polling") {
249
+ errors.push(`Exclusion rule violated: ${mod.name} has ordering=total with transport=polling (incompatible)`);
250
+ }
251
+ }
252
+ }
253
+ // Check: realtime sync requires at_least_once delivery
254
+ for (const ev of system.events) {
255
+ if (ev.delivery === "at_most_once") {
256
+ const sourceModule = system.modules.find(m => m.id === ev.source);
257
+ if (sourceModule && sourceModule.kind === "realtime_service") {
258
+ warnings.push(`Event '${ev.name}' uses at_most_once delivery on a realtime service. Consider at_least_once.`);
259
+ }
260
+ }
261
+ }
262
+ // ─── Phase 5: Complete ───────────────────────────────────────────────────
263
+ // Global resolution entries
264
+ resolution["system.name"] = system.name;
265
+ resolution["system.version"] = system.version;
266
+ resolution["system.domain"] = system.domain || "generic";
267
+ resolution["system.default_timeout_ms"] = "30000";
268
+ resolution["system.default_page_size"] = "50";
269
+ resolution["system.max_connections"] = String(defaults.max_connections);
270
+ // ─── Phase 6: Verify ─────────────────────────────────────────────────────
271
+ // All variables should now be resolved
272
+ for (const [varName] of unresolvedVars) {
273
+ if (!resolution[varName]) {
274
+ errors.push(`C002: Unresolvable variable '${varName}' — no default available. Programmer must specify.`);
275
+ }
276
+ }
277
+ return { resolution, assumptions, warnings, errors };
278
+ }
279
+ }
280
+ exports.ConstraintSolver = ConstraintSolver;
281
+ //# sourceMappingURL=solver.js.map