babavoss 0.12.5 → 0.13.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 (52) hide show
  1. package/gui/babavoss-web.js +234 -0
  2. package/gui/chunk-5hpp1ypv.js +11710 -0
  3. package/gui/chunk-a20zfekq.js +8639 -0
  4. package/gui/chunk-k3cm8j6r.js +433 -0
  5. package/gui/chunk-pk09y98y.js +50 -0
  6. package/gui/chunk-smz02qa6.js +186 -0
  7. package/gui/chunk-wwqypxre.js +49 -0
  8. package/gui/gui.js +2015 -0
  9. package/gui/react-compiler-runtime.js +39 -0
  10. package/gui/react-dom-client.js +21 -0
  11. package/gui/react-dom.js +44 -0
  12. package/gui/react-jsx-runtime.js +19 -0
  13. package/gui/react.js +105 -0
  14. package/gui/theme.css +3053 -0
  15. package/index.ts +1 -1
  16. package/package.json +8 -6
  17. package/src/{promptware → agents}/compile.ts +12 -12
  18. package/src/{promptware → agents}/define.ts +2 -2
  19. package/src/{promptware → agents}/disk.ts +7 -4
  20. package/src/{promptware → agents}/sync.ts +2 -2
  21. package/src/{promptware → agents}/system.ts +17 -17
  22. package/src/baba/check.ts +3 -3
  23. package/src/baba/config.ts +5 -2
  24. package/src/baba/init.ts +13 -18
  25. package/src/baba/node.ts +2 -2
  26. package/src/baba/worker.ts +13 -5
  27. package/src/build/mdx.ts +4 -4
  28. package/src/build/project.ts +6 -1
  29. package/src/build/views.ts +3 -3
  30. package/src/desktop/index.ts +1 -1
  31. package/src/door/core.ts +2 -2
  32. package/src/ecs/baba.ts +27 -17
  33. package/src/generated/build.ts +1 -1
  34. package/src/gui/gui.tsx +3 -3
  35. package/src/gui/{promptware.tsx → instructions.tsx} +12 -12
  36. package/src/gui/theme.css +1 -1
  37. package/src/guide/add-a-desktop.mdx +2 -2
  38. package/src/guide/index.ts +4 -4
  39. package/src/guide/write-a-system.mdx +3 -3
  40. package/src/guide/{write-promptware.mdx → write-agentic-instructions.mdx} +17 -24
  41. package/src/{prompt → instructions}/evals.ts +1 -1
  42. package/src/{prompt → instructions}/index.ts +9 -8
  43. package/src/{prompt → instructions}/jsx-runtime.ts +3 -3
  44. package/src/mcp/main.ts +3 -3
  45. package/src/mcp/tools.ts +4 -4
  46. package/src/runtime/harness.ts +2 -2
  47. package/src/shell/run.ts +18 -18
  48. package/src/spec/index.ts +1 -1
  49. package/src/web/core.tsx +2 -2
  50. /package/src/{promptware → agents}/markdown.d.ts +0 -0
  51. /package/src/{prompt → instructions}/jsx-dev-runtime.ts +0 -0
  52. /package/src/{prompt → instructions}/mdx.d.ts +0 -0
package/index.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  // babavoss: the framework. What a baba imports.
2
- export { baba, effect, source, accept, resource, shape, manifestOf, isBaba, isSystem, nameOf, SYSTEM } from "./src/ecs/baba.ts";
2
+ export { baba, instructed, effect, source, accept, resource, shape, manifestOf, isBaba, isSystem, nameOf, SYSTEM } from "./src/ecs/baba.ts";
3
3
  export { system, declare, part } from "./src/ecs/system.ts";
4
4
  export type { Decl, Entry, Handles, HandlesOf, Building, Maker, Part, Piece, Maybe, StepPiece, OnPiece, ActionPiece, QueryPiece, BindingOf, Scope, Reader, StateOf, ReaderOf, Act, Read } from "./src/ecs/system.ts";
5
5
  export { not, added, changed, removed, select } from "./src/ecs/state.ts";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "babavoss",
3
- "version": "0.12.5",
3
+ "version": "0.13.0",
4
4
  "license": "Apache-2.0",
5
5
  "repository": "github:alanremarc/babavoss",
6
6
  "homepage": "https://babavoss.org",
@@ -14,13 +14,13 @@
14
14
  "./web": "./src/web/index.tsx",
15
15
  "./test": "./src/test/index.ts",
16
16
  "./bench": "./src/bench/index.ts",
17
- "./prompt": "./src/prompt/index.ts",
18
- "./prompt/jsx-runtime": "./src/prompt/jsx-runtime.ts",
19
- "./prompt/jsx-dev-runtime": "./src/prompt/jsx-dev-runtime.ts",
17
+ "./instructions": "./src/instructions/index.ts",
18
+ "./instructions/jsx-runtime": "./src/instructions/jsx-runtime.ts",
19
+ "./instructions/jsx-dev-runtime": "./src/instructions/jsx-dev-runtime.ts",
20
20
  "./desktop": "./src/desktop/index.ts",
21
21
  "./kit": "./src/kit/index.ts",
22
22
  "./spec": "./src/spec/index.ts",
23
- "./prompt/register": "./src/build/mdx-register.ts"
23
+ "./instructions/register": "./src/build/mdx-register.ts"
24
24
  },
25
25
  "files": [
26
26
  "bin",
@@ -37,7 +37,9 @@
37
37
  "test": "bun test",
38
38
  "test:kernel": "VOSS_KERNEL=1 bun test ./test/kernel.test.ts",
39
39
  "test:all": "VOSS_KERNEL=1 bun test",
40
- "check": "bunx tsc --noEmit -p ../.."
40
+ "check": "bunx tsc --noEmit -p ../..",
41
+ "prepack": "bun ../../tools/release/pack.ts prepack",
42
+ "postpack": "bun ../../tools/release/pack.ts postpack"
41
43
  },
42
44
  "devDependencies": {
43
45
  "@types/react-dom": "19"
@@ -1,15 +1,15 @@
1
- // Promptware to harness files, as text. Pure: the manifest, with the baba's
1
+ // Instructions to harness files, as text. Pure: the manifest, with the baba's
2
2
  // context and skills rendered and its harness declaration, becomes what
3
3
  // each output path, relative to the project, should hold.
4
4
  //
5
5
  // Claude Code CLAUDE.md .claude/skills/NAME/SKILL.md .claude/settings.local.json
6
6
  // Codex AGENTS.md .agents/skills/NAME/SKILL.md
7
7
  //
8
- // Promptware is know-how; the contract teaches itself at the doors, the
8
+ // Instructions is know-how; the contract teaches itself at the doors, the
9
9
  // CLI's index and schemas and the MCP server's tools. The instruction file
10
10
  // teaches the doors, true whatever the contract becomes; the table of calls
11
11
  // is rendered only when the baba asks for it. The MCP registration is
12
- // not promptware's: it is the machine's. The permissions, in a file the
12
+ // not agentic instructions's: it is the machine's. The permissions, in a file the
13
13
  // project shares with others, are a merge: voss owns only its entries.
14
14
  import type { Json } from "../kernel/schema.ts";
15
15
  import type { Manifest } from "../ecs/baba.ts";
@@ -18,7 +18,7 @@ import { exampleOf } from "../ecs/handles.ts";
18
18
  import { skillsOf, type SkillManifest } from "./define.ts";
19
19
 
20
20
  /** The systems voss gives every baba: their calls are not the project's contract. */
21
- export const VOSS = new Set(["promptware", "maker"]);
21
+ export const VOSS = new Set(["agents", "maker"]);
22
22
 
23
23
  export type Harness = "claude" | "codex";
24
24
  export const harnesses: Harness[] = ["claude", "codex"];
@@ -31,8 +31,8 @@ const files: Record<Harness, { instructions: string; skills: string }> = {
31
31
  /** Which harness an output path belongs to. */
32
32
  export const harnessOf = (path: string): Harness => (path === "AGENTS.md" || path.startsWith(".agents/") || path.startsWith(".codex/") ? "codex" : "claude");
33
33
 
34
- /** Where the promptware lives, relative to the project. */
35
- export const SOURCE = ".baba/promptware";
34
+ /** Where the agentic instructions lives, relative to the project. */
35
+ export const SOURCE = ".baba/agents";
36
36
 
37
37
  // ---- merges ------------------------------------------------------------
38
38
 
@@ -55,11 +55,11 @@ export type Merge =
55
55
  export const CLAUDE_SETTINGS = ".claude/settings.local.json";
56
56
 
57
57
  /**
58
- * The outputs are made from the promptware: a checkout makes its own with `voss baba promptware sync` (a landing does),
58
+ * The outputs are made from the agentic instructions: a checkout makes its own with `voss baba agents sync` (a landing does),
59
59
  * and git keeps none of them. Voss's lines of the project's .gitignore say so.
60
60
  */
61
61
  export const ignoreLines = (): string[] => [
62
- "# voss makes these from .baba/promptware: `voss baba promptware sync` writes them, git keeps none",
62
+ "# voss makes these from .baba/agents: `voss baba agents sync` writes them, git keeps none",
63
63
  ...harnesses.flatMap((h) => [`/${files[h].instructions}`, `/${files[h].skills}/`]),
64
64
  `/${CLAUDE_SETTINGS}`,
65
65
  ];
@@ -108,7 +108,7 @@ export function compile(input: CompileInput): Compiled {
108
108
  const perms = st.claude.permissions;
109
109
  if (perms.length) lists.push({ at: ["permissions", "allow"], values: [...new Set(perms)] });
110
110
  const byEvent = new Map<string, unknown[]>();
111
- for (const hk of input.manifest.promptware.hooks) {
111
+ for (const hk of input.manifest.instructions.hooks) {
112
112
  const command = `${input.program} ${hk.action} @- --hook ${hk.on}${hk.strict ? " --strict=true" : ""}`;
113
113
  const entry = { ...(hk.match ? { matcher: hk.match } : {}), hooks: [{ type: "command", command }] };
114
114
  if (!byEvent.has(hk.on)) byEvent.set(hk.on, []);
@@ -136,10 +136,10 @@ function instructionFile(input: CompileInput): string {
136
136
  const prog = input.program;
137
137
  const m = input.manifest;
138
138
  const lines = [
139
- `<!-- Generated by ${prog} from the baba's promptware. Do not edit: a hand edit is held and never overwritten. Edit the promptware; it syncs. -->`,
139
+ `<!-- Generated by ${prog} from the baba's agentic instructions. Do not edit: a hand edit is held and never overwritten. Edit the agentic instructions under .baba/agents/; they sync. -->`,
140
140
  `# ${input.title ?? prog}`,
141
141
  ];
142
- const context = m.promptware.context?.trim();
142
+ const context = m.instructions.context?.trim();
143
143
  if (context) lines.push("", context);
144
144
  lines.push(
145
145
  "", "## This baba", "",
@@ -172,7 +172,7 @@ function instructionFile(input: CompileInput): string {
172
172
  ...Object.entries(m.queries).filter(([, q]) => !VOSS.has(q.owner)).map(([n, q]) => `| \`${prog} ${[n, ...usage(q.args, q.positional)].join(" ")}\` | query | ${q.owner} | ${system(q.summary)} |`),
173
173
  );
174
174
  }
175
- lines.push("", "Voss adds two systems to this baba. `promptware` compiles what the baba tells agents, its context, skills and hooks written as code under `.baba/promptware/`, into each harness's files: `CLAUDE.md`, `AGENTS.md`, the skills, Claude Code's permissions and hooks. Those are generated: edit the promptware, never the outputs. `maker` keeps the specs, each system's `systems/NAME/spec.ts` beside it and the whole baba's `.baba/spec.ts`, each a seeded state with its scenarios and the adapters that play its outside, proved under `bun test` by `.baba/spec.test.ts`; `spec` lists them with their verdicts, `spec-run` runs a state's scenarios headless so the verdicts are remade, and the Maker app runs them live, where `spec-step` and `spec-read` reach the state a person has open.");
175
+ lines.push("", "Voss adds two systems to this baba. `agents` compiles what the baba tells agents, its context, skills and hooks, each an .mdx file under `.baba/agents/`, into each harness's files: `CLAUDE.md`, `AGENTS.md`, the skills, Claude Code's permissions and hooks. Those are generated: edit the agentic instructions, never the outputs. `maker` keeps the specs, each system's `systems/NAME/spec.ts` beside it and the whole baba's `.baba/spec.ts`, each a seeded state with its scenarios and the adapters that play its outside, proved under `bun test` by `.baba/spec.test.ts`; `spec` lists them with their verdicts, `spec-run` runs a state's scenarios headless so the verdicts are remade, and the Maker app runs them live, where `spec-step` and `spec-read` reach the state a person has open.");
176
176
  const skills = skillsOf(m).map((sk) => sk.name);
177
177
  if (skills.length) lines.push("", `Skills: ${skills.join(", ")}.`);
178
178
  return lines.join("\n") + "\n";
@@ -1,4 +1,4 @@
1
- // What a baba tells agent harnesses, as data: its promptware rendered into
1
+ // What a baba tells agent harnesses, as data: its agentic instructions rendered into
2
2
  // the manifest; the kernel renders the files from it.
3
3
  import type { Manifest } from "../ecs/baba.ts";
4
4
 
@@ -8,7 +8,7 @@ export interface SkillManifest { name: string; description: string; body: string
8
8
  /** The skills of a manifest, by name, each checked to name actions and queries that exist. */
9
9
  export function skillsOf(m: Manifest): SkillManifest[] {
10
10
  const out: SkillManifest[] = [];
11
- for (const [name, s] of Object.entries(m.promptware.skills).sort(([a], [b]) => a.localeCompare(b))) {
11
+ for (const [name, s] of Object.entries(m.instructions.skills).sort(([a], [b]) => a.localeCompare(b))) {
12
12
  for (const u of s.uses ?? []) if (!(u in m.actions) && !(u in m.queries)) throw new Error(`skill ${name} uses ${u}, which is not an action or query of the baba`);
13
13
  out.push({ name, description: s.description, body: s.body, uses: [...(s.uses ?? [])] });
14
14
  }
@@ -1,5 +1,5 @@
1
- // Promptware with the baba down: the shell reads the manifest the last load
2
- // wrote, which carries the baba's promptware rendered and its harness, and
1
+ // Instructions with the baba down: the shell reads the manifest the last load
2
+ // wrote, which carries the baba's agentic instructions rendered and its harness, and
3
3
  // runs the same compiler and the same plan the system runs.
4
4
  import { join, dirname } from "node:path";
5
5
  import { lstat, mkdir, rename, rm, rmdir } from "node:fs/promises";
@@ -32,7 +32,7 @@ async function look(root: string, path: string): Promise<Seen> {
32
32
 
33
33
  async function writeAtomic(path: string, text: string): Promise<void> {
34
34
  await mkdir(dirname(path), { recursive: true });
35
- const tmp = join(dirname(path), `.promptware-${crypto.randomUUID()}`);
35
+ const tmp = join(dirname(path), `.agents-${crypto.randomUUID()}`);
36
36
  try {
37
37
  await Bun.write(tmp, text);
38
38
  await rename(tmp, path);
@@ -44,7 +44,10 @@ async function writeAtomic(path: string, text: string): Promise<void> {
44
44
 
45
45
  /** What the compiler takes for the project at root. */
46
46
  export function sources(_root: string, manifest: Manifest, title?: string): CompileInput {
47
- return { program: "voss baba", ...(title !== undefined ? { title } : {}), manifest };
47
+ // A manifest an older voss wrote names the instructions `promptware`: read as they are.
48
+ const older = (manifest as unknown as { promptware?: Manifest["instructions"] }).promptware;
49
+ const m = manifest.instructions || !older ? manifest : { ...manifest, instructions: older };
50
+ return { program: "voss baba", ...(title !== undefined ? { title } : {}), manifest: m };
48
51
  }
49
52
 
50
53
  /** Compiles and plans against the project at root. Writes nothing. */
@@ -1,4 +1,4 @@
1
- // Compiled promptware onto disk, owning only what it wrote. The state file
1
+ // Compiled agentic instructions onto disk, owning only what it wrote. The state file
2
2
  // records the sha256 of every output the compiler last wrote, and of its
3
3
  // part of a shared file; comparing it with the files gives each output a
4
4
  // status:
@@ -25,7 +25,7 @@ export type Status = "current" | "stale" | "missing" | "held" | "foreign";
25
25
  export type Action = "write" | "remove";
26
26
 
27
27
  /** Relative to the project root. */
28
- export const statePath = ".baba/.voss/promptware.json";
28
+ export const statePath = ".baba/.voss/agents.json";
29
29
 
30
30
  /** What the compiler last wrote: output path to the hash of its text, or of its part of a shared file, and those parts. */
31
31
  export interface Written {
@@ -1,5 +1,5 @@
1
- // The promptware system: voss gives it to every baba. The know-how is the
2
- // baba's promptware, rendered into the manifest with its harness
1
+ // The agents system: voss gives it to every baba. The know-how is the
2
+ // baba's agentic instructions, rendered into the manifest with its harness
3
3
  // declaration; this system's state is the outputs' hashes; its effects
4
4
  // compile the know-how for each harness and write the files through the
5
5
  // kernel. The system is made per baba, given the manifest of the
@@ -7,7 +7,7 @@
7
7
  import { effect, manifestOf, resource, baba, nameOf, type Manifest, type Baba } from "../ecs/baba.ts";
8
8
  import { system, type StateOf } from "../ecs/system.ts";
9
9
  import { s } from "../kernel/schema.ts";
10
- import type { Prompt } from "../prompt/index.ts";
10
+ import type { Prompt } from "../instructions/index.ts";
11
11
  import type { Fs } from "../kernel/context.ts";
12
12
  import type { Value } from "../ecs/state.ts";
13
13
  import maker from "../maker/system.ts";
@@ -65,9 +65,9 @@ const writtenRow = s.object({ path: s.string(), hash: s.string(), harness: s.str
65
65
  * nothing. Its rows are resources, not entities: voss's own system takes no
66
66
  * ids from the baba's sequence and adds nothing to its entities.
67
67
  */
68
- export const promptwareSystem = (manifest: () => Manifest | null) => system({
69
- // promptware, declared: the same for every baba; what it compiles is the manifest each implementation is given.
70
- name: "promptware",
68
+ export const agentsSystem = (manifest: () => Manifest | null) => system({
69
+ // agentic instructions, declared: the same for every baba; what it compiles is the manifest each implementation is given.
70
+ name: "agents",
71
71
  model: {
72
72
  /** One row per output of the last plan: its hash on disk then, its harness, its status and what a sync does there. */
73
73
  pwWritten: resource(s.array(writtenRow), []),
@@ -105,9 +105,9 @@ export const promptwareSystem = (manifest: () => Manifest | null) => system({
105
105
  },
106
106
  }),
107
107
  },
108
- }, (promptware, p) => {
109
- type W = StateOf<typeof promptware>;
110
- const { pwWritten, pwStatus, pwScan, pwWrite } = promptware;
108
+ }, (agents, p) => {
109
+ type W = StateOf<typeof agents>;
110
+ const { pwWritten, pwStatus, pwScan, pwWrite } = agents;
111
111
  const setIf = <K extends typeof pwWritten | typeof pwStatus>(w: W, r: K, v: Value<K>) => { if (!same(w.get(r), v)) w.set(r, v); };
112
112
 
113
113
  /** The outputs the state compiles to and their key; null before the baba has a manifest. */
@@ -148,7 +148,7 @@ export const promptwareSystem = (manifest: () => Manifest | null) => system({
148
148
  },
149
149
  }),
150
150
 
151
- // What the baba's promptware compiles to, planned when it changed, written when the harness says auto or a sync asked.
151
+ // What the baba's agentic instructions compiles to, planned when it changed, written when the harness says auto or a sync asked.
152
152
  p.step("plan", (w) => {
153
153
  const st = w.get(pwStatus);
154
154
  if (w.running(pwWrite) || !st.scanned) return;
@@ -167,7 +167,7 @@ export const promptwareSystem = (manifest: () => Manifest | null) => system({
167
167
  });
168
168
  }),
169
169
 
170
- p.action("promptware-sync", {
170
+ p.action("agents-sync", {
171
171
  summary: "compile the know-how for each harness and write the files now",
172
172
  result: s.object({ asked: s.boolean(), outputs: s.array(writtenRow) }),
173
173
  run: (w) => {
@@ -176,7 +176,7 @@ export const promptwareSystem = (manifest: () => Manifest | null) => system({
176
176
  },
177
177
  }),
178
178
 
179
- p.query("promptware-plan", {
179
+ p.query("agents-plan", {
180
180
  summary: "each output of each harness: its status and what a sync does there",
181
181
  result: s.object({ auto: s.boolean(), lastSync: s.nullable(s.integer()), syncs: s.integer(), pending: s.integer(), error: s.nullable(s.string()), outputs: s.array(writtenRow) }),
182
182
  read: (w) => {
@@ -187,7 +187,7 @@ export const promptwareSystem = (manifest: () => Manifest | null) => system({
187
187
  ];
188
188
  });
189
189
 
190
- /** What voss tells agents in every baba, after the baba's own promptware: its skills. The word on the two systems it adds is the compiler's, in the shell of the context file. */
190
+ /** What voss tells agents in every baba, after the baba's own agentic instructions: its skills. The word on the two systems it adds is the compiler's, in the shell of the context file. */
191
191
  const voss: readonly Prompt[] = guide;
192
192
 
193
193
  /** Voss's own systems, by identity: filtered from what a project's docs and tables show. */
@@ -195,20 +195,20 @@ export const ours = new WeakSet<object>();
195
195
  export const isOurs = (c: object) => ours.has(c);
196
196
 
197
197
  /** The baba with voss's own systems after its own: what the runtime runs. Every baba gets the shell, the desktop system, over the apps it declares. */
198
- export function withPromptware(v: Baba): Baba {
198
+ export function withInstructions(v: Baba): Baba {
199
199
  if (v.systems.some((c) => ours.has(c))) return v;
200
- for (const name of ["promptware", "maker"]) if (v.systems.some((c) => nameOf(c) === name)) throw new Error(`a system of this baba is named ${name}, which voss gives every baba; name it otherwise`);
200
+ for (const name of ["agents", "maker"]) if (v.systems.some((c) => nameOf(c) === name)) throw new Error(`a system of this baba is named ${name}, which voss gives every baba; name it otherwise`);
201
201
  // A baba from before the shell was voss's brings its own desktop system, and keeps it; one system or the other, never both.
202
202
  const own = v.systems.find((c) => nameOf(c) === "desktop");
203
203
  if (own && v.apps.length) throw new Error("this baba declares apps and also has a system named desktop; the shell is voss's now: drop the system and keep baba({ apps })");
204
204
  let m: Manifest | null = null;
205
- const pw = promptwareSystem(() => m);
205
+ const pw = agentsSystem(() => m);
206
206
  const catalog = own ? v.apps : catalogOf(v.apps);
207
207
  const shell = own ? null : desktop({ apps: catalog });
208
208
  ours.add(pw);
209
209
  ours.add(maker);
210
210
  if (shell) ours.add(shell);
211
- const composed = baba({ systems: [...v.systems, ...(shell ? [shell] : []), pw, maker], apps: catalog, promptware: [...v.promptware, ...voss], harness: v.harness, ...(v.tick !== null ? { tick: v.tick } : {}) });
211
+ const composed = baba({ systems: [...v.systems, ...(shell ? [shell] : []), pw, maker], apps: catalog, instructions: [...v.instructions, ...voss], harness: v.harness, ...(v.tick !== null ? { tick: v.tick } : {}) });
212
212
  m = manifestOf(composed);
213
213
  return composed;
214
214
  }
package/src/baba/check.ts CHANGED
@@ -81,10 +81,10 @@ export async function check(p: Project, stdout: (s: string) => void, stderr: (s:
81
81
  }
82
82
  if (err) stderr(err);
83
83
  }
84
- const mdx = [...new Bun.Glob("promptware/**/*.mdx").scanSync({ cwd: p.baba })];
84
+ const mdx = [...new Bun.Glob("agents/**/*.mdx").scanSync({ cwd: p.baba })];
85
85
  if (mdx.length) {
86
- try { await bundleProject(p); stdout("promptware MDX: clean\n"); }
87
- catch (error) { failed = true; stderr(`promptware MDX: ${String(error)}\n`); }
86
+ try { await bundleProject(p); stdout("agentic instructions MDX: clean\n"); }
87
+ catch (error) { failed = true; stderr(`agentic instructions MDX: ${String(error)}\n`); }
88
88
  }
89
89
  return failed ? 1 : 0;
90
90
  }
@@ -38,7 +38,7 @@ const note = "Written by voss on every load. Edit .baba/tsconfig.json to extend
38
38
  export function editorConfig(): string {
39
39
  return JSON.stringify({
40
40
  "//": note,
41
- // JSX is React's unless a file says otherwise: promptware, TSX that renders to Markdown, names its runtime with a pragma.
41
+ // JSX is React's unless a file says otherwise: agentic instructions, TSX that renders to Markdown, names its runtime with a pragma.
42
42
  // No alias here: the project's tsconfig.json, which extends this, states `@/` relative to itself, and tools that read it resolve it there.
43
43
  compilerOptions: { lib: ["ESNext"], ...options, jsx: "react-jsx", jsxImportSource: "react" },
44
44
  include: ["guard.d.ts", "assets.d.ts", "../**/*.ts"],
@@ -205,7 +205,7 @@ export function assetDeclarations(): string {
205
205
  "// Written by voss on every load: what a baba imports besides code.",
206
206
  "// Text: `import guide from \"./guide.md\" with { type: \"text\" }`.",
207
207
  ...["md", "txt"].map((ext) => `declare module "*.${ext}" {\n const text: string;\n export default text;\n}`),
208
- `declare module "*.mdx" { const prompt: import("babavoss/prompt").Prompt; export default prompt; }`,
208
+ `declare module "*.mdx" { const prompt: import("babavoss/instructions").Prompt; export default prompt; }`,
209
209
  "// Every spec of the baba, found where it lives (systems/NAME/spec.ts, spec.ts): what the Maker's page runs.",
210
210
  `declare module "babavoss:specs" { const specs: import("babavoss/spec").Spec<any, any>[]; export default specs; }`,
211
211
  "// A stylesheet, bundled with the view and attached to its windows: `import \"./view.css\"`.",
@@ -242,6 +242,9 @@ export async function writeEditorConfig(p: Project): Promise<string> {
242
242
  * tsconfig.json and .gitignore that pointed there follow.
243
243
  */
244
244
  export async function moveOldDir(p: Project): Promise<void> {
245
+ // The agentic instructions lived in .baba/promptware, their record in .voss/promptware.json: moved once, by name.
246
+ if (existsSync(join(p.baba, "promptware")) && !existsSync(join(p.baba, "agents"))) await rename(join(p.baba, "promptware"), join(p.baba, "agents"));
247
+ if (existsSync(join(p.baba, VOSS, "promptware.json")) && !existsSync(join(p.baba, VOSS, "agents.json"))) await rename(join(p.baba, VOSS, "promptware.json"), join(p.baba, VOSS, "agents.json"));
245
248
  const old = join(p.baba, "state");
246
249
  if (!existsSync(old) || existsSync(join(p.baba, VOSS))) return;
247
250
  await rename(old, join(p.baba, VOSS));
package/src/baba/init.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  // voss init: a .baba in a directory, its dependencies installed. One entry,
2
- // one interface, one system to start from, and the promptware: what the baba tells
2
+ // one interface, one system to start from, and the agentic instructions: what the baba tells
3
3
  // agents, as code, versioned with the project.
4
4
  import { basename, join, resolve } from "node:path";
5
5
  import { mkdir } from "node:fs/promises";
@@ -42,7 +42,7 @@ export async function init(dir: string, o: InitOptions): Promise<{ name: string;
42
42
  await Bun.write(join(baba, "systems", "hello", "index.ts"), systemFile("hello"));
43
43
  await Bun.write(join(baba, "systems", "hello", "spec.ts"), systemSpecFile("hello"));
44
44
  await Bun.write(join(baba, "spec.test.ts"), specRunnerFile);
45
- await Bun.write(join(baba, "promptware", "index.ts"), promptwareFile(o.title ?? name));
45
+ await Bun.write(join(baba, "agents", "context.mdx"), contextFile(o.title ?? name));
46
46
  if (o.install !== false) await install(baba);
47
47
  return { name, dir };
48
48
  }
@@ -55,34 +55,29 @@ export async function install(baba: string): Promise<void> {
55
55
  if (code !== 0) throw new Error(`bun install failed in ${baba}: ${(err || out).trim().split("\n").slice(-5).join("; ")}`);
56
56
  }
57
57
 
58
- /** The promptware: what the baba tells agents, as code. The contract is not here: agents get it at `voss baba`. */
59
- export const promptwareFile = (title: string) => `import { context, md } from "babavoss/prompt";
58
+ /** The agentic instructions: what the baba tells agents, one .mdx per document under .baba/agents/. The contract is not here: agents get it at `voss baba`. */
59
+ export const contextFile = (title: string) => `export const prompt = { kind: "context" };
60
60
 
61
- // What this baba tells agents: its section of the context file, its skills
62
- // (one skill(...) per .tsx beside this file), its hooks. Code, rendered to
63
- // Markdown and compiled by voss into CLAUDE.md and the skills.
64
- export default [
65
- context(md\`
66
- ${title.replaceAll("\\", "\\\\").replaceAll("`", "\\`").replaceAll("$", "\\$")}: say here what this project is, in a sentence or two.
61
+ {/* What this baba tells agents: its section of the context file. A skill is another .mdx beside this one,
62
+ with export const prompt = { kind: "skill", name, description, uses }. A hook is hooks: [{ on, match, action }] here. */}
67
63
 
68
- How to work on it: the conventions, the checks to run before a commit, what not to touch.
64
+ ${title.replaceAll("{", "\\{").replaceAll("}", "\\}").replaceAll("<", "\\<")}: say here what this project is, in a sentence or two.
69
65
 
70
- ## Rules
66
+ How to work on it: the conventions, the checks to run before a commit, what not to touch.
71
67
 
72
- - Keep the tests green on every commit.
73
- \`),
74
- ];
68
+ ## Rules
69
+
70
+ - Keep the tests green on every commit.
75
71
  `;
76
72
 
77
- /** The entry: the baba, its systems listed, its promptware; `harness` for which harnesses get the files. */
73
+ /** The entry: the baba, its systems listed; `harness` for which harnesses get the files. The agentic instructions are the .mdx files under agents/, read by voss. */
78
74
  export const entry = `import { baba } from "babavoss";
79
75
  import { kit } from "babavoss/kit";
80
76
  import hello from "./systems/hello/index.ts";
81
- import promptware from "./promptware/index.ts";
82
77
 
83
78
  // kit keeps the baba's components, under ui/, as objects: \`voss baba ui\` lists them, \`ui-add\` brings more from shadcn.
84
79
  // The apps voss's shell offers; interface.tsx gives each its component.
85
- export default baba({ systems: [hello, kit], apps: [{ key: "hello", title: "Hello", icon: "hand" }], promptware });
80
+ export default baba({ systems: [hello, kit], apps: [{ key: "hello", title: "Hello", icon: "hand" }] });
86
81
  `;
87
82
 
88
83
  /** A system: a data model, one action, one query, written as one expression: the declaration, then its pieces made from it. */
package/src/baba/node.ts CHANGED
@@ -60,7 +60,7 @@ const ACTIVATE_MS = 10_000;
60
60
  const QUIET_MS = 300;
61
61
  /** How often a reload that waits for a job asks again. */
62
62
  const WAIT_MS = 500;
63
- // What changes under .baba without changing the code: voss's own files and the dependencies. Promptware is code: a change there reloads.
63
+ // What changes under .baba without changing the code: voss's own files and the dependencies. Instructions is code: a change there reloads.
64
64
  const IGNORED = [".voss", "node_modules"];
65
65
 
66
66
  /** Makes the transport a Node loads a project over. The worker is the first; a runtime process is next. */
@@ -188,7 +188,7 @@ export class Node {
188
188
  throw err;
189
189
  });
190
190
  fresh.manifest = loaded.manifest;
191
- // The contract outlives the run: discovery and promptware read it with the baba down.
191
+ // The contract outlives the run: discovery and agentic instructions read it with the baba down.
192
192
  await mkdir(join(this.project.baba, ".voss"), { recursive: true })
193
193
  .then(() => Bun.write(manifestPath(this.project), JSON.stringify(loaded.manifest, null, 2) + "\n"))
194
194
  .catch((err) => this.log(`${this.name}: the manifest was not written: ${err instanceof Error ? err.message : String(err)}`));
@@ -5,7 +5,8 @@ import { plugin as bunPlugin } from "bun";
5
5
  import { dirname, join } from "node:path";
6
6
  import type { ToRuntime, FromRuntime } from "../transport/messages.ts";
7
7
  import type { Snapshot } from "../ecs/state.ts";
8
- import { isBaba } from "../ecs/baba.ts";
8
+ import { isBaba, instructed } from "../ecs/baba.ts";
9
+ import type { Prompt } from "../instructions/index.ts";
9
10
  import { openProject } from "./project.ts";
10
11
  import { readEnv } from "../runtime/env.ts";
11
12
  import { Harness } from "../runtime/harness.ts";
@@ -20,9 +21,9 @@ const names: Record<string, string> = {
20
21
  "babavoss": join(root, "index.ts"),
21
22
  "babavoss/desktop": join(root, "src/desktop/index.ts"),
22
23
  "babavoss/kit": join(root, "src/kit/index.ts"),
23
- "babavoss/prompt": join(root, "src/prompt/index.ts"),
24
- "babavoss/prompt/jsx-runtime": join(root, "src/prompt/jsx-runtime.ts"),
25
- "babavoss/prompt/jsx-dev-runtime": join(root, "src/prompt/jsx-dev-runtime.ts"),
24
+ "babavoss/instructions": join(root, "src/instructions/index.ts"),
25
+ "babavoss/instructions/jsx-runtime": join(root, "src/instructions/jsx-runtime.ts"),
26
+ "babavoss/instructions/jsx-dev-runtime": join(root, "src/instructions/jsx-dev-runtime.ts"),
26
27
  "babavoss/test": join(root, "src/test/index.ts"),
27
28
  "babavoss/bench": join(root, "src/bench/index.ts"),
28
29
  };
@@ -45,7 +46,14 @@ self.onmessage = async (e: MessageEvent<ToWorker>) => {
45
46
  const project = await openProject(m.dir);
46
47
  const mod = (await import(`${project.entry}?t=${Date.now()}`)) as { default?: unknown };
47
48
  if (!isBaba(mod.default)) throw new Error(`${project.entry}: the default export is not a baba(); export default baba({ systems: [...] })`);
48
- h.load(mod.default, { name: project.name, dir: project.dir, baba: project.baba }, await readEnv(project.baba), m.snapshot, m.prepare);
49
+ // The agentic instructions: every .mdx under .baba/agents/, in name order, as the builder's bundle has them.
50
+ const docs: Prompt[] = [];
51
+ for (const f of [...new Bun.Glob("agents/*.mdx").scanSync({ cwd: project.baba })].sort()) {
52
+ const d = (await import(join(project.baba, f))) as { default?: Prompt }; // the plugin reads .mdx by its suffix: no query here
53
+ if (!d.default || typeof d.default !== "object" || !("kind" in d.default)) throw new Error(`${f}: not an instruction document; export const prompt = { kind: "context" | "skill", … }`);
54
+ docs.push(d.default);
55
+ }
56
+ h.load(instructed(mod.default, docs), { name: project.name, dir: project.dir, baba: project.baba }, await readEnv(project.baba), m.snapshot, m.prepare);
49
57
  } catch (err) {
50
58
  post({ type: "failed", error: err instanceof Error ? err.message : String(err) });
51
59
  }
package/src/build/mdx.ts CHANGED
@@ -6,28 +6,28 @@ import { forbiddenModules, advice } from "./guard.ts";
6
6
  function promptExport() {
7
7
  return (tree: any) => {
8
8
  const metadata = tree.body.some((n: any) => n.type === "ExportNamedDeclaration" && n.declaration?.type === "VariableDeclaration" && n.declaration.declarations.some((d: any) => d.id.name === "prompt"));
9
- if (!metadata) throw new Error('MDX promptware needs an exported prompt metadata object');
9
+ if (!metadata) throw new Error('an MDX instruction file needs an exported prompt metadata object');
10
10
  const exported = tree.body.find((n: any) => n.type === "ExportDefaultDeclaration");
11
11
  if (!exported || exported.declaration.type !== "FunctionDeclaration") throw new Error("MDX must export a document component");
12
12
  const component = exported.declaration;
13
13
  const id = (name: string) => ({ type: "Identifier", name });
14
14
  const literal = (value: string) => ({ type: "Literal", value });
15
15
  tree.body[tree.body.indexOf(exported)] = component;
16
- tree.body.push({ type: "ImportDeclaration", source: literal("babavoss/prompt"), specifiers: [{ type: "ImportSpecifier", imported: id("mdxDocument"), local: id("$promptDocument") }] });
16
+ tree.body.push({ type: "ImportDeclaration", source: literal("babavoss/instructions"), specifiers: [{ type: "ImportSpecifier", imported: id("mdxDocument"), local: id("$promptDocument") }] });
17
17
  tree.body.push({ type: "ExportDefaultDeclaration", declaration: { type: "CallExpression", callee: id("$promptDocument"), arguments: [id("prompt"), id(component.id.name)], optional: false } });
18
18
  };
19
19
  }
20
20
 
21
21
  export async function compilePromptMdx(value: string, path: string): Promise<string> {
22
22
  const result = String(await compile({ value, path }, {
23
- jsxImportSource: "babavoss/prompt", format: "mdx", development: false,
23
+ jsxImportSource: "babavoss/instructions", format: "mdx", development: false,
24
24
  remarkPlugins: [gfm], recmaPlugins: [promptExport],
25
25
  }));
26
26
  // Bun's bun-target builtin imports can bypass onResolve: apply the same guard after MDX compilation.
27
27
  for (const item of new Bun.Transpiler({ loader: "js" }).scanImports(result)) {
28
28
  if (forbiddenModules[item.path]) throw new Error(`${path} imports ${item.path}; ${advice(forbiddenModules[item.path]!)}`);
29
29
  }
30
- if (/\b(?:with|assert)\s*\{\s*type\s*:\s*["']macro["']\s*\}/.test(result)) throw new Error(`${path}: macros are not allowed in promptware`);
30
+ if (/\b(?:with|assert)\s*\{\s*type\s*:\s*["']macro["']\s*\}/.test(result)) throw new Error(`${path}: macros are not allowed in agentic instructions`);
31
31
  return result;
32
32
  }
33
33
 
@@ -12,9 +12,14 @@ const harness = join(framework, "src/runtime/worker.ts");
12
12
  const ENTRY = "/babavoss/entry.ts";
13
13
 
14
14
  export async function bundleProject(project: Project): Promise<string> {
15
+ // The agentic instructions: every .mdx under .baba/agents/, in name order, each a document the baba is given.
16
+ const docs = [...new Bun.Glob("agents/*.mdx").scanSync({ cwd: project.baba })].sort().map((f) => join(project.baba, f));
15
17
  const text = [
16
- `import v from ${JSON.stringify(project.entry)};`,
18
+ `import entry from ${JSON.stringify(project.entry)};`,
19
+ `import { instructed } from "babavoss";`,
17
20
  `import { serve } from ${JSON.stringify(harness)};`,
21
+ ...docs.map((f, i) => `import doc${i} from ${JSON.stringify(f)};`),
22
+ `const v = instructed(entry, [${docs.map((_, i) => `doc${i}`).join(", ")}]);`,
18
23
  `export default v;`,
19
24
  `serve(v);`,
20
25
  ].join("\n") + "\n";
@@ -27,9 +27,9 @@ export const names: Record<string, string> = {
27
27
  "babavoss/web": join(framework, "src/web/index.tsx"),
28
28
  "babavoss/test": join(framework, "src/test/index.ts"),
29
29
  "babavoss/bench": join(framework, "src/bench/index.ts"),
30
- "babavoss/prompt": join(framework, "src/prompt/index.ts"),
31
- "babavoss/prompt/jsx-runtime": join(framework, "src/prompt/jsx-runtime.ts"),
32
- "babavoss/prompt/jsx-dev-runtime": join(framework, "src/prompt/jsx-dev-runtime.ts"),
30
+ "babavoss/instructions": join(framework, "src/instructions/index.ts"),
31
+ "babavoss/instructions/jsx-runtime": join(framework, "src/instructions/jsx-runtime.ts"),
32
+ "babavoss/instructions/jsx-dev-runtime": join(framework, "src/instructions/jsx-dev-runtime.ts"),
33
33
  };
34
34
 
35
35
  /**
@@ -293,7 +293,7 @@ export const vossApps = [
293
293
  { key: "maker", title: "Maker", icon: "hammer", group: "Voss" },
294
294
  { key: "state", title: "State", icon: "database", group: "Voss" },
295
295
  { key: "contract", title: "Contract", icon: "square-terminal", group: "Voss" },
296
- { key: "promptware", title: "Promptware", icon: "book-open-text", group: "Voss" },
296
+ { key: "instructions", title: "Instructions", icon: "book-open-text", group: "Voss" },
297
297
  { key: "settings", title: "Settings", icon: "settings", group: "Voss" },
298
298
  ] as const satisfies readonly AppSpec[];
299
299
  export type VossApp = typeof vossApps[number]["key"];
package/src/door/core.ts CHANGED
@@ -73,7 +73,7 @@ export interface Index {
73
73
  error?: string;
74
74
  systems: { name: string }[];
75
75
  /** What the baba tells agents: whether it has a context, and its skills by name. */
76
- promptware: { context: boolean; skills: string[] };
76
+ instructions: { context: boolean; skills: string[] };
77
77
  calls: IndexCall[];
78
78
  components: Record<string, { system: string; key?: string; accept?: true }>;
79
79
  resources: string[];
@@ -115,7 +115,7 @@ export function index(m: Manifest, extra: IndexExtra = {}): Index {
115
115
  ...(extra.gen !== undefined ? { gen: extra.gen } : {}),
116
116
  ...(extra.error ? { error: extra.error } : {}),
117
117
  systems: m.systems.map((c) => ({ name: c.name })),
118
- promptware: { context: !!m.promptware.context, skills: Object.keys(m.promptware.skills) },
118
+ instructions: { context: !!m.instructions.context, skills: Object.keys(m.instructions.skills) },
119
119
  calls: entries(m).map(({ name, kind, c }) => ({ name, kind, system: c.owner, summary: c.summary, example: exampleCall(name, c, extra.prog) })),
120
120
  components: Object.fromEntries(Object.entries(m.components).map(([n, c]) => {
121
121
  const key = keyField(c.schema);