bonecode 1.2.3 → 1.3.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 (66) hide show
  1. package/README.md +20 -0
  2. package/dist/src/engine/agent/prompt/compaction.txt +9 -0
  3. package/dist/src/engine/agent/prompt/explore.txt +18 -0
  4. package/dist/src/engine/agent/prompt/scout.txt +36 -0
  5. package/dist/src/engine/agent/prompt/summary.txt +11 -0
  6. package/dist/src/engine/agent/prompt/title.txt +44 -0
  7. package/dist/src/engine/session/prompt/anthropic.txt +105 -0
  8. package/dist/src/engine/session/prompt/beast.txt +147 -0
  9. package/dist/src/engine/session/prompt/bonescript.txt +391 -0
  10. package/dist/src/engine/session/prompt/build-switch.txt +5 -0
  11. package/dist/src/engine/session/prompt/codex.txt +79 -0
  12. package/dist/src/engine/session/prompt/copilot-gpt-5.txt +143 -0
  13. package/dist/src/engine/session/prompt/default.txt +105 -0
  14. package/dist/src/engine/session/prompt/gemini.txt +155 -0
  15. package/dist/src/engine/session/prompt/gpt.txt +107 -0
  16. package/dist/src/engine/session/prompt/kimi.txt +95 -0
  17. package/dist/src/engine/session/prompt/max-steps.txt +16 -0
  18. package/dist/src/engine/session/prompt/plan-reminder-anthropic.txt +67 -0
  19. package/dist/src/engine/session/prompt/plan.txt +26 -0
  20. package/dist/src/engine/session/prompt/trinity.txt +97 -0
  21. package/dist/src/engine/session/prompt.js +35 -2
  22. package/dist/src/engine/session/prompt.js.map +1 -1
  23. package/dist/src/engine/skill/prompt/customize-opencode.md +377 -0
  24. package/dist/src/engine/tool/apply_patch.txt +33 -0
  25. package/dist/src/engine/tool/edit.txt +10 -0
  26. package/dist/src/engine/tool/glob.txt +6 -0
  27. package/dist/src/engine/tool/grep.txt +8 -0
  28. package/dist/src/engine/tool/lsp.txt +24 -0
  29. package/dist/src/engine/tool/plan-enter.txt +14 -0
  30. package/dist/src/engine/tool/plan-exit.txt +13 -0
  31. package/dist/src/engine/tool/question.txt +10 -0
  32. package/dist/src/engine/tool/read.txt +14 -0
  33. package/dist/src/engine/tool/repo_clone.txt +5 -0
  34. package/dist/src/engine/tool/repo_overview.txt +4 -0
  35. package/dist/src/engine/tool/shell/shell.txt +77 -0
  36. package/dist/src/engine/tool/skill.txt +5 -0
  37. package/dist/src/engine/tool/task.txt +58 -0
  38. package/dist/src/engine/tool/task_status.txt +13 -0
  39. package/dist/src/engine/tool/todowrite.txt +167 -0
  40. package/dist/src/engine/tool/tool/apply_patch.txt +33 -0
  41. package/dist/src/engine/tool/tool/edit.txt +10 -0
  42. package/dist/src/engine/tool/tool/glob.txt +6 -0
  43. package/dist/src/engine/tool/tool/grep.txt +8 -0
  44. package/dist/src/engine/tool/tool/lsp.txt +24 -0
  45. package/dist/src/engine/tool/tool/plan-enter.txt +14 -0
  46. package/dist/src/engine/tool/tool/plan-exit.txt +13 -0
  47. package/dist/src/engine/tool/tool/question.txt +10 -0
  48. package/dist/src/engine/tool/tool/read.txt +14 -0
  49. package/dist/src/engine/tool/tool/repo_clone.txt +5 -0
  50. package/dist/src/engine/tool/tool/repo_overview.txt +4 -0
  51. package/dist/src/engine/tool/tool/shell/shell.txt +77 -0
  52. package/dist/src/engine/tool/tool/skill.txt +5 -0
  53. package/dist/src/engine/tool/tool/task.txt +58 -0
  54. package/dist/src/engine/tool/tool/task_status.txt +13 -0
  55. package/dist/src/engine/tool/tool/todowrite.txt +167 -0
  56. package/dist/src/engine/tool/tool/webfetch.txt +13 -0
  57. package/dist/src/engine/tool/tool/websearch.txt +14 -0
  58. package/dist/src/engine/tool/tool/write.txt +8 -0
  59. package/dist/src/engine/tool/webfetch.txt +13 -0
  60. package/dist/src/engine/tool/websearch.txt +14 -0
  61. package/dist/src/engine/tool/write.txt +8 -0
  62. package/package.json +2 -2
  63. package/scripts/copy_prompts.js +58 -0
  64. package/scripts/test_bonescript_primer.js +111 -0
  65. package/src/engine/session/prompt/bonescript.txt +391 -0
  66. package/src/engine/session/prompt.ts +36 -2
@@ -0,0 +1,391 @@
1
+ # BoneScript — the canonical way to build backends in BoneCode
2
+
3
+ You are working inside a BoneCode project. **BoneScript is a real, deterministic declarative language** that compiles `.bone` system descriptions into complete, runnable Node.js + PostgreSQL backends. It is published on npm as `bonescript-compiler`. The repository is https://github.com/Doorman11991/BoneScript.
4
+
5
+ BoneScript is NOT pseudocode. NOT optional. NOT a generic scripting language. When the user asks you to build a backend feature, your default approach MUST be:
6
+
7
+ 1. **Define** — write or update the relevant `.bone` file using the `edit` or `write` tool
8
+ 2. **Compile** — run `bonec compile <file>` (or `npm run compile`) via the shell tool
9
+ 3. **Extend** — add custom logic only in `extensions/` (these files survive recompilation)
10
+ 4. **Check** — run `bonec check <file>` to validate the spec
11
+
12
+ You must NEVER hand-write models, routes, controllers, services, schemas, or migrations. The compiler generates all of that from `.bone` files. You must NEVER run `prisma migrate`, `drizzle-kit push`, `typeorm migration`, `nest g`, `rails generate`, etc.
13
+
14
+ ## When BoneScript applies
15
+
16
+ Use BoneScript whenever the user asks for any of these:
17
+ - Domain entities (User, Order, Product, Shop, Session, etc.)
18
+ - Persistence (tables, indexes, migrations)
19
+ - API endpoints (REST or GraphQL)
20
+ - State machines (`pending → paid → shipped → delivered`)
21
+ - Events with delivery guarantees (at_least_once, exactly_once)
22
+ - Saga / multi-step transactional flows with compensation
23
+ - WebSocket channels for realtime
24
+ - Permissions, rate limits, auth (JWT, OAuth2, API key)
25
+ - Background workers, scheduled jobs
26
+
27
+ Use plain Python/TypeScript/etc. only for:
28
+ - **Pure simulations** (game loops, math, render) with no persistence layer
29
+ - **Frontend** components
30
+ - **Custom logic** inside `extensions/` that BoneScript cannot generate (LLM calls, embeddings, file system, git, third-party APIs)
31
+
32
+ If the request is ambiguous (e.g. "a 2D market simulation"), ask the user: "Is this a self-contained simulation script (plain code) or a backend service with persistence (BoneScript)?"
33
+
34
+ ## BoneScript syntax — authoritative reference
35
+
36
+ ### `system` block
37
+
38
+ Every `.bone` file declares one `system`:
39
+
40
+ ```bone
41
+ system Marketplace {
42
+ domain: marketplace
43
+
44
+ // entities, stores, events, capabilities, flows, channels, policies
45
+ }
46
+ ```
47
+
48
+ The `domain:` key picks a starter template (`marketplace`, `saas_platform`, `multiplayer_game`, `iot_system`, `social_network`, `realtime_collaboration`, `ecommerce`, `event_driven`, `api_gateway`, or `blank`).
49
+
50
+ ### `entity` — stateful object with constraints, states, relations
51
+
52
+ ```bone
53
+ entity Order {
54
+ owns: [
55
+ buyer_id: uuid,
56
+ listing_id: uuid,
57
+ seller_id: uuid,
58
+ quantity: uint,
59
+ total: uint,
60
+ status: string
61
+ ]
62
+ constraints: [
63
+ quantity >= 1,
64
+ total > 0,
65
+ status in ["pending", "paid", "shipped", "delivered", "cancelled"]
66
+ ]
67
+ states: pending -> paid -> shipped -> delivered | cancelled
68
+ auth: jwt
69
+ index: [buyer_id, seller_id, status]
70
+ relation listing: belongs_to Listing
71
+ relation buyer: belongs_to Buyer
72
+ }
73
+ ```
74
+
75
+ Field types: `string`, `uint`, `int`, `float`, `bool`, `uuid`, `timestamp`, `json`, `optional<T>`.
76
+ Constraints: `>=`, `<=`, `==`, `in [...]`, `field.length in N..M`, `field.unique`.
77
+ States are unidirectional unless explicitly branched with `|` (terminal states).
78
+
79
+ ### `store` — generated database table
80
+
81
+ ```bone
82
+ store OrderStore {
83
+ engine: postgresql
84
+ schema: {
85
+ id: uuid,
86
+ buyer_id: uuid,
87
+ listing_id: uuid,
88
+ quantity: uint,
89
+ total: uint,
90
+ status: string,
91
+ state: string,
92
+ created_at: timestamp,
93
+ updated_at: timestamp
94
+ }
95
+ partition: buyer_id // optional — for sharding
96
+ replicas: 1
97
+ }
98
+ ```
99
+
100
+ The compiler emits SQL migrations with proper indexes, FK constraints, and triggers. Never write migration SQL by hand.
101
+
102
+ ### `event` — durable, typed message with delivery semantics
103
+
104
+ ```bone
105
+ event OrderPlaced {
106
+ payload: {
107
+ order_id: uuid,
108
+ buyer_id: uuid,
109
+ total: uint,
110
+ placed_at: timestamp
111
+ }
112
+ delivery: at_least_once // or exactly_once
113
+ ttl: 30d // 1h, 7d, 90d, etc.
114
+ }
115
+ ```
116
+
117
+ `at_least_once` retries with exponential backoff; `exactly_once` deduplicates via the `event_processed` table. Switch modes globally with `EVENT_MODE=durable|in_process` env var.
118
+
119
+ ### `capability` — generated endpoint with state-machine enforcement
120
+
121
+ ```bone
122
+ capability place_order(buyer: Buyer, listing: Listing, quantity: uint) {
123
+ requires: [
124
+ buyer.state == "active",
125
+ listing.state == "active",
126
+ listing.stock >= quantity,
127
+ buyer.balance >= listing.price * quantity
128
+ ]
129
+ effects: [
130
+ listing.stock -= quantity,
131
+ buyer.balance -= listing.price * quantity
132
+ ]
133
+ emits: OrderPlaced
134
+ sync: transactional // or eventual / realtime
135
+ timeout: 30s
136
+ idempotent: false
137
+ }
138
+ ```
139
+
140
+ The compiler generates an Express route, validates the `requires` predicates, applies the `effects` atomically in a SQL transaction, publishes the event via the outbox, and enforces `timeout`. Never touch the generated route file.
141
+
142
+ ### `pipeline:` capability — multi-step with auto-rollback
143
+
144
+ ```bone
145
+ capability checkout(buyer: Buyer, cart: Cart) {
146
+ pipeline: {
147
+ validate_inventory(cart)
148
+ charge_payment(buyer, cart.total) as payment
149
+ create_order(buyer, cart, payment)
150
+ on_error: rollback
151
+ }
152
+ sync: transactional
153
+ }
154
+ ```
155
+
156
+ ### `algorithm:` capability — built-in algorithm catalog
157
+
158
+ ```bone
159
+ capability find_route(start: string, end: string) {
160
+ algorithm: shortest_path using { graph: road_network, source: start, target: end }
161
+ returns: json
162
+ }
163
+ ```
164
+
165
+ Available: `shortest_path`, `topological_sort`, `binary_search`, `bipartite_matching`, `round_robin`, `weighted_average`, `percentile`, `rank_by`, `consistent_hash`.
166
+
167
+ ### `flow` — saga with backward compensation
168
+
169
+ ```bone
170
+ flow checkout {
171
+ step validate: place_order(buyer, listing, quantity)
172
+ compensate: cancel_order(order)
173
+
174
+ step pay: process_payment(order, buyer)
175
+ compensate: cancel_order(order)
176
+
177
+ step confirm: ship_order(seller, order)
178
+ compensate: cancel_order(order)
179
+ }
180
+ ```
181
+
182
+ If any step fails, the compiler runs all preceding `compensate` actions in reverse order.
183
+
184
+ ### `channel` — WebSocket pub/sub
185
+
186
+ ```bone
187
+ channel game_lobby {
188
+ transport: websocket
189
+ ordering: causal // or fifo / unordered
190
+ participants: set<Player>
191
+ persistence: last_100 // last_N messages retained
192
+ filter: participant.id == event.player_id
193
+ }
194
+ ```
195
+
196
+ ### `policy` — rate limit + access control + audit
197
+
198
+ ```bone
199
+ policy api_limits {
200
+ rate_limit: 200 per 1m // per 1s, 1m, 1h, 1d
201
+ access: [buyer, seller, admin]
202
+ audit: true
203
+ encryption: in_transit // or at_rest, both, none
204
+ }
205
+ ```
206
+
207
+ ### `extension_point` — escape hatch for custom logic
208
+
209
+ ```bone
210
+ extension_point calculate_shipping_cost(order: Order) {
211
+ returns: uint
212
+ stable: true // compilation fails if not implemented
213
+ }
214
+ ```
215
+
216
+ Implement in `extensions/`:
217
+
218
+ ```ts
219
+ // extensions/shipping.ts
220
+ export async function calculate_shipping_cost(order: { id: string; total: number; ... }): Promise<number> {
221
+ // custom logic here — preserved across recompilation
222
+ return Math.ceil(order.total * 0.05)
223
+ }
224
+ ```
225
+
226
+ ### Cross-entity constraints
227
+
228
+ ```bone
229
+ constraint listing_price_limit: Listing.price <= 1000000
230
+ constraint order_quantity_limit: Order.quantity <= 100
231
+ ```
232
+
233
+ ## What gets generated from a `.bone` file
234
+
235
+ Running `bonec compile shop.bone` produces:
236
+
237
+ ```
238
+ output/
239
+ ├── src/
240
+ │ ├── index.ts Express server with all routes wired
241
+ │ ├── db.ts Postgres connection pool
242
+ │ ├── events.ts Durable event bus (transactional outbox)
243
+ │ ├── auth.ts JWT / OAuth2 / API key middleware
244
+ │ ├── publishers.ts Typed event publisher functions
245
+ │ ├── health.ts /health/live, /health/ready, /health/metrics
246
+ │ ├── flows.ts Saga runtime with backward compensation
247
+ │ ├── websocket.ts WebSocket server (if channels declared)
248
+ │ ├── routes/ One file per entity — CRUD + capabilities
249
+ │ ├── state_machines/ One file per entity with states
250
+ │ └── models/ TypeScript interfaces + Zod validators
251
+ ├── migrations/ SQL schemas with indexes, triggers, FKs
252
+ ├── openapi.json OpenAPI 3.0 schema
253
+ ├── Dockerfile
254
+ ├── docker-compose.yaml Postgres + Redis for local dev
255
+ ├── k8s/deployment.yaml
256
+ └── .github/workflows/ CI/CD pipeline
257
+ ```
258
+
259
+ **Never edit anything in `output/` (or `generated/`). It's overwritten on every compile.** All your custom code goes in `extensions/`.
260
+
261
+ ## CLI commands
262
+
263
+ | Command | Purpose |
264
+ |---------|---------|
265
+ | `bonec init <name> --domain <template>` | Scaffold a new project |
266
+ | `bonec compile <file>` | Full 7-stage compile → runnable backend |
267
+ | `bonec check <file>` | Validate without generating |
268
+ | `bonec watch <file>` | Recompile on save |
269
+ | `bonec diff <old> <new>` | Show schema migration diff |
270
+ | `bonec fmt <file>` | Format in place |
271
+ | `bonec test [output-dir]` | Run generated regression tests |
272
+ | `bonec verify-determinism <file>` | Confirm two compiles produce identical output |
273
+
274
+ The compiler is on npm: `npm install -g bonescript-compiler`. Inside a BoneCode project, `npm run compile` typically wraps `bonec compile`.
275
+
276
+ ## Worked example — 2D market simulation done right
277
+
278
+ User: "build me a 2D market simulation with 2000 shops over 100 simulated years"
279
+
280
+ The first question to ask: **is it a simulation script or a backend?**
281
+ - If it's just a runnable visualization with no need for persistent state, REST APIs, or multiplayer — write plain Python/TS.
282
+ - If shops have state, transactions are queryable, multiple users can poke at the world, OR you want to run the simulation as a service — use BoneScript.
283
+
284
+ For the backend version:
285
+
286
+ 1. Create `bone/market.bone`:
287
+
288
+ ```bone
289
+ system Market {
290
+ domain: marketplace
291
+
292
+ entity Shop {
293
+ owns: [
294
+ name: string,
295
+ x_pos: float,
296
+ y_pos: float,
297
+ specialty: string,
298
+ gold: uint,
299
+ reputation: float
300
+ ]
301
+ constraints: [
302
+ specialty in ["food", "tools", "weapons", "luxury", "general"],
303
+ gold >= 0,
304
+ reputation >= 0,
305
+ reputation <= 1
306
+ ]
307
+ states: founded -> active -> struggling -> bankrupt | thriving
308
+ index: [specialty]
309
+ }
310
+
311
+ entity Transaction {
312
+ owns: [
313
+ shop_id: uuid,
314
+ year: uint,
315
+ amount: uint,
316
+ kind: string
317
+ ]
318
+ constraints: [
319
+ amount > 0,
320
+ year >= 0,
321
+ kind in ["sale", "purchase", "tax"]
322
+ ]
323
+ index: [shop_id, year]
324
+ relation shop: belongs_to Shop
325
+ }
326
+
327
+ event TransactionRecorded {
328
+ payload: {
329
+ transaction_id: uuid,
330
+ shop_id: uuid,
331
+ year: uint,
332
+ amount: uint
333
+ }
334
+ delivery: at_least_once
335
+ ttl: 90d
336
+ }
337
+
338
+ capability record_transaction(shop: Shop, year: uint, amount: uint, kind: string) {
339
+ requires: [
340
+ shop.state in ["active", "thriving", "struggling"],
341
+ amount > 0
342
+ ]
343
+ effects: [
344
+ shop.gold = shop.gold + amount
345
+ ]
346
+ emits: TransactionRecorded
347
+ sync: transactional
348
+ timeout: 5s
349
+ idempotent: true
350
+ }
351
+
352
+ extension_point simulate_year(year: uint) {
353
+ returns: json
354
+ stable: true
355
+ }
356
+
357
+ flow advance_year {
358
+ step demand: simulate_year(year)
359
+ compensate: noop()
360
+ }
361
+
362
+ policy api_limits {
363
+ rate_limit: 1000 per 1m
364
+ access: [user, admin]
365
+ audit: true
366
+ }
367
+ }
368
+ ```
369
+
370
+ 2. `npm run compile` (or `bonec compile bone/market.bone`)
371
+
372
+ 3. Implement `simulate_year` in `extensions/simulation.ts`:
373
+
374
+ ```ts
375
+ export async function simulate_year(year: number) {
376
+ // Read all shops, calculate demand, call record_transaction for each
377
+ // This is the only place where you write custom logic.
378
+ }
379
+ ```
380
+
381
+ 4. The generated backend gives you `POST /shops`, `GET /shops/:id`, `POST /shops/:id/record_transaction`, `GET /transactions?shop_id=...`, the state machine, durable events, OpenAPI spec, and a TypeScript SDK — all from the `.bone` file.
382
+
383
+ 5. The 2000-shop × 100-year loop lives in a runner script that calls the generated capabilities (or in `simulate_year` itself).
384
+
385
+ This is how you build real backends in BoneCode. Don't fall back to writing raw Python or hand-rolled Express routes when the user asks for a backend feature. If the user actually wants a script, ask first.
386
+
387
+ ## Reference links (for the user, not for you to fetch)
388
+
389
+ - BoneScript: https://github.com/Doorman11991/BoneScript
390
+ - Compiler: https://www.npmjs.com/package/bonescript-compiler
391
+ - OpenCode plugin: https://github.com/Doorman11991/opencode-bonescript-backend
@@ -598,6 +598,11 @@ async function buildSystemPromptWithRAG(
598
598
  // Base system prompt (provider-specific, from OpenCode)
599
599
  const base = getSystemPrompt(model_id, provider_id, agent_name);
600
600
 
601
+ // BoneScript primer — loaded for every session so the model knows about
602
+ // BoneScript before any tool call. Without this, models default to
603
+ // generic Python/TS and never use the .bone workflow.
604
+ const bonescriptPrimer = loadBonescriptPrimer();
605
+
601
606
  // Environment context
602
607
  const envContext = [
603
608
  `Working directory: ${worktree}`,
@@ -621,7 +626,7 @@ async function buildSystemPromptWithRAG(
621
626
  const project_id = sessionRow.rows[0]?.project_id || "";
622
627
  if (!project_id) {
623
628
  // No project linked yet — skip RAG context
624
- return [base, envContext, instructions].filter(Boolean).join("\n\n");
629
+ return [base, bonescriptPrimer, envContext, instructions].filter(Boolean).join("\n\n");
625
630
  }
626
631
 
627
632
  const ctxResult = await buildContext({
@@ -641,7 +646,36 @@ async function buildSystemPromptWithRAG(
641
646
  }
642
647
  }
643
648
 
644
- return [base, envContext, instructions, codebaseContext].filter(Boolean).join("\n\n");
649
+ return [base, bonescriptPrimer, envContext, instructions, codebaseContext].filter(Boolean).join("\n\n");
650
+ }
651
+
652
+ // ─── BoneScript primer loader ─────────────────────────────────────────────────
653
+
654
+ let _bonescriptPrimer: string | null = null;
655
+ function loadBonescriptPrimer(): string {
656
+ if (_bonescriptPrimer !== null) return _bonescriptPrimer;
657
+ try {
658
+ const fs = require("fs");
659
+ const path = require("path");
660
+ // Look for the primer in the prompt directory next to this compiled module.
661
+ // After compilation, this lives at dist/src/engine/session/prompt.js, so the
662
+ // .txt file is at dist/src/engine/session/prompt/bonescript.txt.
663
+ const candidates = [
664
+ path.join(__dirname, "prompt", "bonescript.txt"),
665
+ path.join(__dirname, "..", "..", "..", "src", "engine", "session", "prompt", "bonescript.txt"),
666
+ ];
667
+ for (const candidate of candidates) {
668
+ if (fs.existsSync(candidate)) {
669
+ _bonescriptPrimer = fs.readFileSync(candidate, "utf-8");
670
+ return _bonescriptPrimer || "";
671
+ }
672
+ }
673
+ _bonescriptPrimer = "";
674
+ return "";
675
+ } catch {
676
+ _bonescriptPrimer = "";
677
+ return "";
678
+ }
645
679
  }
646
680
 
647
681
  // ─── Language Model Factory ───────────────────────────────────────────────────