raga-cli 0.8.0 → 0.9.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 (46) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +27 -4
  3. package/bundled-skills/README.md +2 -2
  4. package/bundled-skills/bundle.json +73 -7
  5. package/bundled-skills/skills/bend/SKILL.md +58 -0
  6. package/bundled-skills/skills/bend/bend_tool.py +144 -0
  7. package/bundled-skills/skills/peak/SKILL.md +1 -1
  8. package/bundled-skills/skills/peak/references/raga-runtime/SKILL.md +18 -4
  9. package/bundled-skills/skills/peak/references/raga-runtime/raga_runtime.py +12 -1
  10. package/bundled-skills/skills/raga-artifacts/SKILL.md +117 -0
  11. package/bundled-skills/skills/raga-artifacts/artifact.mjs +254 -0
  12. package/bundled-skills/skills/raga-artifacts/artifact_tool.py +55 -0
  13. package/bundled-skills/skills/raga-artifacts/diagrams.md +641 -0
  14. package/bundled-skills/skills/raga-artifacts/templates/doc.html +124 -0
  15. package/bundled-skills/skills/raga-artifacts/templates/slides.html +138 -0
  16. package/dist/bundle/chunks/anthropic.js +1 -8
  17. package/dist/bundle/chunks/chunk-3MNXTBQ3.js +2 -0
  18. package/dist/bundle/chunks/{chunk-IOPE2TJ4.js → chunk-ENUUAC3O.js} +8 -8
  19. package/dist/bundle/chunks/{chunk-AI2NMHE7.js → chunk-F7LFZTHT.js} +261 -237
  20. package/dist/bundle/chunks/{chunk-3EGDWOKT.js → chunk-JQDZ4Z7L.js} +1 -1
  21. package/dist/bundle/chunks/{chunk-J22MF7YW.js → chunk-NP6TH6UT.js} +2 -2
  22. package/dist/bundle/chunks/{chunk-YMZUNB25.js → chunk-OPPYO2IE.js} +1 -1
  23. package/dist/bundle/chunks/{chunk-UDT647VB.js → chunk-S5J3UB5O.js} +1 -8
  24. package/dist/bundle/chunks/{cli-4P6FVVLT.js → cli-QLDCDYOR.js} +1 -1
  25. package/dist/bundle/chunks/{easter-egg-3d-65VIC4G2.js → easter-egg-3d-NPDBBPPF.js} +1 -1
  26. package/dist/bundle/chunks/{execute-3H5WKMA3.js → execute-WPTMS4XG.js} +1 -1
  27. package/dist/bundle/chunks/openai-chatgpt.js +1 -8
  28. package/dist/bundle/chunks/openai-codex.js +1 -8
  29. package/dist/bundle/chunks/openrouter.js +1 -8
  30. package/dist/bundle/chunks/radius.js +1 -8
  31. package/dist/bundle/chunks/{runtime-435R6IKY.js → runtime-N5MUH2WA.js} +1 -1
  32. package/dist/bundle/chunks/{virtual-modules-U3JBUDP7.js → virtual-modules-4I6Y6DPQ.js} +1 -1
  33. package/dist/bundle/cli-runtime.js +1 -1
  34. package/dist/bundle/index.js +1 -1
  35. package/dist/bundle/raga-runtime.js +1 -1
  36. package/dist/bundle/rpc-entry.js +1 -1
  37. package/docs/cli.md +6 -0
  38. package/docs/compaction.md +26 -0
  39. package/docs/sdk.md +2 -1
  40. package/docs/settings.md +1 -0
  41. package/package.json +1 -1
  42. package/python/raga_rlm/__init__.py +20 -4
  43. package/python/raga_rlm/mlx_models.py +265 -0
  44. package/schemas/keybindings.schema.json +48 -0
  45. package/schemas/settings.schema.json +14 -0
  46. package/dist/bundle/chunks/chunk-C4IJNE7U.js +0 -2
package/CHANGELOG.md CHANGED
@@ -1,3 +1,18 @@
1
+ ## [0.9.0](https://github.com/mr-jones123/raga/compare/raga-v0.8.0...raga-v0.9.0) (2026-10-31)
2
+
3
+ ### Features
4
+
5
+ * add archive compaction strategy that drops context without a summarization call ([3b682ee](https://github.com/mr-jones123/raga/commit/3b682ee878320ce897f136b8661f3b0178c9df1d))
6
+ * add bend and raga-artifacts skills and run peak in ordinary sessions ([4fb5df2](https://github.com/mr-jones123/raga/commit/4fb5df2d32583b6d03f77d5e62c37a219978fcc7))
7
+ * add managed local models and CI releases ([53a7325](https://github.com/mr-jones123/raga/commit/53a73254eeceba1298c98823c275fff8331bb0b8))
8
+ * store instance memory in SQLite with selectable memory backends ([6c4997b](https://github.com/mr-jones123/raga/commit/6c4997be478c430c27ad378fa4d87bafc12f2444))
9
+ * **tui:** add /diff dashboard for categorized git review ([03cb062](https://github.com/mr-jones123/raga/commit/03cb062df23b6591d33902f7d1bb815976dc4049))
10
+
11
+ ### Bug Fixes
12
+
13
+ * publish CLI updates to npm through trusted publishing ([f236785](https://github.com/mr-jones123/raga/commit/f2367854e11a26576324116194ec299403cc2e6a))
14
+ * **schemas:** regenerate keybindings schema for /diff bindings ([6ce96c7](https://github.com/mr-jones123/raga/commit/6ce96c73b6a742857be37e4bb79a83edb566106e))
15
+
1
16
  # Changelog
2
17
 
3
18
  Generated by scripts/raga-release.mjs from conventional commits. Do not edit by hand.
package/README.md CHANGED
@@ -38,7 +38,20 @@ npm install -g raga-cli
38
38
  raga
39
39
  ```
40
40
 
41
- `raga update` installs the newest `raga-cli` release. To run from source instead:
41
+ ### Update
42
+
43
+ Exit raga, then run:
44
+
45
+ ```bash
46
+ raga update
47
+ raga --version
48
+ ```
49
+
50
+ This installs the latest published `raga-cli` release without deleting your settings or sessions. Restart raga afterward. If an older version cannot update itself, run `npm install -g raga-cli@latest`. See [docs/UPDATING.md](docs/UPDATING.md) for other update targets, source checkouts, and troubleshooting.
51
+
52
+ ### Run from source
53
+
54
+ To run from source instead:
42
55
 
43
56
  ```bash
44
57
  git clone https://github.com/mr-jones123/raga.git
@@ -65,6 +78,14 @@ On the first `--rlm` run, raga creates a Python 3.11 environment with `uv` at `~
65
78
 
66
79
  Without `--rlm`, raga behaves like pi, with `read`, `bash`, `edit`, and `write` as model tools.
67
80
 
81
+ ## Local models
82
+
83
+ On macOS and Linux, `/local-models` searches Hugging Face, asks before downloading missing weights, and starts models locally. The first recommendation is the official LFM3-1.7B GGUF Q4_K_M build through llama.cpp. The same command detects MLX models automatically on Apple Silicon; no separate backend command is needed. See [docs/LOCAL-MODELS.md](docs/LOCAL-MODELS.md) for setup, cache behavior, and limits.
84
+
85
+ ## Review changes
86
+
87
+ `/diff` opens a read-only Git review dashboard. Browse changes by category (tests, modules, GitHub workflows, documentation, dependencies, configuration), inspect staged or working-tree changes, or pick a commit from history. Open a file to scroll its diff, and toggle to its full contents without leaving raga. See [docs/DIFF.md](docs/DIFF.md) for controls.
88
+
68
89
  ## What the model does in RLM mode
69
90
 
70
91
  The kernel already exists when the model's first turn starts. Each `python` call runs a cell, and variables stay defined for the whole session. The model sees at most `rlm.outputLimit` characters of each cell's output. The full output stays in `cells`.
@@ -113,7 +134,9 @@ print(counts.most_common(5))
113
134
  | [docs/RLM.md](docs/RLM.md) | The RLM runtime reference. |
114
135
  | [docs/PROGRESS.md](docs/PROGRESS.md) | Milestones, status, and decisions. |
115
136
  | [docs/BENCHMARKS.md](docs/BENCHMARKS.md) | Benchmark tasks and results. |
116
- | [docs/RELEASING.md](docs/RELEASING.md) | Versioning, the generated changelog, and merging upstream pi. |
137
+ | [docs/LOCAL-MODELS.md](docs/LOCAL-MODELS.md) | Search, download, and run local Hugging Face models with llama.cpp or MLX. |
138
+ | [docs/UPDATING.md](docs/UPDATING.md) | Install and update the CLI, extensions, and model catalogs. |
139
+ | [docs/RELEASING.md](docs/RELEASING.md) | Automatic npm publishing, versioning, and merging upstream pi. |
117
140
  | [packages/coding-agent/docs/](packages/coding-agent/docs/) | Pi's own docs, which still apply to everything raga inherits. |
118
141
 
119
142
  ## Development
@@ -123,10 +146,10 @@ npm run check # Lint, format, and type check
123
146
  ./test.sh # Tests without API keys
124
147
  uv run --no-project --with pytest --with dill \
125
148
  pytest packages/coding-agent/python/tests -q # Python kernel tests
126
- node scripts/raga-release.mjs check # Commit headers since the last release
149
+ node scripts/raga-release.mjs version # Version from raga release tags
127
150
  ```
128
151
 
129
- Commit headers follow Conventional Commits, and `scripts/raga-release.mjs` builds `CHANGELOG.md` from them. [AGENTS.md](AGENTS.md) has the rules for humans and agents.
152
+ Commit headers follow Conventional Commits. Semantic-release generates `CHANGELOG.md`, version tags, and GitHub Releases after CI passes on `main`. See [docs/RELEASING.md](docs/RELEASING.md). [AGENTS.md](AGENTS.md) has the rules for humans and agents.
130
153
 
131
154
  ## Credits
132
155
 
@@ -2,9 +2,9 @@
2
2
 
3
3
  New instances copy this pack into their first accepted revision. Each session reads its pinned copy. Updating package assets does not rewrite an existing instance.
4
4
 
5
- The pack installs one skill, peak. Its 62 references hold 55 portable pstack workflows, four companion workflows, the native create-skill and raga-runtime adapters, and the managed no-mistakes workflow. It excludes make-bot-ui and editor-only services. The original public no-mistakes text stays unchanged under skills/peak/references/no-mistakes/upstream.
5
+ The pack installs three skills. raga-artifacts makes slides and documents with Pele diagrams and exports them as HTML and PDF. bend turns rules the user states into Bend laws and proofs and checks them with the bend CLI. peak is the engineering workflow. Its 62 references hold 55 portable pstack workflows, four companion workflows, the native create-skill and raga-runtime adapters, and the managed no-mistakes workflow. It excludes make-bot-ui and editor-only services. The original public no-mistakes text stays unchanged under skills/peak/references/no-mistakes/upstream.
6
6
 
7
- Read [peak](skills/peak/SKILL.md) to pick a reference. Read [the native runtime](skills/peak/references/raga-runtime/SKILL.md) for the Python API. Read [the workflow guide](docs/guide/README.md) for the reference map. Workers return supervisor-owned workspace changes rather than Git commits. Skill changes go through candidate_read, candidate_write, and candidate_commit. Promotion remains a trusted operator operation.
7
+ Read [peak](skills/peak/SKILL.md) to pick a reference. Read [the native runtime](skills/peak/references/raga-runtime/SKILL.md) for the Python API. Read [the workflow guide](docs/guide/README.md) for the reference map. In instance sessions, workers return supervisor-owned workspace changes rather than Git commits. Ordinary sessions keep code changes in the parent session and use read-only children. Skill changes go through candidate_read, candidate_write, and candidate_commit. Promotion remains a trusted operator operation.
8
8
 
9
9
  ## Sources and regeneration
10
10
 
@@ -23,10 +23,20 @@
23
23
  }
24
24
  ],
25
25
  "skills": [
26
+ {
27
+ "name": "bend",
28
+ "path": "skills/bend/SKILL.md",
29
+ "source": "raga"
30
+ },
26
31
  {
27
32
  "name": "peak",
28
33
  "path": "skills/peak/SKILL.md",
29
34
  "source": "pstack"
35
+ },
36
+ {
37
+ "name": "raga-artifacts",
38
+ "path": "skills/raga-artifacts/SKILL.md",
39
+ "source": "raga"
30
40
  }
31
41
  ],
32
42
  "files": [
@@ -242,11 +252,25 @@
242
252
  },
243
253
  {
244
254
  "path": "README.md",
245
- "sha256": "f49df779e23215fded1a5d1d99ce247bd4f763411689c382bcfe674386672b08",
255
+ "sha256": "f58c9364c2f5a4b25f589ae4bbef0557f2d7fc60a16d87fd087cee3b13013154",
246
256
  "source": "raga bundle maintenance guide",
247
- "sourceSha256": "f49df779e23215fded1a5d1d99ce247bd4f763411689c382bcfe674386672b08",
257
+ "sourceSha256": "f58c9364c2f5a4b25f589ae4bbef0557f2d7fc60a16d87fd087cee3b13013154",
248
258
  "adaptation": "raga bundle maintenance guide"
249
259
  },
260
+ {
261
+ "path": "skills/bend/bend_tool.py",
262
+ "sha256": "cee21f9e40c1d95702f09bd635db3046683f95c3d78f18bd1e68e30e192ed968",
263
+ "source": "raga native adaptation",
264
+ "sourceSha256": "cee21f9e40c1d95702f09bd635db3046683f95c3d78f18bd1e68e30e192ed968",
265
+ "adaptation": "raga native adaptation"
266
+ },
267
+ {
268
+ "path": "skills/bend/SKILL.md",
269
+ "sha256": "89001ac986846444f277ab806c5f92f994924569e418f3da327d61c94b028d2e",
270
+ "source": "raga native adaptation",
271
+ "sourceSha256": "89001ac986846444f277ab806c5f92f994924569e418f3da327d61c94b028d2e",
272
+ "adaptation": "raga native adaptation"
273
+ },
250
274
  {
251
275
  "path": "skills/peak/playbooks/authoring-a-skill.md",
252
276
  "sha256": "4b9b7de20a9456bb17c8646e92b6591408ad68567fe33ed16f3cb6f1b07f40bf",
@@ -858,16 +882,16 @@
858
882
  },
859
883
  {
860
884
  "path": "skills/peak/references/raga-runtime/raga_runtime.py",
861
- "sha256": "5bb5fda3cb481df3dc149b88867a75c1efb27c612a0d3ee194d96c134035e638",
885
+ "sha256": "bb2d22512d55f9acf9e2480efc6aa55f8e28ccd3d9a8e98f5c14a1ee591f7538",
862
886
  "source": "raga native Python adapter",
863
- "sourceSha256": "5bb5fda3cb481df3dc149b88867a75c1efb27c612a0d3ee194d96c134035e638",
887
+ "sourceSha256": "bb2d22512d55f9acf9e2480efc6aa55f8e28ccd3d9a8e98f5c14a1ee591f7538",
864
888
  "adaptation": "raga native Python adapter"
865
889
  },
866
890
  {
867
891
  "path": "skills/peak/references/raga-runtime/SKILL.md",
868
- "sha256": "ef2891819b052f701bbd28b253612ffb76b46538d3f9c35ed4d5a7ef2f3fe342",
892
+ "sha256": "5249166b9afe12ecd202971f5dba602b1a0826b6089b5630488cfda510de0440",
869
893
  "source": "raga native adaptation",
870
- "sourceSha256": "ef2891819b052f701bbd28b253612ffb76b46538d3f9c35ed4d5a7ef2f3fe342",
894
+ "sourceSha256": "5249166b9afe12ecd202971f5dba602b1a0826b6089b5630488cfda510de0440",
871
895
  "adaptation": "raga native adaptation"
872
896
  },
873
897
  {
@@ -1390,10 +1414,52 @@
1390
1414
  },
1391
1415
  {
1392
1416
  "path": "skills/peak/SKILL.md",
1393
- "sha256": "a45c66592cd4b3c5afcdac28e259ae37c76c43d006de664e6091dec0d778af83",
1417
+ "sha256": "f3feb010706f5e125ef7b95059c1c939bf86c366ffc62f3b5d50faba3e864e94",
1394
1418
  "source": "pstack/skills/poteto-mode/SKILL.md",
1395
1419
  "sourceSha256": "2755f102e7a6d0496b429d1031a22fb353e1f3d523543367caeaae5c4ed6f544",
1396
1420
  "adaptation": "raga native delegation policy"
1421
+ },
1422
+ {
1423
+ "path": "skills/raga-artifacts/artifact_tool.py",
1424
+ "sha256": "5e4d7ca9db500877f6386a85ce7906cdff79f0c791cad4c5253c9c6d7043b721",
1425
+ "source": "raga native adaptation",
1426
+ "sourceSha256": "5e4d7ca9db500877f6386a85ce7906cdff79f0c791cad4c5253c9c6d7043b721",
1427
+ "adaptation": "raga native adaptation"
1428
+ },
1429
+ {
1430
+ "path": "skills/raga-artifacts/artifact.mjs",
1431
+ "sha256": "a1affbf90bedc1809654b715d746ee2691de896043b919222d3cb35dd5369cc1",
1432
+ "source": "raga native adaptation",
1433
+ "sourceSha256": "a1affbf90bedc1809654b715d746ee2691de896043b919222d3cb35dd5369cc1",
1434
+ "adaptation": "raga native adaptation"
1435
+ },
1436
+ {
1437
+ "path": "skills/raga-artifacts/diagrams.md",
1438
+ "sha256": "f5218754b25c7a441ee81ff6755a36320c559835edc574b00ac6eaf9c82b2de6",
1439
+ "source": "raga native adaptation",
1440
+ "sourceSha256": "f5218754b25c7a441ee81ff6755a36320c559835edc574b00ac6eaf9c82b2de6",
1441
+ "adaptation": "raga native adaptation"
1442
+ },
1443
+ {
1444
+ "path": "skills/raga-artifacts/SKILL.md",
1445
+ "sha256": "e258a80cadf528f411ed25bc793a4b0963a38e0776485cb2df7e357fb277192a",
1446
+ "source": "raga native adaptation",
1447
+ "sourceSha256": "e258a80cadf528f411ed25bc793a4b0963a38e0776485cb2df7e357fb277192a",
1448
+ "adaptation": "raga native adaptation"
1449
+ },
1450
+ {
1451
+ "path": "skills/raga-artifacts/templates/doc.html",
1452
+ "sha256": "a2f0ed6c3f7b4cbea5f5fa16436623a71ac49ad536a1129bb08911e4337eb9f6",
1453
+ "source": "raga native adaptation",
1454
+ "sourceSha256": "a2f0ed6c3f7b4cbea5f5fa16436623a71ac49ad536a1129bb08911e4337eb9f6",
1455
+ "adaptation": "raga native adaptation"
1456
+ },
1457
+ {
1458
+ "path": "skills/raga-artifacts/templates/slides.html",
1459
+ "sha256": "1aa47336acfe08114464cf27e13131714c23d4f7667940a92620eb39fb626c3c",
1460
+ "source": "raga native adaptation",
1461
+ "sourceSha256": "1aa47336acfe08114464cf27e13131714c23d4f7667940a92620eb39fb626c3c",
1462
+ "adaptation": "raga native adaptation"
1397
1463
  }
1398
1464
  ],
1399
1465
  "exclusions": [
@@ -0,0 +1,58 @@
1
+ ---
2
+ name: bend
3
+ description: Turn rules the user states in plain words into Bend laws, write the proofs, and check them with the bend CLI. Use when the user asks to formally verify, prove, or guarantee that a rule can never break.
4
+ ---
5
+
6
+ # Bend formal verification
7
+
8
+ You write Bend laws and proofs for the user. The user decides the rules. Bend decides whether the proofs hold. Never claim a rule is proven unless `bend` printed `ALL PROOFS CHECK`.
9
+
10
+ By Bend convention, `LAWS.bend` states the rules and `PROOF.bend` proves them. Here you write both, so the user must approve every law before you write proofs. After approval, a law is the spec. Do not edit it to make a proof pass.
11
+
12
+ ## Load the helper
13
+
14
+ Work in the Python tool. Load the helper beside this file, then find the CLI:
15
+
16
+ ```python
17
+ exec(await read("<directory of this SKILL.md>/bend_tool.py"), globals())
18
+ bend = find_bend()
19
+ files = law_files()
20
+ ```
21
+
22
+ `find_bend()` checks `BEND_BIN`, then `PATH`, then `~/.bend/bin/bend`. If it returns `None`, stop. Ask the user to install Bend with `curl -fsSL https://bend-lang.com/install.sh | sh`. Do not install it yourself.
23
+
24
+ Outside the Python tool, run the same commands with bash: `bend guide`, `bend PROOF.bend --check-only`.
25
+
26
+ ## Read the guide first
27
+
28
+ Run `guide = await bend_guide()` and keep it in a variable. Read the sections on laws and proofs, recursion and termination, quantities, and kinds before you write Bend. Search the variable for anything else you need. `bend base --types` and `bend base <name>` print the standard library.
29
+
30
+ ## Steps
31
+
32
+ 1. **Ask for the rules.** Ask the user which rules must never break, then stop and wait for the answer. Offer two or three concrete examples taken from the project. Do not invent rules. If the user asks you to choose, propose rules in plain words and wait for confirmation.
33
+ 2. **Write the laws.** Write `files["laws"]`. Start with `import Base`. Define, in Bend, the code or model each rule talks about, then add one `law` per rule. Put the user's own words in a `# LAW:` comment above each law. Keep each law to one rule.
34
+ 3. **Check that the laws parse.** Write a `files["proof"]` that only imports `./LAWS.bend as Laws`, then run `await bend_check(files["proof"])`. Expect `SOME PROOFS FAIL` with a count of open claims. Fix any other error in the laws file.
35
+ 4. **Get approval.** Show the user each law twice: the Bend text and a one-sentence plain reading. Say what the laws do not cover. Ask whether they match the intended rules. Revise and ask again until the user approves. After the user says yes, call `approve_laws(files["laws"])`. A message the user sent before you asked is not approval. `bend_check` fails until the laws are approved.
36
+ 5. **Write the proofs.** In `files["proof"]`, prove each law with `def Laws.<law name>`. Do not write a `law` in the proof file, and do not move a law out of the laws file. The laws file includes its definitions. If a proof needs any change to that file, stop, show the user the change, and call `approve_laws` again only after a new yes. Run `await bend_check(files["proof"])` after each change. Read `problems` first, then the expected and observed terms in `output`. Use `?name` to print a goal while you work.
37
+ 6. **Handle a law you cannot prove.** If the output shows the law is false, show the user the counterexample and ask how to change the rule. If you cannot find a proof, leave `?TODO` in that def and report the law as open. Never use `@unsafe` or foreign code in a proof.
38
+ 7. **Report.** A check passes only when `bend_check` returns `verdict` `passed`, which needs `ALL PROOFS CHECK` and an empty `problems` list. Run the final check through `bend_check`, not bash. Quote its `verdict` and `problems` and the verdict line from `output`. Copy each law from the laws file as written. Do not retype or restate it in Bend. List each law as proven or open. If Lean is installed, `await bend_check(files["proof"], verdict=True)` rechecks with the Lean-proven kernel. Report its result separately.
39
+
40
+ ## Where the files go
41
+
42
+ `law_files()` reads custom file names from `.raga/verification.json`.
43
+
44
+ - In an ordinary session, `files["directory"]` is `.raga/verification/`. These are the files the instance gate reads.
45
+ - In an instance session, the sandbox hides `.raga`, so `files["directory"]` is `verification-draft/`. After the user approves, tell them to copy both files into `.raga/verification/`.
46
+
47
+ ## Turn on the gate
48
+
49
+ Only the user can make a revision depend on these proofs. In an instance project, give the user these commands and let them run each one:
50
+
51
+ - `raga verify install --approved --network` downloads the pinned Bend release the gate uses.
52
+ - `raga verify enable --approved` requires a passing check before a harness revision becomes active.
53
+ - `raga verify run` runs the check in the sandbox and records the verdict.
54
+
55
+ ## Limits
56
+
57
+ - A law proves only the Bend code that `LAWS.bend` defines or imports. For a project in another language, the laws prove facts about a Bend model of the code. Say so in the report.
58
+ - Proofs need structural recursion. Read the termination section before you write recursive defs.
@@ -0,0 +1,144 @@
1
+ """Bend helpers for the raga Python REPL. Load with exec(await read(path), globals())."""
2
+
3
+ import asyncio
4
+ import hashlib
5
+ import json
6
+ import os
7
+ import re
8
+ import shlex
9
+ import shutil
10
+
11
+ BEND_INSTALL = "curl -fsSL https://bend-lang.com/install.sh | sh"
12
+ CHECK_TIMEOUT = 600
13
+
14
+
15
+ def find_bend():
16
+ """Path of the bend executable, or None. BEND_BIN wins, then PATH, then the installer's default."""
17
+ for candidate in (os.environ.get("BEND_BIN"), shutil.which("bend"), os.path.expanduser("~/.bend/bin/bend")):
18
+ if candidate and os.path.isfile(candidate) and os.access(candidate, os.X_OK):
19
+ return candidate
20
+ return None
21
+
22
+
23
+ def law_files(project="."):
24
+ """Where LAWS.bend and PROOF.bend belong, and whether this session may write there.
25
+
26
+ An ordinary session writes the files the instance gate reads: .raga/verification/<laws> and <proof>,
27
+ named by .raga/verification.json. An instance session cannot write .raga, so it drafts under
28
+ verification-draft/ for the user to copy.
29
+ """
30
+ project = os.path.abspath(project)
31
+ names = {"laws": "LAWS.bend", "proof": "PROOF.bend"}
32
+ config = os.path.join(project, ".raga", "verification.json")
33
+ if os.path.isfile(config):
34
+ with open(config, encoding="utf-8") as handle:
35
+ data = json.load(handle)
36
+ names = {key: data.get(key) or default for key, default in names.items()}
37
+ instance = bool(os.environ.get("RAGA_INSTANCE_ID"))
38
+ directory = os.path.join(project, "verification-draft" if instance else os.path.join(".raga", "verification"))
39
+ return {
40
+ "directory": directory,
41
+ "laws": os.path.join(directory, names["laws"]),
42
+ "proof": os.path.join(directory, names["proof"]),
43
+ "mode": "instance" if instance else "ordinary",
44
+ }
45
+
46
+
47
+ async def _run(command, cwd):
48
+ line = "cd " + shlex.quote(cwd) + " && " + command + " 2>&1; printf '\\nEXIT=%s\\n' $?"
49
+ runner = globals().get("bash")
50
+ if runner is not None:
51
+ output = await runner(line, timeout=CHECK_TIMEOUT)
52
+ else:
53
+ process = await asyncio.create_subprocess_shell(line, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.STDOUT)
54
+ stdout, _ = await asyncio.wait_for(process.communicate(), CHECK_TIMEOUT)
55
+ output = stdout.decode("utf-8", "replace")
56
+ body, _, code = output.rstrip().rpartition("\nEXIT=")
57
+ return body.strip(), int(code) if code.strip().isdigit() else None
58
+
59
+
60
+ async def bend_guide(topic=None):
61
+ """The Bend guide text, or one named sub-guide such as "shaders"."""
62
+ bend = find_bend()
63
+ if bend is None:
64
+ raise RuntimeError("bend is not installed. Ask the user to run: " + BEND_INSTALL)
65
+ output, code = await _run(shlex.quote(bend) + " guide" + ((" " + shlex.quote(topic)) if topic else ""), os.getcwd())
66
+ if code != 0:
67
+ raise RuntimeError(output)
68
+ return output
69
+
70
+
71
+ def _digest(path):
72
+ with open(path, "rb") as handle:
73
+ return hashlib.sha256(handle.read()).hexdigest()
74
+
75
+
76
+ def approve_laws(laws_path):
77
+ """Record the laws the user approved. Call only after the user says yes."""
78
+ with open(laws_path + ".approved", "w", encoding="utf-8") as handle:
79
+ handle.write(_digest(laws_path) + "\n")
80
+
81
+
82
+ def _problems(proof_path):
83
+ with open(proof_path, encoding="utf-8") as handle:
84
+ proof = handle.read()
85
+ imported = re.search(r"^import\s+\./(\S+)\s+as\s+Laws\s*$", proof, re.M)
86
+ if not imported:
87
+ return ["PROOF.bend must import the laws file as Laws"]
88
+ problems = []
89
+ if re.search(r"^law\s", proof, re.M):
90
+ problems.append("PROOF.bend states a law. Laws belong only in the laws file")
91
+ laws_path = os.path.join(os.path.dirname(proof_path), imported.group(1))
92
+ with open(laws_path, encoding="utf-8") as handle:
93
+ laws = handle.read()
94
+ if not re.search(r"^law\s", laws, re.M):
95
+ problems.append("the laws file states no law")
96
+ problems.extend(_unused_variables(laws))
97
+ approval = laws_path + ".approved"
98
+ if not os.path.isfile(approval):
99
+ problems.append("the user has not approved these laws. Show them to the user and call approve_laws after a yes")
100
+ else:
101
+ with open(approval, encoding="utf-8") as handle:
102
+ if handle.read().strip() != _digest(laws_path):
103
+ problems.append("the laws changed after the user approved them. Ask the user to approve them again")
104
+ return problems
105
+
106
+
107
+ def _unused_variables(laws):
108
+ """A law whose statement ignores one of its `for` variables usually does not say what the user meant."""
109
+ problems = []
110
+ for name, body in re.findall(r"^law\s+([\w.]+)\s*:[^\n]*\n((?:[ \t]+[^\n]*(?:\n|$))+)", laws, re.M):
111
+ lines = [line.split("#", 1)[0].strip() for line in body.splitlines()]
112
+ binders = [line[4:].split(":", 1)[0] for line in lines if line.startswith("for ")]
113
+ statement = " ".join(line for line in lines if line and not line.startswith("for "))
114
+ for binder in binders:
115
+ for variable in (part.strip().lstrip("+-") for part in binder.split(",")):
116
+ if variable and not re.search(r"(?<![\w.])" + re.escape(variable) + r"(?!\w)", statement):
117
+ problems.append("law " + name + " never uses its variable " + variable)
118
+ return problems
119
+
120
+
121
+ async def bend_check(proof_path, verdict=False):
122
+ """Run the gate on PROOF.bend. Passed needs exit 0, ALL PROOFS CHECK, and no problems.
123
+
124
+ Problems are structural: a law stated in the proof file, a laws file without laws, or laws that
125
+ differ from the approved ones. verdict=True adds --verdict, which rechecks with the Lean-proven
126
+ kernel and needs Lean installed.
127
+ """
128
+ bend = find_bend()
129
+ if bend is None:
130
+ raise RuntimeError("bend is not installed. Ask the user to run: " + BEND_INSTALL)
131
+ proof_path = os.path.abspath(proof_path)
132
+ problems = _problems(proof_path)
133
+ command = shlex.quote(bend) + " " + shlex.quote(os.path.basename(proof_path)) + (" --verdict" if verdict else " --check-only")
134
+ output, code = await _run(command, os.path.dirname(proof_path))
135
+ passed = code == 0 and "ALL PROOFS CHECK" in output and not problems
136
+ if problems:
137
+ output = "CHECK REJECTED: " + "; ".join(problems) + ". Bend's own output follows and does not count.\n" + output
138
+ return {
139
+ "verdict": "passed" if passed else ("failed" if code is not None else "inconclusive"),
140
+ "problems": problems,
141
+ "exit_code": code,
142
+ "output": output,
143
+ "command": command,
144
+ }
@@ -39,7 +39,7 @@ Remaining triggers:
39
39
 
40
40
  ## Reference index
41
41
 
42
- This is the only installed skill. Every other workflow is a reference under `references/<name>/SKILL.md`. Pick the reference whose description matches the task and read it in full before acting. Do not read them all.
42
+ Peak, `bend`, and `raga-artifacts` are the installed skills. `bend` handles Bend formal verification, and `raga-artifacts` makes shareable slides and documents. Every other workflow is a reference under `references/<name>/SKILL.md`. Pick the reference whose description matches the task and read it in full before acting. Do not read them all.
43
43
 
44
44
  ### Principles
45
45
 
@@ -12,7 +12,21 @@ Use the Python tool. It owns one persistent kernel per session. Load this adapte
12
12
 
13
13
  `await context.history(offset=0, limit=None)` reads only this session's history. Use explicitly provided current-instance records for historical research. Never scan another project's home or transcripts. `await llm_query(prompt, system=None, model=None)` is a one-shot model call. `await llm_batch(prompts, system=None, model=None)` runs independent one-shot calls.
14
14
 
15
- Load `raga_runtime.py` beside this skill with `exec(await read(absolute_helper_path), globals())`, then call `await run_child(spec, task, resource_root, context_data=None, model=None, max_turns=None, read_only=True, details=False)`. The resource root is the session's pinned harness path. Independent calls run with `await asyncio.gather(...)`. Writing children require `read_only=False, details=True` and receive isolated application workspaces from the supervisor. A context value is data, never a permission grant. The supervisor pins every child to the parent's harness revision.
15
+ Load `raga_runtime.py` beside this skill with `exec(await read(absolute_helper_path), globals())`, then call `await run_child(spec, task, resource_root, context_data=None, model=None, max_turns=None, read_only=True, details=False)`. Independent calls run with `await asyncio.gather(...)`. A context value is data, never a permission grant.
16
+
17
+ ## Pick the session mode first
18
+
19
+ Call `harness_mode()` before any child launch, `instance` call, or `memory` call. It returns `instance` or `ordinary`.
20
+
21
+ In an instance session, the resource root is the pinned harness path. Writing children require `read_only=False, details=True` and receive isolated application workspaces from the supervisor. The supervisor pins every child to the parent's harness revision. A `read_only=True` child gets the parent's workspace mounted read-only.
22
+
23
+ In an ordinary session, the resource root is the `bundled-skills` directory three levels above this file. That is the directory holding `skills/` and `agents/`. Children share the parent's checkout. Raga does not isolate them, collect their changes, or enforce `read_only=True`. Follow these rules:
24
+
25
+ - Make every code change in this session. `run_child` refuses `read_only=False`.
26
+ - Use `read_only=True` children for exploration, design sketches, and review. `run_child` adds a no-write instruction to each child prompt.
27
+ - A playbook step that delegates code writing is satisfied when this session owns the diff and a read-only child reviews it.
28
+ - `instance` and `memory` calls do not exist. Candidate authoring, child patches, integration workspaces, instance memory, and no-mistakes need instance mode. Skip those steps and report them as unavailable in ordinary mode.
29
+ - Commit, branch, and push only when the user asks. Preserve unrelated changes in the shared checkout.
16
30
 
17
31
  Child specifications are in `../../../agents/`. `poteto-agent` carries the engineering style. `comment-sicko` reviews comments. `worker` handles general tasks. Model selectors are real provider/model strings from the configured registry. `None` inherits the parent. Role settings live in `agents/model-roles.json` in a candidate revision. When different review seats resolve to the same family, report that the review is not model-diverse. Do not invent aliases or silently replace a rejected model.
18
32
 
@@ -20,15 +34,15 @@ Child specifications are in `../../../agents/`. `poteto-agent` carries the engin
20
34
 
21
35
  Only the documented run_child parameters are supported. Inherited spec labels select one of the three native specifications. Tool-schema, environment, cloud branch, background, resume, effort, and file-attachment fields from other agents are not launch arguments. Read-only review does not remove ordinary sandboxed inspection tools. Configure real model selectors in agents/model-roles.json. Null inherits. A rejected selector is a prerequisite failure, never permission to choose an unapproved substitute.
22
36
 
23
- Use `await instance.child_patch(workspace_id)` to collect a child's owned change and patch. Use `await instance.integrate(workspace_ids, command, args, timeout_ms=120000)` for one supervisor-owned integration workspace and combined verification after each merge. Inspect its accepted result and returned patch before applying changes to the root workspace. Do not create or remove Git worktrees from worker shell commands. Git administration is deliberately hidden. Portable prose that requests branches or worktrees means these supervisor APIs, not raw Git worktree mutation.
37
+ In instance mode, use `await instance.child_patch(workspace_id)` to collect a child's owned change and patch. Use `await instance.integrate(workspace_ids, command, args, timeout_ms=120000)` for one supervisor-owned integration workspace and combined verification after each merge. Inspect its accepted result and returned patch before applying changes to the root workspace. Do not create or remove Git worktrees from worker shell commands. Git administration is deliberately hidden. Portable prose that requests branches or worktrees means these supervisor APIs, not raw Git worktree mutation.
24
38
 
25
39
  Use an in-process bounded loop for autonomous work. A process exit ends the loop. There is no persistent wake scheduler or editor automation service. Keep ownership records in the instance state and stop descendant processes before cleanup.
26
40
 
27
41
  ## Candidate authoring
28
42
 
29
- `await instance.info()` reports the current pin. `candidate = await instance.candidate_create()` creates an editable proposal. Read and write its allowlisted resources with `await instance.candidate_read(candidate['id'], path)` and `await instance.candidate_write(candidate['id'], path, content)`. Use `await instance.candidate_commit(candidate['id'], message)` to commit it. Ordinary model filesystem access does not expose instance state or accepted artifacts. Do not invoke management CLI commands through shell. Promotion is a user CLI operation backed by exact-revision evidence, never a model approval.
43
+ Candidate authoring needs instance mode. `await instance.info()` reports the current pin. `candidate = await instance.candidate_create()` creates an editable proposal. Read and write its allowlisted resources with `await instance.candidate_read(candidate['id'], path)` and `await instance.candidate_write(candidate['id'], path, content)`. Use `await instance.candidate_commit(candidate['id'], message)` to commit it. Ordinary model filesystem access does not expose instance state or accepted artifacts. Do not invoke management CLI commands through shell. Promotion is a user CLI operation backed by exact-revision evidence, never a model approval.
30
44
 
31
- `await memory.search(query)`, `await memory.get(entry_id)`, and `await memory.observe(text, evidence)` access only this project's structured observations. Search returns observations, not an automatic proof that an earlier decision remains valid. Read the current source before reusing a lesson.
45
+ In instance mode, `await memory.search(query)`, `await memory.get(entry_id)`, and `await memory.observe(text, evidence)` access only this project's structured observations. Search returns observations, not an automatic proof that an earlier decision remains valid. Read the current source before reusing a lesson.
32
46
 
33
47
  ## Capabilities and dependencies
34
48
 
@@ -4,11 +4,21 @@ import os
4
4
  import shlex
5
5
  from pathlib import PurePosixPath
6
6
 
7
+ ORDINARY_READ_ONLY = "This child shares the parent's checkout in an ordinary raga session, and raga does not enforce read-only access here. Do not create, edit, delete, format, stage, or commit files. Do not run commands that write to the project."
8
+
9
+
10
+ def harness_mode():
11
+ return "instance" if os.environ.get("RAGA_INSTANCE_ID") else "ordinary"
12
+
13
+
7
14
  async def run_child(spec, task, resource_root, context_data=None, model=None, max_turns=None, read_only=True, details=False):
8
15
  if spec not in ("worker", "poteto-agent", "comment-sicko"):
9
16
  raise ValueError("Unknown bundled child specification")
10
17
  if not read_only and not details:
11
18
  raise ValueError("Writing children require details=True for supervisor-owned change evidence")
19
+ ordinary = harness_mode() == "ordinary"
20
+ if ordinary and not read_only:
21
+ raise ValueError("Ordinary raga sessions have no isolated child workspaces. Make the change in this session and use read_only=True children for exploration and review")
12
22
  root = resource_root.rstrip("/")
13
23
  definition = json.loads(await read(root + "/agents/" + spec + ".json"))
14
24
  definition_path = PurePosixPath(definition["instructions"])
@@ -21,7 +31,8 @@ async def run_child(spec, task, resource_root, context_data=None, model=None, ma
21
31
  roles = json.loads(await read(root + "/agents/model-roles.json"))
22
32
  if model is None:
23
33
  model = roles.get(definition["modelRole"])
24
- prompt = instructions + "\n\nPinned resource root: " + root + "\n\n# Assignment\n" + task
34
+ notice = "\n\n" + ORDINARY_READ_ONLY if ordinary else ""
35
+ prompt = instructions + "\n\nPinned resource root: " + root + notice + "\n\n# Assignment\n" + task
25
36
  return await rlm_query(prompt, context=context_data, model=model, max_turns=max_turns, read_only=read_only, details=details)
26
37
 
27
38
  async def capability_report():
@@ -0,0 +1,117 @@
1
+ ---
2
+ name: raga-artifacts
3
+ description: Make shareable slides and documents for developers and clients, with Mermaid diagrams rendered by Pele, exported as a self-contained HTML file and a PDF. Use when the user asks for a deck, slides, a report, a proposal, a one-pager, or another polished document to share.
4
+ ---
5
+
6
+ # Raga artifacts
7
+
8
+ You make slides and documents the user can send to developers and clients. You write one static HTML source file. The builder renders its Mermaid diagrams to SVG with Pele, highlights code, inlines local images, and prints a PDF with headless Chrome. The results are `dist/<name>.html`, which works offline, and `dist/<name>.pdf`.
9
+
10
+ ## Load the helper
11
+
12
+ Work in the Python tool:
13
+
14
+ ```python
15
+ exec(await read("<directory of this SKILL.md>/artifact_tool.py"), globals())
16
+ artifact_setup("<directory of this SKILL.md>")
17
+ ```
18
+
19
+ ## Steps
20
+
21
+ 1. **Ask what to make.** Ask the user, then wait for the answer:
22
+ - Slides or a document?
23
+ - Who reads it: developers, clients, or both?
24
+ - What should the reader know or decide at the end?
25
+ - Which material should it use: files, notes, or this conversation?
26
+ - Is there a theme or brand color?
27
+
28
+ If the user already answered these, do not ask again.
29
+ 2. **Outline.** Propose an outline: one line per slide, or one line per section. Wait for approval before you write the full artifact. Keep decks to 6 to 12 slides unless the user asks for more.
30
+ 3. **Start from a template.** Run `artifact_new("slides", "artifacts/<name>/<name>.html")` or `artifact_new("doc", ...)`. The default folder is `artifacts/` in the project. Use the template's markup and classes.
31
+ 4. **Write the content.** Edit the source file with the edit or write tools.
32
+ 5. **Build and look.** Run `result = await artifact_build(path, preview=True)`. If `result["ok"]` is false, fix every item in `problems` and build again. Fix every item in `layout`: each one is a slide or block that does not fit its page. Read every item in `warnings`. If your tools can show you images, open `result["preview"]` and fix crowded slides, unreadable diagrams, and awkward empty space. The Python REPL's `read` returns raw bytes for images, so in a REPL session rely on `layout` and ask the user to look at the PDF.
33
+ 6. **Hand it over.** Give the user the PDF path and the HTML path. Report the slide or page count and any warning you did not fix. Then offer the sharing options below.
34
+
35
+ ## Writing rules
36
+
37
+ - Each slide makes one point, and its title states that point as a sentence. Use at most five bullets.
38
+ - For clients, lead with the outcome and the decision you need. For developers, show the design, the trade-offs, and the code.
39
+ - Prefer a diagram, a table, or one large number over a paragraph.
40
+ - Do not invent numbers, quotes, logos, or customer names. Use only what the user or the project provides, and mark estimates as estimates.
41
+
42
+ ## Markup
43
+
44
+ The templates define these pieces. Combine them instead of writing new CSS:
45
+
46
+ | Markup | Use |
47
+ |---|---|
48
+ | `<section class="slide">` | One slide. Add `title`, `section`, or `statement` for those layouts. |
49
+ | `<div class="kicker">` | Small label above a title |
50
+ | `<div class="cols" style="--cols: 3">` | Columns. The default is 2. |
51
+ | `<div class="card">` | A boxed group |
52
+ | `<div class="stat"><div class="value">42%</div><div class="label">...</div></div>` | A large number |
53
+ | `<div class="callout good">` | A highlighted note. Variants are `good`, `warn`, and `bad`. |
54
+ | `<span class="tag">` | A small label |
55
+ | `<pre class="mermaid">...</pre>` | A diagram in Mermaid syntax. Escape `<`, `>`, and `&` as `&lt;`, `&gt;`, and `&amp;`. |
56
+ | `<pre><code class="language-ts">...</code></pre>` | Code, highlighted at build time |
57
+ | `<img src="images/x.png">` | A local image, inlined at build time |
58
+ | `<div class="footer">` | Slide footer |
59
+ | `<div class="page-break">` | Start a new page in a document |
60
+
61
+ Set the theme with `data-theme` on `<html>`. The values are `light`, `dark`, and `ink`. To use a brand color, change `--accent` and `--accent-soft` in the `:root` block. Diagrams take their colors from the same variables.
62
+
63
+ ## Diagrams
64
+
65
+ Pele renders these 32 diagram types. Pick the type that fits the point, not always a flowchart. Before you write a type for the first time in a session, read its example in [diagrams.md](diagrams.md). Always do this for keywords that end in `-beta` and for `eventmodeling`, because their syntax is new.
66
+
67
+ | Type | Keyword | Use for | Audience |
68
+ |---|---|---|---|
69
+ | Flowchart | `flowchart LR` | Processes, decisions, pipelines | both |
70
+ | Sequence | `sequenceDiagram` | Requests between services or people over time | developers |
71
+ | Class | `classDiagram` | Types, interfaces, and their relations | developers |
72
+ | State | `stateDiagram-v2` | Lifecycles and state machines | developers |
73
+ | Entity relationship | `erDiagram` | Database tables and relations | developers |
74
+ | C4 | `C4Context` | System context, containers, components | both |
75
+ | Architecture | `architecture-beta` | Cloud and service topology with groups and icons | both |
76
+ | Block | `block` | Layered or grid layouts of components | developers |
77
+ | Packet | `packet` | Bit and byte layouts of protocols or file formats | developers |
78
+ | Git graph | `gitGraph` | Branching and release strategy | developers |
79
+ | Agentflow | `agentflow-beta` | AI agent and tool-call workflows | developers |
80
+ | Railroad | `railroad-ebnf-beta` | Grammar and syntax rules | developers |
81
+ | Event modeling | `eventmodeling` | Commands, events, and views of an event-driven system | developers |
82
+ | Requirement | `requirementDiagram` | Requirements and what satisfies or verifies them | both |
83
+ | Gantt | `gantt` | Schedules with tasks and dependencies | clients |
84
+ | Timeline | `timeline` | Milestones and history | clients |
85
+ | Kanban | `kanban` | Work status by column | clients |
86
+ | User journey | `journey` | Steps a user takes, with satisfaction scores | clients |
87
+ | Mindmap | `mindmap` | Topics and ideas branching from one center | clients |
88
+ | Use case | `usecase-beta` | Actors and what they can do | both |
89
+ | Swimlane | `swimlane-beta` | A process split by team or role | clients |
90
+ | Tree view | `treeView-beta` | File trees and hierarchies | developers |
91
+ | Pie | `pie` | Parts of a whole, at most six slices | clients |
92
+ | XY chart | `xychart` | Bar and line charts over a series | clients |
93
+ | Quadrant chart | `quadrantChart` | Two-axis prioritization, such as effort against impact | clients |
94
+ | Sankey | `sankey` | Flows of volume, money, or traffic between stages | clients |
95
+ | Treemap | `treemap-beta` | Sizes of nested parts, such as cost or code by module | both |
96
+ | Radar | `radar-beta` | Comparing options across several criteria | clients |
97
+ | Venn | `venn-beta` | Overlap between groups | clients |
98
+ | Ishikawa | `ishikawa-beta` | Root causes of a problem, fishbone style | both |
99
+ | Cynefin | `cynefin-beta` | Sorting problems by how predictable they are | clients |
100
+ | Wardley map | `wardley-beta` | Strategy: components by visibility and maturity | clients |
101
+
102
+ Keep a slide diagram to about 15 nodes. If a diagram fails to build, the problem names the diagram number. Compare it with the example and fix the syntax.
103
+
104
+ ## Limits the builder enforces
105
+
106
+ - No `<script>`, `<iframe>`, `<object>`, or `<embed>`. Artifacts are static so they print and share safely.
107
+ - No remote images, stylesheets, or fonts. Download images next to the source. Fonts come from the reader's system: the theme lists Inter first and falls back to system fonts.
108
+ - A slide whose content overflows its 1600 by 900 frame adds a PDF page. The builder warns when the page count differs from the slide count.
109
+
110
+ ## Sharing
111
+
112
+ The PDF is the default deliverable. It opens everywhere and looks the same for every reader. The HTML file is a second copy for screens.
113
+
114
+ Offer these only when the user asks for a link, and run any of them only after the user agrees, because each one publishes the file:
115
+
116
+ - A secret GitHub gist: `gh gist create dist/<name>.html`. Anyone with the link can read it. GitHub shows HTML in a gist as source code, so readers must download the file to view it.
117
+ - A static host the user already uses, such as GitHub Pages.