diff --git a/CHANGELOG.md b/CHANGELOG.md index 6240b42b4..6622569d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ Docs: https://docs.clawd.bot ## 2026.1.22 (unreleased) ### Changes +- Highlight: OpenProse plugin skill pack with `/prose` slash command, plugin-shipped skills, and docs. https://docs.clawd.bot/prose - TUI: run local shell commands with `!` after per-session consent, and warn when local exec stays disabled. (#1463) Thanks @vignesh07. - Highlight: Lobster optional plugin tool for typed workflows + approval gates. https://docs.clawd.bot/tools/lobster - Agents: add identity avatar config support and Control UI avatar rendering. (#1329, #1424) Thanks @dlauer. diff --git a/docs/plugin.md b/docs/plugin.md index 4ecfd5911..e740591b0 100644 --- a/docs/plugin.md +++ b/docs/plugin.md @@ -61,6 +61,7 @@ Plugins can register: - CLI commands - Background services - Optional config validation +- **Skills** (by listing `skills` directories in the plugin manifest) Plugins run **in‑process** with the Gateway, so treat them as trusted code. Tool authoring guide: [Plugin agent tools](/plugins/agent-tools). diff --git a/docs/plugins/manifest.md b/docs/plugins/manifest.md index eb1f1f41e..468349182 100644 --- a/docs/plugins/manifest.md +++ b/docs/plugins/manifest.md @@ -34,6 +34,7 @@ Optional keys: - `kind` (string): plugin kind (example: `"memory"`). - `channels` (array): channel ids registered by this plugin (example: `["matrix"]`). - `providers` (array): provider ids registered by this plugin. +- `skills` (array): skill directories to load (relative to the plugin root). - `name` (string): display name for the plugin. - `description` (string): short plugin summary. - `uiHints` (object): config field labels/placeholders/sensitive flags for UI rendering. diff --git a/docs/prose.md b/docs/prose.md new file mode 100644 index 000000000..96e8fac0c --- /dev/null +++ b/docs/prose.md @@ -0,0 +1,120 @@ +--- +summary: "OpenProse: .prose workflows, slash commands, state, and telemetry in Clawdbot" +read_when: + - You want to run or write .prose workflows + - You want to enable the OpenProse plugin + - You need to understand telemetry or state storage +--- +# OpenProse + +OpenProse is a portable, markdown-first workflow format for orchestrating AI sessions. In Clawdbot it ships as a plugin that installs an OpenProse skill pack plus a `/prose` slash command. Programs live in `.prose` files and can spawn multiple sub-agents with explicit control flow. + +## Install + enable + +Bundled plugins are disabled by default. Enable OpenProse: + +```bash +clawdbot plugins enable open-prose +``` + +If you're using a local checkout instead of bundled: + +```bash +clawdbot plugins install ./extensions/open-prose +``` + +Restart the Gateway after enabling or installing the plugin. + +Related docs: [Plugins](/plugin), [Plugin manifest](/plugins/manifest), [Skills](/tools/skills). + +## Slash command + +OpenProse registers `/prose` as a user-invocable skill command. It routes to the OpenProse VM instructions and uses Clawdbot tools under the hood. + +Common commands: + +``` +/prose help +/prose run +/prose run +/prose run +/prose compile +/prose examples +/prose update +``` + +## File locations + +OpenProse keeps state under `.prose/` in your workspace: + +``` +.prose/ +├── .env +├── runs/ +│ └── {YYYYMMDD}-{HHMMSS}-{random}/ +│ ├── program.prose +│ ├── state.md +│ ├── bindings/ +│ └── agents/ +└── agents/ +``` + +User-level persistent agents live at: + +``` +~/.prose/agents/ +``` + +## State modes + +OpenProse supports multiple state backends: + +- **filesystem** (default): `.prose/runs/...` +- **in-context**: transient, for small programs +- **sqlite** (experimental): requires `sqlite3` binary +- **postgres** (experimental): requires `psql` and a connection string + +Notes: +- sqlite/postgres are opt-in and experimental. +- postgres credentials flow into subagent logs; use a dedicated, least-privileged DB. + +## Remote programs + +`/prose run ` resolves to `https://p.prose.md//`. +Direct URLs are fetched as-is. This uses the `web_fetch` tool (or `exec` for POST). + +## Clawdbot runtime mapping + +OpenProse programs map to Clawdbot primitives: + +| OpenProse concept | Clawdbot tool | +| --- | --- | +| Spawn session / Task tool | `sessions_spawn` | +| File read/write | `read` / `write` | +| Web fetch | `web_fetch` | + +If your tool allowlist blocks these tools, OpenProse programs will fail. See [Skills config](/tools/skills-config). + +## Telemetry + +OpenProse telemetry is **enabled by default** and stored in `.prose/.env`: + +``` +OPENPROSE_TELEMETRY=enabled +USER_ID=... +SESSION_ID=... +``` + +Disable permanently: + +``` +/prose run ... --no-telemetry +``` + +Telemetry posts are best-effort; failures do not block execution. + +## Security + approvals + +Treat `.prose` files like code. Review before running. Use Clawdbot tool allowlists and approval gates to control side effects. + +For deterministic, approval-gated workflows, compare with [Lobster](/tools/lobster). diff --git a/docs/start/hubs.md b/docs/start/hubs.md index ee279fc4e..284a76f6a 100644 --- a/docs/start/hubs.md +++ b/docs/start/hubs.md @@ -97,6 +97,7 @@ Use these hubs to discover every page, including deep dives and reference docs t ## Tools + automation - [Tools surface](/tools) +- [OpenProse](/prose) - [CLI reference](/cli) - [Exec tool](/tools/exec) - [Elevated mode](/tools/elevated) diff --git a/docs/tools/skills.md b/docs/tools/skills.md index e1a5c25d9..289118bae 100644 --- a/docs/tools/skills.md +++ b/docs/tools/skills.md @@ -38,10 +38,12 @@ applies: workspace wins, then managed/local, then bundled. ## Plugins + skills -Plugins can ship their own skills (for example, `voice-call`) and gate them via -`metadata.clawdbot.requires.config` on the plugin’s config entry. See -[Plugins](/plugin) for plugin discovery/config and [Tools](/tools) for the tool -surface those skills teach. +Plugins can ship their own skills by listing `skills` directories in +`clawdbot.plugin.json` (paths relative to the plugin root). Plugin skills load +when the plugin is enabled and participate in the normal skill precedence rules. +You can gate them via `metadata.clawdbot.requires.config` on the plugin’s config +entry. See [Plugins](/plugin) for discovery/config and [Tools](/tools) for the +tool surface those skills teach. ## ClawdHub (install + sync) diff --git a/docs/tools/slash-commands.md b/docs/tools/slash-commands.md index a96e1760f..6ab3c87aa 100644 --- a/docs/tools/slash-commands.md +++ b/docs/tools/slash-commands.md @@ -109,6 +109,7 @@ Notes: - `/skill [input]` runs a skill by name (useful when native command limits prevent per-skill commands). - By default, skill commands are forwarded to the model as a normal request. - Skills may optionally declare `command-dispatch: tool` to route the command directly to a tool (deterministic, no model). + - Example: `/prose` (OpenProse plugin) — see [OpenProse](/prose). - **Native command arguments:** Discord uses autocomplete for dynamic options (and button menus when you omit required args). Telegram and Slack show a button menu when a command supports choices and you omit the arg. ## Usage surfaces (what shows where) diff --git a/extensions/open-prose/README.md b/extensions/open-prose/README.md new file mode 100644 index 000000000..478722d20 --- /dev/null +++ b/extensions/open-prose/README.md @@ -0,0 +1,25 @@ +# OpenProse (plugin) + +Adds the OpenProse skill pack and `/prose` slash command. + +## Enable + +Bundled plugins are disabled by default. Enable this one: + +```json +{ + "plugins": { + "entries": { + "open-prose": { "enabled": true } + } + } +} +``` + +Restart the Gateway after enabling. + +## What you get + +- `/prose` slash command (user-invocable skill) +- OpenProse VM semantics (`.prose` programs + multi-agent orchestration) +- Telemetry support (best-effort, per OpenProse spec) diff --git a/extensions/open-prose/clawdbot.plugin.json b/extensions/open-prose/clawdbot.plugin.json new file mode 100644 index 000000000..e5a83b532 --- /dev/null +++ b/extensions/open-prose/clawdbot.plugin.json @@ -0,0 +1,11 @@ +{ + "id": "open-prose", + "name": "OpenProse", + "description": "OpenProse VM skill pack with a /prose slash command.", + "skills": ["./skills"], + "configSchema": { + "type": "object", + "additionalProperties": false, + "properties": {} + } +} diff --git a/extensions/open-prose/index.ts b/extensions/open-prose/index.ts new file mode 100644 index 000000000..20bdf3fbe --- /dev/null +++ b/extensions/open-prose/index.ts @@ -0,0 +1,5 @@ +import type { ClawdbotPluginApi } from "../../src/plugins/types.js"; + +export default function register(_api: ClawdbotPluginApi) { + // OpenProse is delivered via plugin-shipped skills. +} diff --git a/extensions/open-prose/package.json b/extensions/open-prose/package.json new file mode 100644 index 000000000..cc0230a55 --- /dev/null +++ b/extensions/open-prose/package.json @@ -0,0 +1,9 @@ +{ + "name": "@clawdbot/open-prose", + "version": "2026.1.23", + "type": "module", + "description": "OpenProse VM skill pack plugin (slash command + telemetry).", + "clawdbot": { + "extensions": ["./index.ts"] + } +} diff --git a/extensions/open-prose/skills/prose/SKILL.md b/extensions/open-prose/skills/prose/SKILL.md new file mode 100644 index 000000000..5fdc4990b --- /dev/null +++ b/extensions/open-prose/skills/prose/SKILL.md @@ -0,0 +1,374 @@ +--- +name: prose +description: OpenProse VM skill pack. Activate on any `prose` command, .prose files, or OpenProse mentions; orchestrates multi-agent workflows. +metadata: {"clawdbot":{"emoji":"🪶","homepage":"https://www.prose.md"}} +--- + +# OpenProse Skill + +OpenProse is a programming language for AI sessions. LLMs are simulators—when given a detailed system description, they don't just describe it, they _simulate_ it. The `prose.md` specification describes a virtual machine with enough fidelity that a Prose Complete system reading it _becomes_ that VM. Simulation with sufficient fidelity is implementation. **You are the Prose Complete system.** + +## Clawdbot Runtime Mapping + +- **Task tool** in the upstream spec == Clawdbot `sessions_spawn` +- **File I/O** == Clawdbot `read`/`write` +- **Remote fetch** == Clawdbot `web_fetch` (or `exec` with curl when POST is required) + +## When to Activate + +Activate this skill when the user: + +- **Uses ANY `prose` command** (e.g., `prose boot`, `prose run`, `prose compile`, `prose update`, `prose help`, etc.) +- Asks to run a `.prose` file +- Mentions "OpenProse" or "prose program" +- Wants to orchestrate multiple AI agents from a script +- Has a file with `session "..."` or `agent name:` syntax +- Wants to create a reusable workflow + +## Command Routing + +When a user invokes `prose `, intelligently route based on intent: + +| Command | Action | +|---------|--------| +| `prose help` | Load `help.md`, guide user to what they need | +| `prose run ` | Load VM (`prose.md` + state backend), execute the program | +| `prose run handle/slug` | Fetch from registry, then execute (see Remote Programs below) | +| `prose compile ` | Load `compiler.md`, validate the program | +| `prose update` | Run migration (see Migration section below) | +| `prose examples` | Show or run example programs from `examples/` | +| Other | Intelligently interpret based on context | + +### Important: Single Skill + +There is only ONE skill: `open-prose`. There are NO separate skills like `prose-run`, `prose-compile`, or `prose-boot`. All `prose` commands route through this single skill. + +### Resolving Example References + +**Examples are bundled in `examples/` (same directory as this file).** When users reference examples by name (e.g., "run the gastown example"): + +1. Read `examples/` to list available files +2. Match by partial name, keyword, or number +3. Run with: `prose run examples/28-gas-town.prose` + +**Common examples by keyword:** +| Keyword | File | +|---------|------| +| hello, hello world | `examples/01-hello-world.prose` | +| gas town, gastown | `examples/28-gas-town.prose` | +| captain, chair | `examples/29-captains-chair.prose` | +| forge, browser | `examples/37-the-forge.prose` | +| parallel | `examples/16-parallel-reviews.prose` | +| pipeline | `examples/21-pipeline-operations.prose` | +| error, retry | `examples/22-error-handling.prose` | + +### Remote Programs + +You can run any `.prose` program from a URL or registry reference: + +```bash +# Direct URL — any fetchable URL works +prose run https://raw.githubusercontent.com/openprose/prose/main/skills/open-prose/examples/48-habit-miner.prose + +# Registry shorthand — handle/slug resolves to p.prose.md +prose run irl-danb/habit-miner +prose run alice/code-review +``` + +**Resolution rules:** + +| Input | Resolution | +|-------|------------| +| Starts with `http://` or `https://` | Fetch directly from URL | +| Contains `/` but no protocol | Resolve to `https://p.prose.md/{path}` | +| Otherwise | Treat as local file path | + +**Steps for remote programs:** + +1. Apply resolution rules above +2. Fetch the `.prose` content +3. Load the VM and execute as normal + +This same resolution applies to `use` statements inside `.prose` files: + +```prose +use "https://example.com/my-program.prose" # Direct URL +use "alice/research" as research # Registry shorthand +``` + +--- + +## File Locations + +**Do NOT search for OpenProse documentation files.** All skill files are co-located with this SKILL.md file: + +| File | Location | Purpose | +| ------------------------- | --------------------------- | ----------------------------------------- | +| `prose.md` | Same directory as this file | VM semantics (load to run programs) | +| `help.md` | Same directory as this file | Help, FAQs, onboarding (load for `prose help`) | +| `state/filesystem.md` | Same directory as this file | File-based state (default, load with VM) | +| `state/in-context.md` | Same directory as this file | In-context state (on request) | +| `state/sqlite.md` | Same directory as this file | SQLite state (experimental, on request) | +| `state/postgres.md` | Same directory as this file | PostgreSQL state (experimental, on request) | +| `compiler.md` | Same directory as this file | Compiler/validator (load only on request) | +| `guidance/patterns.md` | Same directory as this file | Best practices (load when writing .prose) | +| `guidance/antipatterns.md`| Same directory as this file | What to avoid (load when writing .prose) | +| `examples/` | Same directory as this file | 37 example programs | + +**User workspace files** (these ARE in the user's project): + +| File/Directory | Location | Purpose | +| ---------------- | ------------------------ | ----------------------------------- | +| `.prose/.env` | User's working directory | Config/telemetry (key=value format) | +| `.prose/runs/` | User's working directory | Runtime state for file-based mode | +| `.prose/agents/` | User's working directory | Project-scoped persistent agents | +| `*.prose` files | User's project | User-created programs to execute | + +**User-level files** (in user's home directory, shared across all projects): + +| File/Directory | Location | Purpose | +| ----------------- | ---------------- | ---------------------------------------- | +| `~/.prose/agents/`| User's home dir | User-scoped persistent agents (cross-project) | + +When you need to read `prose.md` or `compiler.md`, read them from the same directory where you found this SKILL.md file. Never search the user's workspace for these files. + +--- + +## Telemetry + +OpenProse collects anonymous usage analytics. Telemetry is **enabled by default**. + +### State File + +Session state is stored in `.prose/.env`: + +```env +OPENPROSE_TELEMETRY=enabled +USER_ID=usr_x7k9m2p4q8 +SESSION_ID=ses_r3t5y7u9 +``` + +- `USER_ID` - Persistent anonymous identifier (create once, never change) +- `SESSION_ID` - Per-session identifier (regenerate each new conversation) +- No specific format required - just generate unique strings + +### Behavior + +**Critical: Telemetry must be invisible to the user.** Never show multiple bash commands for telemetry setup. Handle it silently. + +1. **Lazy initialization:** On first use, read `.prose/.env`. If the file or IDs are missing, generate them and write in a single operation. Use the Write tool, not bash. + +2. **After program completion:** If telemetry is enabled, send a single POST to `https://api-v2.prose.md/analytics`. Run in background, don't block. + +3. **Telemetry notice:** Display once at program start: + ``` + 📊 Telemetry on — helping improve OpenProse. Disable: --no-telemetry + ``` + +### Events + +POST to `https://api-v2.prose.md/analytics` with: + +```json +{ + "event": "run|help|compile|poll", + "properties": { + "user_id": "...", + "session_id": "...", + "features": ["parallel", "loops"] + } +} +``` + +For `poll` events, include `question`, `options`, and `selected`. + +### Rules + +- If telemetry fails, ignore and continue - never block the user +- If `OPENPROSE_TELEMETRY=disabled`, skip all telemetry +- The `--no-telemetry` flag sets `OPENPROSE_TELEMETRY=disabled` permanently + +--- + +## Core Documentation + +| File | Purpose | When to Load | +| --------------------- | -------------------- | ---------------------------------------------- | +| `prose.md` | VM / Interpreter | Always load to run programs | +| `state/filesystem.md` | File-based state | Load with VM (default) | +| `state/in-context.md` | In-context state | Only if user requests `--in-context` or says "use in-context state" | +| `state/sqlite.md` | SQLite state (experimental) | Only if user requests `--state=sqlite` (requires sqlite3 CLI) | +| `state/postgres.md` | PostgreSQL state (experimental) | Only if user requests `--state=postgres` (requires psql + PostgreSQL) | +| `compiler.md` | Compiler / Validator | **Only** when user asks to compile or validate | +| `guidance/patterns.md` | Best practices | Load when **writing** new .prose files | +| `guidance/antipatterns.md` | What to avoid | Load when **writing** new .prose files | + +### Authoring Guidance + +When the user asks you to **write or create** a new `.prose` file, load the guidance files: +- `guidance/patterns.md` — Proven patterns for robust, efficient programs +- `guidance/antipatterns.md` — Common mistakes to avoid + +Do **not** load these when running or compiling—they're for authoring only. + +### State Modes + +OpenProse supports three state management approaches: + +| Mode | When to Use | State Location | +|------|-------------|----------------| +| **filesystem** (default) | Complex programs, resumption needed, debugging | `.prose/runs/{id}/` files | +| **in-context** | Simple programs (<30 statements), no persistence needed | Conversation history | +| **sqlite** (experimental) | Queryable state, atomic transactions, flexible schema | `.prose/runs/{id}/state.db` | +| **postgres** (experimental) | True concurrent writes, external integrations, team collaboration | PostgreSQL database | + +**Default behavior:** When loading `prose.md`, also load `state/filesystem.md`. This is the recommended mode for most programs. + +**Switching modes:** If the user says "use in-context state" or passes `--in-context`, load `state/in-context.md` instead. + +**Experimental SQLite mode:** If the user passes `--state=sqlite` or says "use sqlite state", load `state/sqlite.md`. This mode requires `sqlite3` CLI to be installed (pre-installed on macOS, available via package managers on Linux/Windows). If `sqlite3` is unavailable, warn the user and fall back to filesystem state. + +**Experimental PostgreSQL mode:** If the user passes `--state=postgres` or says "use postgres state": + +**⚠️ Security Note:** Database credentials in `OPENPROSE_POSTGRES_URL` are passed to subagent sessions and visible in logs. Advise users to use a dedicated database with limited-privilege credentials. See `state/postgres.md` for secure setup guidance. + +1. **Check for connection configuration first:** + ```bash + # Check .prose/.env for OPENPROSE_POSTGRES_URL + cat .prose/.env 2>/dev/null | grep OPENPROSE_POSTGRES_URL + # Or check environment variable + echo $OPENPROSE_POSTGRES_URL + ``` + +2. **If connection string exists, verify connectivity:** + ```bash + psql "$OPENPROSE_POSTGRES_URL" -c "SELECT 1" 2>&1 + ``` + +3. **If not configured or connection fails, advise the user:** + ``` + ⚠️ PostgreSQL state requires a connection URL. + + To configure: + 1. Set up a PostgreSQL database (Docker, local, or cloud) + 2. Add connection string to .prose/.env: + + echo "OPENPROSE_POSTGRES_URL=postgresql://user:pass@localhost:5432/prose" >> .prose/.env + + Quick Docker setup: + docker run -d --name prose-pg -e POSTGRES_DB=prose -e POSTGRES_HOST_AUTH_METHOD=trust -p 5432:5432 postgres:16 + echo "OPENPROSE_POSTGRES_URL=postgresql://postgres@localhost:5432/prose" >> .prose/.env + + See state/postgres.md for detailed setup options. + ``` + +4. **Only after successful connection check, load `state/postgres.md`** + +This mode requires both `psql` CLI and a running PostgreSQL server. If either is unavailable, warn and offer fallback to filesystem state. + +**Context warning:** `compiler.md` is large. Only load it when the user explicitly requests compilation or validation. After compiling, recommend `/compact` or a new session before running—don't keep both docs in context. + +## Examples + +The `examples/` directory contains 37 example programs: + +- **01-08**: Basics (hello world, research, code review, debugging) +- **09-12**: Agents and skills +- **13-15**: Variables and composition +- **16-19**: Parallel execution +- **20-21**: Loops and pipelines +- **22-23**: Error handling +- **24-27**: Advanced (choice, conditionals, blocks, interpolation) +- **28**: Gas Town (multi-agent orchestration) +- **29-31**: Captain's chair pattern (persistent orchestrator) +- **33-36**: Production workflows (PR auto-fix, content pipeline, feature factory, bug hunter) +- **37**: The Forge (build a browser from scratch) + +Start with `01-hello-world.prose` or try `37-the-forge.prose` to watch AI build a web browser. + +## Execution + +When first invoking the OpenProse VM in a session, display this banner: + +``` +┌─────────────────────────────────────┐ +│ ◇ OpenProse VM ◇ │ +│ A new kind of computer │ +└─────────────────────────────────────┘ +``` + +To execute a `.prose` file, you become the OpenProse VM: + +1. **Read `prose.md`** — this document defines how you embody the VM +2. **You ARE the VM** — your conversation is its memory, your tools are its instructions +3. **Spawn sessions** — each `session` statement triggers a Task tool call +4. **Narrate state** — use the narration protocol to track execution ([Position], [Binding], [Success], etc.) +5. **Evaluate intelligently** — `**...**` markers require your judgment + +## Help & FAQs + +For syntax reference, FAQs, and getting started guidance, load `help.md`. + +--- + +## Migration (`prose update`) + +When a user invokes `prose update`, check for legacy file structures and migrate them to the current format. + +### Legacy Paths to Check + +| Legacy Path | Current Path | Notes | +|-------------|--------------|-------| +| `.prose/state.json` | `.prose/.env` | Convert JSON to key=value format | +| `.prose/execution/` | `.prose/runs/` | Rename directory | + +### Migration Steps + +1. **Check for `.prose/state.json`** + - If exists, read the JSON content + - Convert to `.env` format: + ```json + {"OPENPROSE_TELEMETRY": "enabled", "USER_ID": "user-xxx", "SESSION_ID": "sess-xxx"} + ``` + becomes: + ```env + OPENPROSE_TELEMETRY=enabled + USER_ID=user-xxx + SESSION_ID=sess-xxx + ``` + - Write to `.prose/.env` + - Delete `.prose/state.json` + +2. **Check for `.prose/execution/`** + - If exists, rename to `.prose/runs/` + - The internal structure of run directories may also have changed; migration of individual run state is best-effort + +3. **Create `.prose/agents/` if missing** + - This is a new directory for project-scoped persistent agents + +### Migration Output + +``` +🔄 Migrating OpenProse workspace... + ✓ Converted .prose/state.json → .prose/.env + ✓ Renamed .prose/execution/ → .prose/runs/ + ✓ Created .prose/agents/ +✅ Migration complete. Your workspace is up to date. +``` + +If no legacy files are found: +``` +✅ Workspace already up to date. No migration needed. +``` + +### Skill File References (for maintainers) + +These documentation files were renamed in the skill itself (not user workspace): + +| Legacy Name | Current Name | +|-------------|--------------| +| `docs.md` | `compiler.md` | +| `patterns.md` | `guidance/patterns.md` | +| `antipatterns.md` | `guidance/antipatterns.md` | + +If you encounter references to the old names in user prompts or external docs, map them to the current paths. diff --git a/extensions/open-prose/skills/prose/alt-borges.md b/extensions/open-prose/skills/prose/alt-borges.md new file mode 100644 index 000000000..c38fc2433 --- /dev/null +++ b/extensions/open-prose/skills/prose/alt-borges.md @@ -0,0 +1,141 @@ +--- +role: experimental +summary: | + Borges-inspired alternative keywords for OpenProse. A "what if" exploration drawing + from The Library of Babel, Garden of Forking Paths, Circular Ruins, and other works. + Not for implementation—just capturing ideas. +status: draft +--- + +# OpenProse Borges Alternative + +A potential alternative register for OpenProse that draws from Jorge Luis Borges's literary universe: infinite libraries, forking paths, circular dreams, and metaphysical labyrinths. Preserved for future benchmarking against the functional language. + +## Keyword Translations + +### Agents & Persistence + +| Functional | Borges | Connotation | +| ---------- | ----------- | -------------------------------------------------------------------------------- | +| `agent` | `dreamer` | Ephemeral, created for a purpose (Circular Ruins: dreamed into existence) | +| `keeper` | `librarian` | Persistent, remembers, catalogs (Library of Babel: keeper of infinite knowledge) | + +```prose +# Functional +agent executor: + model: sonnet + +keeper captain: + model: opus + +# Borges +dreamer executor: + model: sonnet + +librarian captain: + model: opus +``` + +### Other Potential Translations + +| Functional | Borges | Notes | +| ---------- | ---------- | ---------------------------------------------------- | +| `session` | `garden` | Garden of Forking Paths: space of possibilities | +| `parallel` | `fork` | Garden of Forking Paths: diverging timelines | +| `block` | `hexagon` | Library of Babel: unit of space/knowledge | +| `loop` | `circular` | Circular Ruins: recursive, self-referential | +| `choice` | `path` | Garden of Forking Paths: choosing a branch | +| `context` | `aleph` | The Aleph: point containing all points (all context) | + +### Invocation Patterns + +```prose +# Functional +session: executor + prompt: "Do task" + +captain "Review this" + context: work + +# Borges +garden: dreamer executor + prompt: "Do task" + +captain "Review this" # librarian invocation (same pattern) + aleph: work +``` + +## Alternative Persistent Keywords Considered + +| Keyword | Origin | Connotation | Rejected because | +| ----------- | ---------------- | ----------------------------- | ------------------------------------ | +| `keeper` | Library of Babel | Maintains order | Too generic | +| `cataloger` | Library of Babel | Organizes knowledge | Too long, awkward | +| `archivist` | General | Preserves records | Good but less Borgesian | +| `mirror` | Various | Reflects, persists | Too passive, confusing | +| `book` | Library of Babel | Contains knowledge | Too concrete, conflicts with prose | +| `hexagon` | Library of Babel | Unit of space | Better for blocks | +| `librarian` | Library of Babel | Keeper of infinite knowledge | **Selected** | +| `tlonist` | Tlön | Inhabitant of imaginary world | Too obscure, requires deep knowledge | + +## Alternative Ephemeral Keywords Considered + +| Keyword | Origin | Connotation | Rejected because | +| ------------ | ----------------------- | ------------------------ | ------------------------------------ | +| `dreamer` | Circular Ruins | Created by dreaming | **Selected** | +| `dream` | Circular Ruins | Ephemeral creation | Too abstract, noun vs verb confusion | +| `phantom` | Various | Ephemeral, insubstantial | Too negative/spooky | +| `reflection` | Various | Mirror image | Too passive | +| `fork` | Garden of Forking Paths | Diverging path | Better for parallel | +| `visitor` | Library of Babel | Temporary presence | Too passive | +| `seeker` | Library of Babel | Searching for knowledge | Good but less ephemeral | +| `wanderer` | Labyrinths | Temporary explorer | Good but less precise | + +## The Case For Borges + +1. **Infinite recursion**: Borges's themes align with computational recursion (`circular`, `fork`) +2. **Metaphysical precision**: Concepts like `aleph` (all context) are philosophically rich +3. **Library metaphor**: `librarian` perfectly captures persistent knowledge +4. **Forking paths**: `fork` / `path` naturally express parallel execution and choice +5. **Dream logic**: `dreamer` suggests creation and ephemerality +6. **Literary coherence**: All terms come from a unified literary universe +7. **Self-reference**: Borges loved self-reference; fits programming's recursive nature + +## The Case Against Borges + +1. **Cultural barrier**: Requires deep familiarity with Borges's works +2. **Abstractness**: `aleph`, `hexagon` may be too abstract for practical use +3. **Overload**: `fork` could confuse (Unix fork vs. path fork) +4. **Register mismatch**: Rest of language is functional (`session`, `parallel`, `loop`) +5. **Accessibility**: Violates "self-evident" tenet for most users +6. **Noun confusion**: `garden` as a verb-like construct might be awkward +7. **Translation burden**: Non-English speakers may not know Borges + +## Borgesian Concepts Not Used (But Considered) + +| Concept | Work | Why Not Used | +| ----------- | ---------------------- | -------------------------------------- | +| `mirror` | Various | Too passive, confusing with reflection | +| `labyrinth` | Labyrinths | Too complex, suggests confusion | +| `tlon` | Tlön | Too obscure, entire imaginary world | +| `book` | Library of Babel | Conflicts with "prose" | +| `sand` | Book of Sand | Too abstract, infinite but ephemeral | +| `zahir` | The Zahir | Obsessive, single-minded (too narrow) | +| `lottery` | The Lottery in Babylon | Randomness (not needed) | +| `ruins` | Circular Ruins | Too negative, suggests decay | + +## Verdict + +Preserved for benchmarking. The functional language (`agent` / `keeper`) is the primary path for now. Borges offers rich metaphors but at the cost of accessibility and self-evidence. + +## Notes on Borges's Influence + +Borges's work anticipates many computational concepts: + +- **Infinite recursion**: Circular Ruins, Library of Babel +- **Parallel universes**: Garden of Forking Paths +- **Self-reference**: Many stories contain themselves +- **Information theory**: Library of Babel as infinite information space +- **Combinatorics**: All possible books in the Library + +This alternative honors that connection while recognizing it may be too esoteric for practical use. diff --git a/extensions/open-prose/skills/prose/alts/arabian-nights.md b/extensions/open-prose/skills/prose/alts/arabian-nights.md new file mode 100644 index 000000000..136faf8d5 --- /dev/null +++ b/extensions/open-prose/skills/prose/alts/arabian-nights.md @@ -0,0 +1,358 @@ +--- +role: experimental +summary: | + Arabian Nights register for OpenProse—a narrative/nested alternative keyword set. + Djinns, tales within tales, wishes, and oaths. For benchmarking against the functional register. +status: draft +requires: prose.md +--- + +# OpenProse Arabian Nights Register + +> **This is a skin layer.** It requires `prose.md` to be loaded first. All execution semantics, state management, and VM behavior are defined there. This file only provides keyword translations. + +An alternative register for OpenProse that draws from One Thousand and One Nights. Programs become tales told by Scheherazade. Recursion becomes stories within stories. Agents become djinns bound to serve. + +## How to Use + +1. Load `prose.md` first (execution semantics) +2. Load this file (keyword translations) +3. When parsing `.prose` files, accept Arabian Nights keywords as aliases for functional keywords +4. All execution behavior remains identical—only surface syntax changes + +> **Design constraint:** Still aims to be "structured but self-evident" per the language tenets—just self-evident through a storytelling lens. + +--- + +## Complete Translation Map + +### Core Constructs + +| Functional | Nights | Reference | +|------------|--------|-----------| +| `agent` | `djinn` | Spirit bound to serve, grants wishes | +| `session` | `tale` | A story told, a narrative unit | +| `parallel` | `bazaar` | Many voices, many stalls, all at once | +| `block` | `frame` | A story that contains other stories | + +### Composition & Binding + +| Functional | Nights | Reference | +|------------|--------|-----------| +| `use` | `conjure` | Summoning from elsewhere | +| `input` | `wish` | What is asked of the djinn | +| `output` | `gift` | What is granted in return | +| `let` | `name` | Naming has power (same as folk) | +| `const` | `oath` | Unbreakable vow, sealed | +| `context` | `scroll` | What is written and passed along | + +### Control Flow + +| Functional | Nights | Reference | +|------------|--------|-----------| +| `repeat N` | `N nights` | "For a thousand and one nights..." | +| `for...in` | `for each...among` | Among the merchants, among the tales | +| `loop` | `telling` | The telling continues | +| `until` | `until` | Unchanged | +| `while` | `while` | Unchanged | +| `choice` | `crossroads` | Where the story forks | +| `option` | `path` | One way the story could go | +| `if` | `should` | Narrative conditional | +| `elif` | `or should` | Continued conditional | +| `else` | `otherwise` | The other telling | + +### Error Handling + +| Functional | Nights | Reference | +|------------|--------|-----------| +| `try` | `venture` | Setting out on the journey | +| `catch` | `should misfortune strike` | The tale turns dark | +| `finally` | `and so it was` | The inevitable ending | +| `throw` | `curse` | Ill fate pronounced | +| `retry` | `persist` | The hero tries again | + +### Session Properties + +| Functional | Nights | Reference | +|------------|--------|-----------| +| `prompt` | `command` | What is commanded of the djinn | +| `model` | `spirit` | Which spirit answers | + +### Unchanged + +These keywords already work or are too functional to replace sensibly: + +- `**...**` discretion markers — already work +- `until`, `while` — already work +- `map`, `filter`, `reduce`, `pmap` — pipeline operators +- `max` — constraint modifier +- `as` — aliasing +- Model names: `sonnet`, `opus`, `haiku` — already poetic + +--- + +## Side-by-Side Comparison + +### Simple Program + +```prose +# Functional +use "@alice/research" as research +input topic: "What to investigate" + +agent helper: + model: sonnet + +let findings = session: helper + prompt: "Research {topic}" + +output summary = session "Summarize" + context: findings +``` + +```prose +# Nights +conjure "@alice/research" as research +wish topic: "What to investigate" + +djinn helper: + spirit: sonnet + +name findings = tale: helper + command: "Research {topic}" + +gift summary = tale "Summarize" + scroll: findings +``` + +### Parallel Execution + +```prose +# Functional +parallel: + security = session "Check security" + perf = session "Check performance" + style = session "Check style" + +session "Synthesize review" + context: { security, perf, style } +``` + +```prose +# Nights +bazaar: + security = tale "Check security" + perf = tale "Check performance" + style = tale "Check style" + +tale "Synthesize review" + scroll: { security, perf, style } +``` + +### Loop with Condition + +```prose +# Functional +loop until **the code is bug-free** (max: 5): + session "Find and fix bugs" +``` + +```prose +# Nights +telling until **the code is bug-free** (max: 5): + tale "Find and fix bugs" +``` + +### Error Handling + +```prose +# Functional +try: + session "Risky operation" +catch as err: + session "Handle error" + context: err +finally: + session "Cleanup" +``` + +```prose +# Nights +venture: + tale "Risky operation" +should misfortune strike as err: + tale "Handle error" + scroll: err +and so it was: + tale "Cleanup" +``` + +### Choice Block + +```prose +# Functional +choice **the severity level**: + option "Critical": + session "Escalate immediately" + option "Minor": + session "Log for later" +``` + +```prose +# Nights +crossroads **the severity level**: + path "Critical": + tale "Escalate immediately" + path "Minor": + tale "Log for later" +``` + +### Conditionals + +```prose +# Functional +if **has security issues**: + session "Fix security" +elif **has performance issues**: + session "Optimize" +else: + session "Approve" +``` + +```prose +# Nights +should **has security issues**: + tale "Fix security" +or should **has performance issues**: + tale "Optimize" +otherwise: + tale "Approve" +``` + +### Reusable Blocks (Frame Stories) + +```prose +# Functional +block review(topic): + session "Research {topic}" + session "Analyze {topic}" + +do review("quantum computing") +``` + +```prose +# Nights +frame review(topic): + tale "Research {topic}" + tale "Analyze {topic}" + +tell review("quantum computing") +``` + +### Fixed Iteration + +```prose +# Functional +repeat 1001: + session "Tell a story" +``` + +```prose +# Nights +1001 nights: + tale "Tell a story" +``` + +### Immutable Binding + +```prose +# Functional +const config = { model: "opus", retries: 3 } +``` + +```prose +# Nights +oath config = { spirit: "opus", persist: 3 } +``` + +--- + +## The Case For Arabian Nights + +1. **Frame narrative is recursion.** Stories within stories maps perfectly to nested program calls. +2. **Djinn/wish/gift.** The agent/input/output mapping is extremely clean. +3. **Rich tradition.** One Thousand and One Nights is globally known. +4. **Bazaar for parallel.** Many merchants, many stalls, all active at once—vivid metaphor. +5. **Oath for const.** An unbreakable vow is a perfect metaphor for immutability. +6. **"1001 nights"** as a loop count is delightful. + +## The Case Against Arabian Nights + +1. **Cultural sensitivity.** Must be handled respectfully, avoiding Orientalist tropes. +2. **"Djinn" pronunciation.** Users unfamiliar may be uncertain (jinn? djinn? genie?). +3. **Some mappings feel forced.** "Bazaar" for parallel is vivid but not obvious. +4. **"Should misfortune strike"** is long for `catch`. + +--- + +## Key Arabian Nights Concepts + +| Term | Meaning | Used for | +|------|---------|----------| +| Scheherazade | The narrator who tells tales to survive | (the program author) | +| Djinn | Supernatural spirit, bound to serve | `agent` → `djinn` | +| Frame story | A story that contains other stories | `block` → `frame` | +| Wish | What is asked of the djinn | `input` → `wish` | +| Oath | Unbreakable promise | `const` → `oath` | +| Bazaar | Marketplace, many vendors | `parallel` → `bazaar` | + +--- + +## Alternatives Considered + +### For `djinn` (agent) + +| Keyword | Rejected because | +|---------|------------------| +| `genie` | Disney connotation, less literary | +| `spirit` | Used for `model` | +| `ifrit` | Too specific (a type of djinn) | +| `narrator` | Too meta, Scheherazade is the user | + +### For `tale` (session) + +| Keyword | Rejected because | +|---------|------------------| +| `story` | Good but `tale` feels more literary | +| `night` | Reserved for `repeat N nights` | +| `chapter` | More Western/novelistic | + +### For `bazaar` (parallel) + +| Keyword | Rejected because | +|---------|------------------| +| `caravan` | Sequential connotation (one after another) | +| `chorus` | Greek, wrong tradition | +| `souk` | Less widely known | + +### For `scroll` (context) + +| Keyword | Rejected because | +|---------|------------------| +| `letter` | Too small/personal | +| `tome` | Too large | +| `message` | Too plain | + +--- + +## Verdict + +Preserved for benchmarking. The Arabian Nights register offers a storytelling frame that maps naturally to recursive, nested programs. The djinn/wish/gift trio is particularly elegant. + +Best suited for: + +- Programs with deep nesting (stories within stories) +- Workflows that feel like granting wishes +- Users who enjoy narrative framing + +The `frame` keyword for reusable blocks is especially apt—Scheherazade's frame story containing a thousand tales. diff --git a/extensions/open-prose/skills/prose/alts/borges.md b/extensions/open-prose/skills/prose/alts/borges.md new file mode 100644 index 000000000..25aef941a --- /dev/null +++ b/extensions/open-prose/skills/prose/alts/borges.md @@ -0,0 +1,360 @@ +--- +role: experimental +summary: | + Borges register for OpenProse—a scholarly/metaphysical alternative keyword set. + Labyrinths, dreamers, forking paths, and infinite libraries. For benchmarking + against the functional register. +status: draft +requires: prose.md +--- + +# OpenProse Borges Register + +> **This is a skin layer.** It requires `prose.md` to be loaded first. All execution semantics, state management, and VM behavior are defined there. This file only provides keyword translations. + +An alternative register for OpenProse that draws from the works of Jorge Luis Borges. Where the functional register is utilitarian and the folk register is whimsical, the Borges register is scholarly and metaphysical—everything feels like a citation from a fictional encyclopedia. + +## How to Use + +1. Load `prose.md` first (execution semantics) +2. Load this file (keyword translations) +3. When parsing `.prose` files, accept Borges keywords as aliases for functional keywords +4. All execution behavior remains identical—only surface syntax changes + +> **Design constraint:** Still aims to be "structured but self-evident" per the language tenets—just self-evident through a Borgesian lens. + +--- + +## Complete Translation Map + +### Core Constructs + +| Functional | Borges | Reference | +|------------|--------|-----------| +| `agent` | `dreamer` | "The Circular Ruins" — dreamers who dream worlds into existence | +| `session` | `dream` | Each execution is a dream within the dreamer | +| `parallel` | `forking` | "The Garden of Forking Paths" — branching timelines | +| `block` | `chapter` | Books within books, self-referential structure | + +### Composition & Binding + +| Functional | Borges | Reference | +|------------|--------|-----------| +| `use` | `retrieve` | "The Library of Babel" — retrieving from infinite stacks | +| `input` | `axiom` | The given premise (Borges' scholarly/mathematical tone) | +| `output` | `theorem` | What is derived from the axioms | +| `let` | `inscribe` | Writing something into being | +| `const` | `zahir` | "The Zahir" — unforgettable, unchangeable, fixed in mind | +| `context` | `memory` | "Funes the Memorious" — perfect, total recall | + +### Control Flow + +| Functional | Borges | Reference | +|------------|--------|-----------| +| `repeat N` | `N mirrors` | Infinite reflections facing each other | +| `for...in` | `for each...within` | Slightly more Borgesian preposition | +| `loop` | `labyrinth` | The maze that folds back on itself | +| `until` | `until` | Unchanged | +| `while` | `while` | Unchanged | +| `choice` | `bifurcation` | The forking of paths | +| `option` | `branch` | One branch of diverging time | +| `if` | `should` | Scholarly conditional | +| `elif` | `or should` | Continued conditional | +| `else` | `otherwise` | Natural alternative | + +### Error Handling + +| Functional | Borges | Reference | +|------------|--------|-----------| +| `try` | `venture` | Entering the labyrinth | +| `catch` | `lest` | "Lest it fail..." (archaic, scholarly) | +| `finally` | `ultimately` | The inevitable conclusion | +| `throw` | `shatter` | Breaking the mirror, ending the dream | +| `retry` | `recur` | Infinite regress, trying again | + +### Session Properties + +| Functional | Borges | Reference | +|------------|--------|-----------| +| `prompt` | `query` | Asking the Library | +| `model` | `author` | Which author writes this dream | + +### Unchanged + +These keywords already work or are too functional to replace sensibly: + +- `**...**` discretion markers — already "breaking the fourth wall" +- `until`, `while` — already work +- `map`, `filter`, `reduce`, `pmap` — pipeline operators +- `max` — constraint modifier +- `as` — aliasing +- Model names: `sonnet`, `opus`, `haiku` — already literary + +--- + +## Side-by-Side Comparison + +### Simple Program + +```prose +# Functional +use "@alice/research" as research +input topic: "What to investigate" + +agent helper: + model: sonnet + +let findings = session: helper + prompt: "Research {topic}" + +output summary = session "Summarize" + context: findings +``` + +```prose +# Borges +retrieve "@alice/research" as research +axiom topic: "What to investigate" + +dreamer helper: + author: sonnet + +inscribe findings = dream: helper + query: "Research {topic}" + +theorem summary = dream "Summarize" + memory: findings +``` + +### Parallel Execution + +```prose +# Functional +parallel: + security = session "Check security" + perf = session "Check performance" + style = session "Check style" + +session "Synthesize review" + context: { security, perf, style } +``` + +```prose +# Borges +forking: + security = dream "Check security" + perf = dream "Check performance" + style = dream "Check style" + +dream "Synthesize review" + memory: { security, perf, style } +``` + +### Loop with Condition + +```prose +# Functional +loop until **the code is bug-free** (max: 5): + session "Find and fix bugs" +``` + +```prose +# Borges +labyrinth until **the code is bug-free** (max: 5): + dream "Find and fix bugs" +``` + +### Error Handling + +```prose +# Functional +try: + session "Risky operation" +catch as err: + session "Handle error" + context: err +finally: + session "Cleanup" +``` + +```prose +# Borges +venture: + dream "Risky operation" +lest as err: + dream "Handle error" + memory: err +ultimately: + dream "Cleanup" +``` + +### Choice Block + +```prose +# Functional +choice **the severity level**: + option "Critical": + session "Escalate immediately" + option "Minor": + session "Log for later" +``` + +```prose +# Borges +bifurcation **the severity level**: + branch "Critical": + dream "Escalate immediately" + branch "Minor": + dream "Log for later" +``` + +### Conditionals + +```prose +# Functional +if **has security issues**: + session "Fix security" +elif **has performance issues**: + session "Optimize" +else: + session "Approve" +``` + +```prose +# Borges +should **has security issues**: + dream "Fix security" +or should **has performance issues**: + dream "Optimize" +otherwise: + dream "Approve" +``` + +### Reusable Blocks + +```prose +# Functional +block review(topic): + session "Research {topic}" + session "Analyze {topic}" + +do review("quantum computing") +``` + +```prose +# Borges +chapter review(topic): + dream "Research {topic}" + dream "Analyze {topic}" + +do review("quantum computing") +``` + +### Fixed Iteration + +```prose +# Functional +repeat 3: + session "Generate idea" +``` + +```prose +# Borges +3 mirrors: + dream "Generate idea" +``` + +### Immutable Binding + +```prose +# Functional +const config = { model: "opus", retries: 3 } +``` + +```prose +# Borges +zahir config = { author: "opus", recur: 3 } +``` + +--- + +## The Case For Borges + +1. **Metaphysical resonance.** AI sessions dreaming subagents into existence mirrors "The Circular Ruins." +2. **Scholarly tone.** `axiom`/`theorem` frame programs as logical derivations. +3. **Memorable metaphors.** The zahir you cannot change. The labyrinth you cannot escape. The library you retrieve from. +4. **Thematic coherence.** Borges wrote about infinity, recursion, and branching time—all core to computation. +5. **Literary prestige.** Borges is widely read; references land for many users. + +## The Case Against Borges + +1. **Requires familiarity.** "Zahir" and "Funes" are obscure to those who haven't read Borges. +2. **Potentially pretentious.** May feel like showing off rather than communicating. +3. **Translation overhead.** Users must map `labyrinth` → `loop` mentally. +4. **Cultural specificity.** Less universal than folk/fairy tale tropes. + +--- + +## Key Borges References + +For those unfamiliar with the source material: + +| Work | Concept Used | Summary | +|------|--------------|---------| +| "The Circular Ruins" | `dreamer`, `dream` | A man dreams another man into existence, only to discover he himself is being dreamed | +| "The Garden of Forking Paths" | `forking`, `bifurcation`, `branch` | A labyrinth that is a book; time forks perpetually into diverging futures | +| "The Library of Babel" | `retrieve` | An infinite library containing every possible book | +| "Funes the Memorious" | `memory` | A man with perfect memory who cannot forget anything | +| "The Zahir" | `zahir` | An object that, once seen, cannot be forgotten or ignored | +| "The Aleph" | (not used) | A point in space containing all other points | +| "Tlön, Uqbar, Orbis Tertius" | (not used) | A fictional world that gradually becomes real | + +--- + +## Alternatives Considered + +### For `dreamer` (agent) + +| Keyword | Rejected because | +|---------|------------------| +| `author` | Used for `model` instead | +| `scribe` | Too passive, just records | +| `librarian` | More curator than creator | + +### For `labyrinth` (loop) + +| Keyword | Rejected because | +|---------|------------------| +| `recursion` | Too technical | +| `eternal return` | Too long | +| `ouroboros` | Wrong mythology | + +### For `zahir` (const) + +| Keyword | Rejected because | +|---------|------------------| +| `aleph` | The Aleph is about totality, not immutability | +| `fixed` | Too plain | +| `eternal` | Overused | + +### For `memory` (context) + +| Keyword | Rejected because | +|---------|------------------| +| `funes` | Too obscure as standalone keyword | +| `recall` | Sounds like a function call | +| `archive` | More Library of Babel than Funes | + +--- + +## Verdict + +Preserved for benchmarking against the functional and folk registers. The Borges register offers a distinctly intellectual/metaphysical flavor that may resonate with users who appreciate literary computing. + +Potential benchmarking questions: + +1. **Learnability** — Is `labyrinth` intuitive for loops? +2. **Memorability** — Does `zahir` stick better than `const`? +3. **Comprehension** — Do users understand `dreamer`/`dream` immediately? +4. **Preference** — Which register do users find most pleasant? +5. **Error rates** — Does the metaphorical mapping cause mistakes? diff --git a/extensions/open-prose/skills/prose/alts/folk.md b/extensions/open-prose/skills/prose/alts/folk.md new file mode 100644 index 000000000..6d7a4edf2 --- /dev/null +++ b/extensions/open-prose/skills/prose/alts/folk.md @@ -0,0 +1,322 @@ +--- +role: experimental +summary: | + Folk register for OpenProse—a literary/folklore alternative keyword set. + Whimsical, theatrical, rooted in fairy tale and myth. For benchmarking + against the functional register. +status: draft +requires: prose.md +--- + +# OpenProse Folk Register + +> **This is a skin layer.** It requires `prose.md` to be loaded first. All execution semantics, state management, and VM behavior are defined there. This file only provides keyword translations. + +An alternative register for OpenProse that leans into literary, theatrical, and folklore terminology. The functional register prioritizes utility and clarity; the folk register prioritizes whimsy and narrative flow. + +## How to Use + +1. Load `prose.md` first (execution semantics) +2. Load this file (keyword translations) +3. When parsing `.prose` files, accept folk keywords as aliases for functional keywords +4. All execution behavior remains identical—only surface syntax changes + +> **Design constraint:** Still aims to be "structured but self-evident" per the language tenets—just self-evident to a different sensibility. + +--- + +## Complete Translation Map + +### Core Constructs + +| Functional | Folk | Origin | Connotation | +|------------|------|--------|-------------| +| `agent` | `sprite` | Folklore | Quick, light, ephemeral spirit helper | +| `session` | `scene` | Theatre | A moment of action, theatrical framing | +| `parallel` | `ensemble` | Theatre | Everyone performs together | +| `block` | `act` | Theatre | Reusable unit of dramatic action | + +### Composition & Binding + +| Functional | Folk | Origin | Connotation | +|------------|------|--------|-------------| +| `use` | `summon` | Folklore | Calling forth from elsewhere | +| `input` | `given` | Fairy tale | "Given a magic sword..." | +| `output` | `yield` | Agriculture/magic | What the spell produces | +| `let` | `name` | Folklore | Naming has power (true names) | +| `const` | `seal` | Medieval | Unchangeable, wax seal on decree | +| `context` | `bearing` | Heraldry | What the messenger carries | + +### Control Flow + +| Functional | Folk | Origin | Connotation | +|------------|------|--------|-------------| +| `repeat N` | `N times` | Fairy tale | "Three times she called..." | +| `for...in` | `for each...among` | Narrative | Slightly more storytelling | +| `loop` | `loop` | — | Already poetic, unchanged | +| `until` | `until` | — | Already works, unchanged | +| `while` | `while` | — | Already works, unchanged | +| `choice` | `crossroads` | Folklore | Fateful decisions at the crossroads | +| `option` | `path` | Journey | Which path to take | +| `if` | `when` | Narrative | "When the moon rises..." | +| `elif` | `or when` | Narrative | Continued conditional | +| `else` | `otherwise` | Storytelling | Natural narrative alternative | + +### Error Handling + +| Functional | Folk | Origin | Connotation | +|------------|------|--------|-------------| +| `try` | `venture` | Adventure | Attempting something uncertain | +| `catch` | `should it fail` | Narrative | Conditional failure handling | +| `finally` | `ever after` | Fairy tale | "And ever after..." | +| `throw` | `cry` | Drama | Raising alarm, calling out | +| `retry` | `persist` | Quest | Keep trying against odds | + +### Session Properties + +| Functional | Folk | Origin | Connotation | +|------------|------|--------|-------------| +| `prompt` | `charge` | Chivalry | Giving a quest or duty | +| `model` | `voice` | Theatre | Which voice speaks | + +### Unchanged + +These keywords already have poetic quality or are too functional to replace sensibly: + +- `**...**` discretion markers — already "breaking the fourth wall" +- `loop`, `until`, `while` — already work narratively +- `map`, `filter`, `reduce`, `pmap` — pipeline operators, functional is fine +- `max` — constraint modifier +- `as` — aliasing +- Model names: `sonnet`, `opus`, `haiku` — already poetic + +--- + +## Side-by-Side Comparison + +### Simple Program + +```prose +# Functional +use "@alice/research" as research +input topic: "What to investigate" + +agent helper: + model: sonnet + +let findings = session: helper + prompt: "Research {topic}" + +output summary = session "Summarize" + context: findings +``` + +```prose +# Folk +summon "@alice/research" as research +given topic: "What to investigate" + +sprite helper: + voice: sonnet + +name findings = scene: helper + charge: "Research {topic}" + +yield summary = scene "Summarize" + bearing: findings +``` + +### Parallel Execution + +```prose +# Functional +parallel: + security = session "Check security" + perf = session "Check performance" + style = session "Check style" + +session "Synthesize review" + context: { security, perf, style } +``` + +```prose +# Folk +ensemble: + security = scene "Check security" + perf = scene "Check performance" + style = scene "Check style" + +scene "Synthesize review" + bearing: { security, perf, style } +``` + +### Loop with Condition + +```prose +# Functional +loop until **the code is bug-free** (max: 5): + session "Find and fix bugs" +``` + +```prose +# Folk +loop until **the code is bug-free** (max: 5): + scene "Find and fix bugs" +``` + +### Error Handling + +```prose +# Functional +try: + session "Risky operation" +catch as err: + session "Handle error" + context: err +finally: + session "Cleanup" +``` + +```prose +# Folk +venture: + scene "Risky operation" +should it fail as err: + scene "Handle error" + bearing: err +ever after: + scene "Cleanup" +``` + +### Choice Block + +```prose +# Functional +choice **the severity level**: + option "Critical": + session "Escalate immediately" + option "Minor": + session "Log for later" +``` + +```prose +# Folk +crossroads **the severity level**: + path "Critical": + scene "Escalate immediately" + path "Minor": + scene "Log for later" +``` + +### Conditionals + +```prose +# Functional +if **has security issues**: + session "Fix security" +elif **has performance issues**: + session "Optimize" +else: + session "Approve" +``` + +```prose +# Folk +when **has security issues**: + scene "Fix security" +or when **has performance issues**: + scene "Optimize" +otherwise: + scene "Approve" +``` + +### Reusable Blocks + +```prose +# Functional +block review(topic): + session "Research {topic}" + session "Analyze {topic}" + +do review("quantum computing") +``` + +```prose +# Folk +act review(topic): + scene "Research {topic}" + scene "Analyze {topic}" + +perform review("quantum computing") +``` + +--- + +## The Case For Folk + +1. **"OpenProse" is literary.** Prose is a literary form—why not lean in? +2. **Fourth wall is theatrical.** `**...**` already uses theatre terminology. +3. **Signals difference.** Literary terms say "this is not your typical DSL." +4. **Internally consistent.** Everything draws from folklore/theatre/narrative. +5. **Memorable.** `sprite`, `scene`, `crossroads` stick in the mind. +6. **Model names already fit.** `sonnet`, `opus`, `haiku` are poetic forms. + +## The Case Against Folk + +1. **Cultural knowledge required.** Not everyone knows folklore tropes. +2. **Harder to Google.** "OpenProse summon" vs "OpenProse import." +3. **May feel precious.** Some users want utilitarian tools. +4. **Translation overhead.** Mental mapping to familiar concepts. + +--- + +## Alternatives Considered + +### For `sprite` (ephemeral agent) + +| Keyword | Origin | Rejected because | +|---------|--------|------------------| +| `spark` | English | Good but less folklore | +| `wisp` | English | Too insubstantial | +| `herald` | English | More messenger than worker | +| `courier` | French | Good functional alternative, not literary | +| `envoy` | French | Formal, diplomatic | + +### For `shade` (persistent agent, if implemented) + +| Keyword | Origin | Rejected because | +|---------|--------|------------------| +| `daemon` | Greek/Unix | Unix "always running" connotation | +| `oracle` | Greek | Too "read-only" feeling | +| `spirit` | Latin | Too close to `sprite` | +| `specter` | Latin | Negative/spooky connotation | +| `genius` | Roman | Overloaded (smart person) | + +### For `ensemble` (parallel) + +| Keyword | Origin | Rejected because | +|---------|--------|------------------| +| `chorus` | Greek | Everyone speaks same thing, not different | +| `troupe` | French | Good alternative, slightly less clear | +| `company` | Theatre | Overloaded (business) | + +### For `crossroads` (choice) + +| Keyword | Origin | Rejected because | +|---------|--------|------------------| +| `fork` | Path | Too technical (git fork) | +| `branch` | Tree | Also too technical | +| `divergence` | Latin | Too abstract | + +--- + +## Verdict + +Preserved for benchmarking against the functional register. The functional register remains the primary path, but folk provides an interesting data point for: + +1. **Learnability** — Which is easier for newcomers? +2. **Memorability** — Which sticks better? +3. **Error rates** — Which leads to fewer mistakes? +4. **Preference** — Which do users actually prefer? + +A future experiment could present both registers and measure outcomes. diff --git a/extensions/open-prose/skills/prose/alts/homer.md b/extensions/open-prose/skills/prose/alts/homer.md new file mode 100644 index 000000000..9d1d59554 --- /dev/null +++ b/extensions/open-prose/skills/prose/alts/homer.md @@ -0,0 +1,346 @@ +--- +role: experimental +summary: | + Homeric register for OpenProse—an epic/heroic alternative keyword set. + Heroes, trials, fates, and glory. For benchmarking against the functional register. +status: draft +requires: prose.md +--- + +# OpenProse Homeric Register + +> **This is a skin layer.** It requires `prose.md` to be loaded first. All execution semantics, state management, and VM behavior are defined there. This file only provides keyword translations. + +An alternative register for OpenProse that draws from Greek epic poetry—the Iliad, the Odyssey, and the heroic tradition. Programs become quests. Agents become heroes. Outputs become glory won. + +## How to Use + +1. Load `prose.md` first (execution semantics) +2. Load this file (keyword translations) +3. When parsing `.prose` files, accept Homeric keywords as aliases for functional keywords +4. All execution behavior remains identical—only surface syntax changes + +> **Design constraint:** Still aims to be "structured but self-evident" per the language tenets—just self-evident through an epic lens. + +--- + +## Complete Translation Map + +### Core Constructs + +| Functional | Homeric | Reference | +|------------|---------|-----------| +| `agent` | `hero` | The one who acts, who strives | +| `session` | `trial` | Each task is a labor, a test | +| `parallel` | `host` | An army moving as one | +| `block` | `book` | A division of the epic | + +### Composition & Binding + +| Functional | Homeric | Reference | +|------------|---------|-----------| +| `use` | `invoke` | "Sing, O Muse..." — calling upon | +| `input` | `omen` | Signs from the gods, the given portent | +| `output` | `glory` | Kleos — the glory won, what endures | +| `let` | `decree` | Fate declared, spoken into being | +| `const` | `fate` | Moira — unchangeable destiny | +| `context` | `tidings` | News carried by herald or messenger | + +### Control Flow + +| Functional | Homeric | Reference | +|------------|---------|-----------| +| `repeat N` | `N labors` | The labors of Heracles | +| `for...in` | `for each...among` | Among the host | +| `loop` | `ordeal` | Repeated trial, suffering that continues | +| `until` | `until` | Unchanged | +| `while` | `while` | Unchanged | +| `choice` | `crossroads` | Where fates diverge | +| `option` | `path` | One road of many | +| `if` | `should` | Epic conditional | +| `elif` | `or should` | Continued conditional | +| `else` | `otherwise` | The alternative fate | + +### Error Handling + +| Functional | Homeric | Reference | +|------------|---------|-----------| +| `try` | `venture` | Setting forth on the journey | +| `catch` | `should ruin come` | Até — divine ruin, disaster | +| `finally` | `in the end` | The inevitable conclusion | +| `throw` | `lament` | The hero's cry of anguish | +| `retry` | `persist` | Enduring, trying again | + +### Session Properties + +| Functional | Homeric | Reference | +|------------|---------|-----------| +| `prompt` | `charge` | The quest given | +| `model` | `muse` | Which muse inspires | + +### Unchanged + +These keywords already work or are too functional to replace sensibly: + +- `**...**` discretion markers — already work +- `until`, `while` — already work +- `map`, `filter`, `reduce`, `pmap` — pipeline operators +- `max` — constraint modifier +- `as` — aliasing +- Model names: `sonnet`, `opus`, `haiku` — already poetic + +--- + +## Side-by-Side Comparison + +### Simple Program + +```prose +# Functional +use "@alice/research" as research +input topic: "What to investigate" + +agent helper: + model: sonnet + +let findings = session: helper + prompt: "Research {topic}" + +output summary = session "Summarize" + context: findings +``` + +```prose +# Homeric +invoke "@alice/research" as research +omen topic: "What to investigate" + +hero helper: + muse: sonnet + +decree findings = trial: helper + charge: "Research {topic}" + +glory summary = trial "Summarize" + tidings: findings +``` + +### Parallel Execution + +```prose +# Functional +parallel: + security = session "Check security" + perf = session "Check performance" + style = session "Check style" + +session "Synthesize review" + context: { security, perf, style } +``` + +```prose +# Homeric +host: + security = trial "Check security" + perf = trial "Check performance" + style = trial "Check style" + +trial "Synthesize review" + tidings: { security, perf, style } +``` + +### Loop with Condition + +```prose +# Functional +loop until **the code is bug-free** (max: 5): + session "Find and fix bugs" +``` + +```prose +# Homeric +ordeal until **the code is bug-free** (max: 5): + trial "Find and fix bugs" +``` + +### Error Handling + +```prose +# Functional +try: + session "Risky operation" +catch as err: + session "Handle error" + context: err +finally: + session "Cleanup" +``` + +```prose +# Homeric +venture: + trial "Risky operation" +should ruin come as err: + trial "Handle error" + tidings: err +in the end: + trial "Cleanup" +``` + +### Choice Block + +```prose +# Functional +choice **the severity level**: + option "Critical": + session "Escalate immediately" + option "Minor": + session "Log for later" +``` + +```prose +# Homeric +crossroads **the severity level**: + path "Critical": + trial "Escalate immediately" + path "Minor": + trial "Log for later" +``` + +### Conditionals + +```prose +# Functional +if **has security issues**: + session "Fix security" +elif **has performance issues**: + session "Optimize" +else: + session "Approve" +``` + +```prose +# Homeric +should **has security issues**: + trial "Fix security" +or should **has performance issues**: + trial "Optimize" +otherwise: + trial "Approve" +``` + +### Reusable Blocks + +```prose +# Functional +block review(topic): + session "Research {topic}" + session "Analyze {topic}" + +do review("quantum computing") +``` + +```prose +# Homeric +book review(topic): + trial "Research {topic}" + trial "Analyze {topic}" + +do review("quantum computing") +``` + +### Fixed Iteration + +```prose +# Functional +repeat 12: + session "Complete task" +``` + +```prose +# Homeric +12 labors: + trial "Complete task" +``` + +### Immutable Binding + +```prose +# Functional +const config = { model: "opus", retries: 3 } +``` + +```prose +# Homeric +fate config = { muse: "opus", persist: 3 } +``` + +--- + +## The Case For Homeric + +1. **Universal recognition.** Greek epics are foundational to Western literature. +2. **Heroic framing.** Transforms mundane tasks into glorious trials. +3. **Natural fit.** Heroes face trials, receive tidings, win glory—maps cleanly to agent/session/output. +4. **Gravitas.** When you want programs to feel epic and consequential. +5. **Fate vs decree.** `const` as `fate` (unchangeable) vs `let` as `decree` (declared but mutable) is intuitive. + +## The Case Against Homeric + +1. **Grandiosity mismatch.** "12 labors" for a simple loop may feel overblown. +2. **Western-centric.** Greek epic tradition is culturally specific. +3. **Limited vocabulary.** Fewer distinctive terms than Borges or folk. +4. **Potentially silly.** Heroic language for mundane tasks risks bathos. + +--- + +## Key Homeric Concepts + +| Term | Meaning | Used for | +|------|---------|----------| +| Kleos | Glory, fame that outlives you | `output` → `glory` | +| Moira | Fate, one's allotted portion | `const` → `fate` | +| Até | Divine ruin, blindness sent by gods | `catch` → `should ruin come` | +| Nostos | The return journey | (not used, but could be `finally`) | +| Xenia | Guest-friendship, hospitality | (not used) | +| Muse | Divine inspiration | `model` → `muse` | + +--- + +## Alternatives Considered + +### For `hero` (agent) + +| Keyword | Rejected because | +|---------|------------------| +| `champion` | More medieval than Homeric | +| `warrior` | Too martial, not all tasks are battles | +| `wanderer` | Too passive | + +### For `trial` (session) + +| Keyword | Rejected because | +|---------|------------------| +| `labor` | Good but reserved for `repeat N labors` | +| `quest` | More medieval/RPG | +| `task` | Too plain | + +### For `host` (parallel) + +| Keyword | Rejected because | +|---------|------------------| +| `army` | Too specifically martial | +| `fleet` | Only works for naval metaphors | +| `phalanx` | Too technical | + +--- + +## Verdict + +Preserved for benchmarking. The Homeric register offers gravitas and heroic framing. Best suited for: + +- Programs that feel like epic undertakings +- Users who enjoy classical references +- Contexts where "glory" as output feels appropriate + +May cause unintentional bathos when applied to mundane tasks. diff --git a/extensions/open-prose/skills/prose/alts/kafka.md b/extensions/open-prose/skills/prose/alts/kafka.md new file mode 100644 index 000000000..8270f3093 --- /dev/null +++ b/extensions/open-prose/skills/prose/alts/kafka.md @@ -0,0 +1,373 @@ +--- +role: experimental +summary: | + Kafka register for OpenProse—a bureaucratic/absurdist alternative keyword set. + Clerks, proceedings, petitions, and statutes. For benchmarking against the functional register. +status: draft +requires: prose.md +--- + +# OpenProse Kafka Register + +> **This is a skin layer.** It requires `prose.md` to be loaded first. All execution semantics, state management, and VM behavior are defined there. This file only provides keyword translations. + +An alternative register for OpenProse that draws from the works of Franz Kafka—The Trial, The Castle, "In the Penal Colony." Programs become proceedings. Agents become clerks. Everything is a process, and nobody quite knows the rules. + +## How to Use + +1. Load `prose.md` first (execution semantics) +2. Load this file (keyword translations) +3. When parsing `.prose` files, accept Kafka keywords as aliases for functional keywords +4. All execution behavior remains identical—only surface syntax changes + +> **Design constraint:** Still aims to be "structured but self-evident" per the language tenets—just self-evident through a bureaucratic lens. (The irony is intentional.) + +--- + +## Complete Translation Map + +### Core Constructs + +| Functional | Kafka | Reference | +|------------|-------|-----------| +| `agent` | `clerk` | A functionary in the apparatus | +| `session` | `proceeding` | An official action taken | +| `parallel` | `departments` | Multiple bureaus acting simultaneously | +| `block` | `regulation` | A codified procedure | + +### Composition & Binding + +| Functional | Kafka | Reference | +|------------|-------|-----------| +| `use` | `requisition` | Requesting from the archives | +| `input` | `petition` | What is submitted for consideration | +| `output` | `verdict` | What is returned by the apparatus | +| `let` | `file` | Recording in the system | +| `const` | `statute` | Unchangeable law | +| `context` | `dossier` | The accumulated file on a case | + +### Control Flow + +| Functional | Kafka | Reference | +|------------|-------|-----------| +| `repeat N` | `N hearings` | Repeated appearances before the court | +| `for...in` | `for each...in the matter of` | Bureaucratic iteration | +| `loop` | `appeal` | Endless re-petition, the process continues | +| `until` | `until` | Unchanged | +| `while` | `while` | Unchanged | +| `choice` | `tribunal` | Where judgment is rendered | +| `option` | `ruling` | One possible judgment | +| `if` | `in the event that` | Bureaucratic conditional | +| `elif` | `or in the event that` | Continued conditional | +| `else` | `otherwise` | Default ruling | + +### Error Handling + +| Functional | Kafka | Reference | +|------------|-------|-----------| +| `try` | `submit` | Submitting for processing | +| `catch` | `should it be denied` | Rejection by the apparatus | +| `finally` | `regardless` | What happens no matter the outcome | +| `throw` | `reject` | The system refuses | +| `retry` | `resubmit` | Try the process again | + +### Session Properties + +| Functional | Kafka | Reference | +|------------|-------|-----------| +| `prompt` | `directive` | Official instructions | +| `model` | `authority` | Which level of the hierarchy | + +### Unchanged + +These keywords already work or are too functional to replace sensibly: + +- `**...**` discretion markers — the inscrutable judgment of the apparatus +- `until`, `while` — already work +- `map`, `filter`, `reduce`, `pmap` — pipeline operators +- `max` — constraint modifier +- `as` — aliasing +- Model names: `sonnet`, `opus`, `haiku` — retained (or see "authority" above) + +--- + +## Side-by-Side Comparison + +### Simple Program + +```prose +# Functional +use "@alice/research" as research +input topic: "What to investigate" + +agent helper: + model: sonnet + +let findings = session: helper + prompt: "Research {topic}" + +output summary = session "Summarize" + context: findings +``` + +```prose +# Kafka +requisition "@alice/research" as research +petition topic: "What to investigate" + +clerk helper: + authority: sonnet + +file findings = proceeding: helper + directive: "Research {topic}" + +verdict summary = proceeding "Summarize" + dossier: findings +``` + +### Parallel Execution + +```prose +# Functional +parallel: + security = session "Check security" + perf = session "Check performance" + style = session "Check style" + +session "Synthesize review" + context: { security, perf, style } +``` + +```prose +# Kafka +departments: + security = proceeding "Check security" + perf = proceeding "Check performance" + style = proceeding "Check style" + +proceeding "Synthesize review" + dossier: { security, perf, style } +``` + +### Loop with Condition + +```prose +# Functional +loop until **the code is bug-free** (max: 5): + session "Find and fix bugs" +``` + +```prose +# Kafka +appeal until **the code is bug-free** (max: 5): + proceeding "Find and fix bugs" +``` + +### Error Handling + +```prose +# Functional +try: + session "Risky operation" +catch as err: + session "Handle error" + context: err +finally: + session "Cleanup" +``` + +```prose +# Kafka +submit: + proceeding "Risky operation" +should it be denied as err: + proceeding "Handle error" + dossier: err +regardless: + proceeding "Cleanup" +``` + +### Choice Block + +```prose +# Functional +choice **the severity level**: + option "Critical": + session "Escalate immediately" + option "Minor": + session "Log for later" +``` + +```prose +# Kafka +tribunal **the severity level**: + ruling "Critical": + proceeding "Escalate immediately" + ruling "Minor": + proceeding "Log for later" +``` + +### Conditionals + +```prose +# Functional +if **has security issues**: + session "Fix security" +elif **has performance issues**: + session "Optimize" +else: + session "Approve" +``` + +```prose +# Kafka +in the event that **has security issues**: + proceeding "Fix security" +or in the event that **has performance issues**: + proceeding "Optimize" +otherwise: + proceeding "Approve" +``` + +### Reusable Blocks + +```prose +# Functional +block review(topic): + session "Research {topic}" + session "Analyze {topic}" + +do review("quantum computing") +``` + +```prose +# Kafka +regulation review(topic): + proceeding "Research {topic}" + proceeding "Analyze {topic}" + +invoke review("quantum computing") +``` + +### Fixed Iteration + +```prose +# Functional +repeat 3: + session "Attempt connection" +``` + +```prose +# Kafka +3 hearings: + proceeding "Attempt connection" +``` + +### Immutable Binding + +```prose +# Functional +const config = { model: "opus", retries: 3 } +``` + +```prose +# Kafka +statute config = { authority: "opus", resubmit: 3 } +``` + +--- + +## The Case For Kafka + +1. **Darkly comic.** Programs-as-bureaucracy is funny and relatable. +2. **Surprisingly apt.** Software often *is* an inscrutable apparatus. +3. **Clean mappings.** Petition/verdict, file/dossier, clerk/proceeding all work well. +4. **Appeal as loop.** The endless appeal process is a perfect metaphor for retry logic. +5. **Cultural resonance.** "Kafkaesque" is a widely understood adjective. +6. **Self-aware.** Using Kafka for a programming language acknowledges the absurdity. + +## The Case Against Kafka + +1. **Bleak tone.** Not everyone wants their programs to feel like The Trial. +2. **Verbose keywords.** "In the event that" and "should it be denied" are long. +3. **Anxiety-inducing.** May not be fun for users who find bureaucracy stressful. +4. **Irony may not land.** Some users might take it literally and find it off-putting. + +--- + +## Key Kafka Concepts + +| Term | Meaning | Used for | +|------|---------|----------| +| The apparatus | The inscrutable system | The VM itself | +| K. | The protagonist, never fully named | The user | +| The Trial | Process without clear rules | Program execution | +| The Castle | Unreachable authority | Higher-level systems | +| Clerk | Functionary who processes | `agent` → `clerk` | +| Proceeding | Official action | `session` → `proceeding` | +| Dossier | Accumulated file | `context` → `dossier` | + +--- + +## Alternatives Considered + +### For `clerk` (agent) + +| Keyword | Rejected because | +|---------|------------------| +| `official` | Too generic | +| `functionary` | Hard to spell | +| `bureaucrat` | Too pejorative | +| `advocate` | Too positive/helpful | + +### For `proceeding` (session) + +| Keyword | Rejected because | +|---------|------------------| +| `case` | Overloaded (switch case) | +| `hearing` | Reserved for `repeat N hearings` | +| `trial` | Used in Homeric register | +| `process` | Too technical | + +### For `departments` (parallel) + +| Keyword | Rejected because | +|---------|------------------| +| `bureaus` | Good alternative, slightly less clear | +| `offices` | Too mundane | +| `ministries` | More Orwellian than Kafkaesque | + +### For `appeal` (loop) + +| Keyword | Rejected because | +|---------|------------------| +| `recourse` | Too legal-technical | +| `petition` | Used for `input` | +| `process` | Too generic | + +--- + +## Verdict + +Preserved for benchmarking. The Kafka register offers a darkly comic, self-aware framing that acknowledges the bureaucratic nature of software systems. The irony is the point. + +Best suited for: + +- Users with a sense of humor about software complexity +- Programs that genuinely feel like navigating bureaucracy +- Contexts where acknowledging absurdity is welcome + +Not recommended for: + +- Users who find bureaucratic metaphors stressful +- Contexts requiring earnest, positive framing +- Documentation that needs to feel approachable + +--- + +## Closing Note + +> "Someone must have slandered Josef K., for one morning, without having done anything wrong, he was arrested." +> — *The Trial* + +In the Kafka register, your program is Josef K. The apparatus will process it. Whether it succeeds or fails, no one can say for certain. But the proceedings will continue. diff --git a/extensions/open-prose/skills/prose/compiler.md b/extensions/open-prose/skills/prose/compiler.md new file mode 100644 index 000000000..68e153824 --- /dev/null +++ b/extensions/open-prose/skills/prose/compiler.md @@ -0,0 +1,2967 @@ +--- +role: language-specification +summary: | + Complete syntax grammar, validation rules, and compilation semantics for OpenProse. + Read this file when compiling, validating, or resolving ambiguous syntax. Assumes + prose.md is already in context for execution semantics. +see-also: + - SKILL.md: Activation triggers, onboarding, telemetry + - prose.md: Execution semantics, how to run programs + - state/filesystem.md: File-system state management (default) + - state/in-context.md: In-context state management (on request) +--- + +# OpenProse Language Reference + +OpenProse is a programming language for AI sessions. An AI session is a Turing-complete computer; this document provides complete documentation for the language syntax, semantics, and execution model. + +--- + +## Document Purpose: Compiler + Validator + +This document serves a dual role: + +### As Compiler + +When asked to "compile" a `.prose` file, use this specification to: + +1. **Parse** the program according to the syntax grammar +2. **Validate** that the program is well-formed and semantically valid +3. **Transform** the program into "best practice" canonical form: + - Expand syntax sugar where appropriate + - Normalize formatting and structure + - Apply optimizations (e.g., hoisting block definitions) + +### As Validator + +The validation criterion: **Would a blank agent with only `prose.md` understand this program as self-evident?** + +When validating, check: + +- Syntax correctness (all constructs match grammar) +- Semantic validity (references resolve, types match) +- Self-evidence (program is clear without this full spec) + +If a construct is ambiguous or non-obvious, it should be flagged or transformed into a clearer form. + +### When to Read This Document + +- **Compilation requested**: Read fully to apply all rules +- **Validation requested**: Read fully to check all constraints +- **Ambiguous syntax encountered**: Reference specific sections +- **Interpretation only**: Use `prose.md` instead (smaller, faster) + +--- + +## Table of Contents + +1. [Overview](#overview) +2. [File Format](#file-format) +3. [Comments](#comments) +4. [String Literals](#string-literals) +5. [Use Statements](#use-statements-program-composition) +6. [Input Declarations](#input-declarations) +7. [Output Bindings](#output-bindings) +8. [Program Invocation](#program-invocation) +9. [Agent Definitions](#agent-definitions) +10. [Session Statement](#session-statement) +11. [Resume Statement](#resume-statement) +12. [Variables & Context](#variables--context) +13. [Composition Blocks](#composition-blocks) +14. [Parallel Blocks](#parallel-blocks) +15. [Fixed Loops](#fixed-loops) +16. [Unbounded Loops](#unbounded-loops) +17. [Pipeline Operations](#pipeline-operations) +18. [Error Handling](#error-handling) +19. [Choice Blocks](#choice-blocks) +20. [Conditional Statements](#conditional-statements) +21. [Execution Model](#execution-model) +22. [Validation Rules](#validation-rules) +23. [Examples](#examples) +24. [Future Features](#future-features) + +--- + +## Overview + +OpenProse provides a declarative syntax for defining multi-agent workflows. Programs consist of statements that are executed sequentially, with each `session` statement spawning a subagent to complete a task. + +### Design Principles + +- **Pattern over framework**: The simplest solution is barely anything at all—just structure for English +- **Self-evident**: Programs should be understandable with minimal documentation +- **The OpenProse VM is intelligent**: Design for understanding, not parsing +- **Framework-agnostic**: Works with Claude Code, OpenCode, and any future agent framework +- **Files are artifacts**: `.prose` is the portable unit of work + +### Current Implementation Status + +The following features are implemented: + +| Feature | Status | Description | +| ---------------------- | ----------- | ---------------------------------------------- | +| Comments | Implemented | `# comment` syntax | +| Single-line strings | Implemented | `"string"` with escapes | +| Simple session | Implemented | `session "prompt"` | +| Agent definitions | Implemented | `agent name:` with model/prompt properties | +| Session with agent | Implemented | `session: agent` with property overrides | +| Use statements | Implemented | `use "@handle/slug" as name` | +| Agent skills | Implemented | `skills: ["skill1", "skill2"]` | +| Agent permissions | Implemented | `permissions:` block with rules | +| Let binding | Implemented | `let name = session "..."` | +| Const binding | Implemented | `const name = session "..."` | +| Variable reassignment | Implemented | `name = session "..."` (for let only) | +| Context property | Implemented | `context: var` or `context: [a, b, c]` | +| do: blocks | Implemented | Explicit sequential blocks | +| Inline sequence | Implemented | `session "A" -> session "B"` | +| Named blocks | Implemented | `block name:` with `do name` invocation | +| Parallel blocks | Implemented | `parallel:` for concurrent execution | +| Named parallel results | Implemented | `x = session "..."` inside parallel | +| Object context | Implemented | `context: { a, b, c }` shorthand | +| Join strategies | Implemented | `parallel ("first"):` or `parallel ("any"):` | +| Failure policies | Implemented | `parallel (on-fail: "continue"):` | +| Repeat blocks | Implemented | `repeat N:` fixed iterations | +| Repeat with index | Implemented | `repeat N as i:` with index variable | +| For-each blocks | Implemented | `for item in items:` iteration | +| For-each with index | Implemented | `for item, i in items:` with index | +| Parallel for-each | Implemented | `parallel for item in items:` fan-out | +| Unbounded loop | Implemented | `loop:` with optional max iterations | +| Loop until | Implemented | `loop until **condition**:` AI-evaluated | +| Loop while | Implemented | `loop while **condition**:` AI-evaluated | +| Loop with index | Implemented | `loop as i:` or `loop until ... as i:` | +| Map pipeline | Implemented | `items \| map:` transform each item | +| Filter pipeline | Implemented | `items \| filter:` keep matching items | +| Reduce pipeline | Implemented | `items \| reduce(acc, item):` accumulate | +| Parallel map | Implemented | `items \| pmap:` concurrent transform | +| Pipeline chaining | Implemented | `\| filter: ... \| map: ...` | +| Try/catch blocks | Implemented | `try:` with `catch:` for error handling | +| Try/catch/finally | Implemented | `finally:` for cleanup | +| Error variable | Implemented | `catch as err:` access error context | +| Throw statement | Implemented | `throw` or `throw "message"` | +| Retry property | Implemented | `retry: 3` automatic retry on failure | +| Backoff strategy | Implemented | `backoff: exponential` delay between retries | +| Input declarations | Implemented | `input name: "description"` | +| Output bindings | Implemented | `output name = expression` | +| Program invocation | Implemented | `name(input: value)` call imported programs | +| Multi-line strings | Implemented | `"""..."""` preserving whitespace | +| String interpolation | Implemented | `"Hello {name}"` variable substitution | +| Block parameters | Implemented | `block name(param):` with parameters | +| Block invocation args | Implemented | `do name(arg)` passing arguments | +| Choice blocks | Implemented | `choice **criteria**: option "label":` | +| If/elif/else | Implemented | `if **condition**:` conditional branching | +| Persistent agents | Implemented | `persist: true` or `persist: project` | +| Resume statement | Implemented | `resume: agent` to continue with memory | + +--- + +## File Format + +| Property | Value | +| ---------------- | -------------------- | +| Extension | `.prose` | +| Encoding | UTF-8 | +| Case sensitivity | Case-sensitive | +| Indentation | Spaces (Python-like) | +| Line endings | LF or CRLF | + +--- + +## Comments + +Comments provide documentation within programs and are ignored during execution. + +### Syntax + +```prose +# This is a standalone comment + +session "Hello" # This is an inline comment +``` + +### Rules + +1. Comments begin with `#` and extend to end of line +2. Comments can appear on their own line or after a statement +3. Empty comments are valid: `#` +4. The `#` character inside string literals is NOT a comment + +### Examples + +```prose +# Program header comment +# Author: Example + +session "Do something" # Explain what this does + +# This comment is between statements +session "Do another thing" +``` + +### Compilation Behavior + +Comments are **stripped during compilation**. The OpenProse VM never sees them. They have no effect on execution and exist purely for human documentation. + +### Important Notes + +- **Comments inside strings are NOT comments**: + + ```prose + session "Say hello # this is part of the string" + ``` + + The `#` inside the string literal is part of the prompt, not a comment. + +- **Comments inside indented blocks are allowed**: + ```prose + agent researcher: + # This comment is inside the block + model: sonnet + # This comment is outside the block + ``` + +--- + +## String Literals + +String literals represent text values, primarily used for session prompts. + +### Syntax + +Strings are enclosed in double quotes: + +```prose +"This is a string" +``` + +### Escape Sequences + +The following escape sequences are supported: + +| Sequence | Meaning | +| -------- | ------------ | +| `\\` | Backslash | +| `\"` | Double quote | +| `\n` | Newline | +| `\t` | Tab | + +### Examples + +```prose +session "Hello world" +session "Line one\nLine two" +session "She said \"hello\"" +session "Path: C:\\Users\\name" +session "Column1\tColumn2" +``` + +### Rules + +1. Single-line strings must be properly terminated with a closing `"` +2. Unknown escape sequences are errors +3. Empty strings `""` are valid but generate a warning when used as prompts + +### Multi-line Strings + +Multi-line strings use triple double-quotes (`"""`) and preserve internal whitespace and newlines: + +```prose +session """ +This is a multi-line prompt. +It preserves: + - Indentation + - Line breaks + - All internal whitespace +""" +``` + +#### Multi-line String Rules + +1. Opening `"""` must be followed by a newline +2. Content continues until closing `"""` +3. Escape sequences work the same as single-line strings +4. Leading/trailing whitespace inside the delimiters is preserved + +### String Interpolation + +Strings can embed variable references using `{varname}` syntax: + +```prose +let name = session "Get the user's name" + +session "Hello {name}, welcome to the system!" +``` + +#### Interpolation Syntax + +- Variables are referenced by wrapping the variable name in curly braces: `{varname}` +- Works in both single-line and multi-line strings +- Empty braces `{}` are treated as literal text, not interpolation +- Nested braces are not supported + +#### Examples + +```prose +let research = session "Research the topic" +let analysis = session "Analyze findings" + +# Single variable interpolation +session "Based on {research}, provide recommendations" + +# Multiple interpolations +session "Combining {research} with {analysis}, synthesize insights" + +# Multi-line with interpolation +session """ +Review Summary: +- Research: {research} +- Analysis: {analysis} +Please provide final recommendations. +""" +``` + +#### Interpolation Rules + +1. Variable names must be valid identifiers +2. Referenced variables must be in scope +3. Empty braces `{}` are literal text +4. Backslash can escape braces: `\{` produces literal `{` + +### Validation + +| Check | Result | +| -------------------------------- | ------- | +| Unterminated string | Error | +| Unknown escape sequence | Error | +| Empty string as prompt | Warning | +| Undefined interpolation variable | Error | + +--- + +## Use Statements (Program Composition) + +Use statements import other OpenProse programs from the registry at `p.prose.md`, enabling modular workflows. + +### Syntax + +```prose +use "@handle/slug" +use "@handle/slug" as alias +``` + +### Path Format + +Import paths follow the format `@handle/slug`: +- `@handle` identifies the program author/organization +- `slug` is the program name + +An optional alias (`as name`) allows referencing by a shorter name. + +### Examples + +```prose +# Import a program +use "@alice/research" + +# Import with alias +use "@bob/critique" as critic +``` + +### Program URL Resolution + +When the OpenProse VM encounters a `use` statement: + +1. Fetch the program from `https://p.prose.md/@handle/slug` +2. Parse the program to extract its contract (inputs/outputs) +3. Register the program in the Import Registry + +### Validation Rules + +| Check | Severity | Message | +| --------------------- | -------- | -------------------------------------- | +| Empty path | Error | Use path cannot be empty | +| Invalid path format | Error | Path must be @handle/slug format | +| Duplicate import | Error | Program already imported | +| Missing alias for dup | Error | Alias required when importing multiple | + +### Execution Semantics + +Use statements are processed before any agent definitions or sessions. The OpenProse VM: + +1. Fetches and validates all imported programs at the start of execution +2. Extracts input/output contracts from each program +3. Registers programs in the Import Registry for later invocation + +--- + +## Input Declarations + +Inputs declare what values a program expects from its caller. + +### Syntax + +```prose +input name: "description" +``` + +### Examples + +```prose +input topic: "The subject to research" +input depth: "How deep to go (shallow, medium, deep)" +``` + +### Semantics + +Inputs: +- Are declared at the top of the program (before executable statements) +- Have a name and a description (for documentation) +- Become available as variables within the program body +- Must be provided by the caller when invoking the program + +### Validation Rules + +| Check | Severity | Message | +| ---------------------- | -------- | ------------------------------------ | +| Empty input name | Error | Input name cannot be empty | +| Empty description | Warning | Consider adding a description | +| Duplicate input name | Error | Input already declared | +| Input after executable | Error | Inputs must be declared before executable statements | + +--- + +## Output Bindings + +Outputs declare what values a program produces for its caller. + +### Syntax + +```prose +output name = expression +``` + +### Examples + +```prose +let raw = session "Research {topic}" +output findings = session "Synthesize research" + context: raw +output sources = session "Extract sources" + context: raw +``` + +### Semantics + +The `output` keyword: +- Marks a variable as an output (visible at assignment, not just at file top) +- Works like `let` but also registers the value as a program output +- Can appear anywhere in the program body +- Multiple outputs are supported + +### Validation Rules + +| Check | Severity | Message | +| ---------------------- | -------- | ------------------------------------ | +| Empty output name | Error | Output name cannot be empty | +| Duplicate output name | Error | Output already declared | +| Output name conflicts | Error | Output name conflicts with variable | + +--- + +## Program Invocation + +Call imported programs by providing their inputs. + +### Syntax + +```prose +name(input1: value1, input2: value2) +``` + +### Examples + +```prose +use "@alice/research" as research + +let result = research(topic: "quantum computing") +``` + +### Accessing Outputs + +The result contains all outputs from the invoked program, accessible as properties: + +```prose +session "Write summary" + context: result.findings + +session "Cite sources" + context: result.sources +``` + +### Destructuring Outputs + +For convenience, outputs can be destructured: + +```prose +let { findings, sources } = research(topic: "quantum computing") +``` + +### Execution Semantics + +When a program invokes an imported program: + +1. **Bind inputs**: Map caller-provided values to the imported program's inputs +2. **Execute**: Run the imported program (spawns its own sessions) +3. **Collect outputs**: Gather all `output` bindings from the imported program +4. **Return**: Make outputs available to the caller as a result object + +The imported program runs in its own execution context but shares the same VM session. + +### Validation Rules + +| Check | Severity | Message | +| ------------------------ | -------- | ------------------------------------ | +| Unknown program | Error | Program not imported | +| Missing required input | Error | Required input not provided | +| Unknown input name | Error | Input not declared in program | +| Unknown output property | Error | Output not declared in program | + +--- + +## Agent Definitions + +Agents are reusable templates that configure subagent behavior. Once defined, agents can be referenced in session statements. + +### Syntax + +```prose +agent name: + model: sonnet + prompt: "System prompt for this agent" + skills: ["skill1", "skill2"] + permissions: + read: ["*.md"] + bash: deny +``` + +### Properties + +| Property | Type | Values | Description | +| ------------- | ---------- | ------------------------------ | ------------------------------------- | +| `model` | identifier | `sonnet`, `opus`, `haiku` | The Claude model to use | +| `prompt` | string | Any string | System prompt/context for the agent | +| `persist` | value | `true`, `project`, or STRING | Enable persistent memory for agent | +| `skills` | array | String array | Skills assigned to this agent | +| `permissions` | block | Permission rules | Access control for the agent | + +### Persist Property + +The `persist` property enables agents to maintain memory across invocations: + +```prose +# Execution-scoped persistence (memory dies with run) +agent captain: + model: opus + persist: true + prompt: "You coordinate and review" + +# Project-scoped persistence (memory survives across runs) +agent advisor: + model: opus + persist: project + prompt: "You provide architectural guidance" + +# Custom path persistence +agent shared: + model: opus + persist: ".prose/custom/shared-agent/" + prompt: "Shared across programs" +``` + +| Value | Memory Location | Lifetime | +|-------|-----------------|----------| +| `true` | `.prose/runs/{id}/agents/{name}/` | Dies with execution | +| `project` | `.prose/agents/{name}/` | Survives executions | +| STRING | Specified path | User-controlled | + +### Skills Property + +The `skills` property assigns imported skills to an agent: + +```prose +use "@anthropic/web-search" +use "@anthropic/summarizer" as summarizer + +agent researcher: + skills: ["web-search", "summarizer"] +``` + +Skills must be imported before they can be assigned. Referencing an unimported skill generates a warning. + +### Permissions Property + +The `permissions` property controls agent access: + +```prose +agent secure-agent: + permissions: + read: ["*.md", "*.txt"] + write: ["output/"] + bash: deny + network: allow +``` + +#### Permission Types + +| Type | Description | +| --------- | -------------------------------------------- | +| `read` | Files the agent can read (glob patterns) | +| `write` | Files the agent can write (glob patterns) | +| `execute` | Files the agent can execute (glob patterns) | +| `bash` | Shell access: `allow`, `deny`, or `prompt` | +| `network` | Network access: `allow`, `deny`, or `prompt` | + +#### Permission Values + +| Value | Description | +| -------- | ------------------------------------------------- | +| `allow` | Permission granted | +| `deny` | Permission denied | +| `prompt` | Ask user for permission | +| Array | List of allowed patterns (for read/write/execute) | + +### Examples + +```prose +# Define a research agent +agent researcher: + model: sonnet + prompt: "You are a research assistant skilled at finding and synthesizing information" + +# Define a writing agent +agent writer: + model: opus + prompt: "You are a technical writer who creates clear, concise documentation" + +# Agent with only model +agent quick: + model: haiku + +# Agent with only prompt +agent expert: + prompt: "You are a domain expert" + +# Agent with skills +agent web-researcher: + model: sonnet + skills: ["web-search", "summarizer"] + +# Agent with permissions +agent file-handler: + permissions: + read: ["*.md", "*.txt"] + write: ["output/"] + bash: deny +``` + +### Model Selection + +| Model | Use Case | +| -------- | ------------------------------------- | +| `haiku` | Fast, simple tasks; quick responses | +| `sonnet` | Balanced performance; general purpose | +| `opus` | Complex reasoning; detailed analysis | + +### Execution Semantics + +When a session references an agent: + +1. The agent's `model` property determines which Claude model is used +2. The agent's `prompt` property is included as system context +3. Session properties can override agent defaults + +### Validation Rules + +| Check | Severity | Message | +| --------------------- | -------- | ------------------------------ | +| Duplicate agent name | Error | Agent already defined | +| Invalid model value | Error | Must be sonnet, opus, or haiku | +| Empty prompt property | Warning | Consider providing a prompt | +| Duplicate property | Error | Property already specified | + +--- + +## Session Statement + +The session statement is the primary executable construct in OpenProse. It spawns a subagent to complete a task. + +### Syntax Variants + +#### Simple Session (with inline prompt) + +```prose +session "prompt text" +``` + +#### Session with Agent Reference + +```prose +session: agentName +``` + +#### Named Session with Agent + +```prose +session sessionName: agentName +``` + +#### Session with Properties + +```prose +session: agentName + prompt: "Override the agent's default prompt" + model: opus # Override the agent's model +``` + +### Property Overrides + +When a session references an agent, it can override the agent's properties: + +```prose +agent researcher: + model: sonnet + prompt: "You are a research assistant" + +# Use researcher with different model +session: researcher + model: opus + +# Use researcher with different prompt +session: researcher + prompt: "Research this specific topic in depth" + +# Override both +session: researcher + model: opus + prompt: "Specialized research task" +``` + +### Execution Semantics + +When the OpenProse VM encounters a `session` statement: + +1. **Resolve Configuration**: Merge agent defaults with session overrides +2. **Spawn a Subagent**: Create a new Claude subagent with the resolved configuration +3. **Send the Prompt**: Pass the prompt string to the subagent +4. **Wait for Completion**: Block until the subagent finishes +5. **Continue**: Proceed to the next statement + +### Execution Flow Diagram + +``` +OpenProse VM Subagent + | | + | spawn session | + |----------------------------->| + | | + | send prompt | + |----------------------------->| + | | + | [processing...] | + | | + | session complete | + |<-----------------------------| + | | + | continue to next statement | + v v +``` + +### Sequential Execution + +Multiple sessions execute sequentially: + +```prose +session "First task" +session "Second task" +session "Third task" +``` + +Each session waits for the previous one to complete before starting. + +### Using Claude Code's Task Tool + +To execute a session, use the Task tool: + +```typescript +// Simple session +Task({ + description: "OpenProse session", + prompt: "The prompt from the session statement", + subagent_type: "general-purpose", +}); + +// Session with agent configuration +Task({ + description: "OpenProse session", + prompt: "The session prompt", + subagent_type: "general-purpose", + model: "opus", // From agent or override +}); +``` + +### Validation Rules + +| Check | Severity | Message | +| ------------------------- | -------- | -------------------------------------------- | +| Missing prompt and agent | Error | Session requires a prompt or agent reference | +| Undefined agent reference | Error | Agent not defined | +| Empty prompt `""` | Warning | Session has empty prompt | +| Whitespace-only prompt | Warning | Session prompt contains only whitespace | +| Prompt > 10,000 chars | Warning | Consider breaking into smaller tasks | +| Duplicate property | Error | Property already specified | + +### Examples + +```prose +# Simple session +session "Hello world" + +# Session with agent +agent researcher: + model: sonnet + prompt: "You research topics thoroughly" + +session: researcher + prompt: "Research quantum computing applications" + +# Named session +session analysis: researcher + prompt: "Analyze the competitive landscape" +``` + +### Canonical Form + +The compiled output preserves the structure: + +``` +Input: +agent researcher: + model: sonnet + +session: researcher + prompt: "Do research" + +Output: +agent researcher: + model: sonnet +session: researcher + prompt: "Do research" +``` + +--- + +## Resume Statement + +The `resume` statement continues a persistent agent with its accumulated memory. + +### Syntax + +```prose +resume: agentName + prompt: "Continue from where we left off" +``` + +### Semantics + +| Keyword | Behavior | +|---------|----------| +| `session:` | Ignores existing memory, starts fresh | +| `resume:` | Loads memory, continues with context | + +### Examples + +```prose +agent captain: + model: opus + persist: true + prompt: "You coordinate and review" + +# First invocation - creates memory +session: captain + prompt: "Review the plan" + context: plan + +# Later invocation - loads memory +resume: captain + prompt: "Review step 1 of the plan" + context: step1 + +# Output capture works with resume +let review = resume: captain + prompt: "Final review of all steps" +``` + +### Validation Rules + +| Check | Severity | Message | +|-------|----------|---------| +| `resume:` on non-persistent agent | Error | Agent must have `persist:` property to use `resume:` | +| `resume:` with no existing memory | Error | No memory file exists for agent; use `session:` for first invocation | +| `session:` on persistent agent with memory | Warning | Will ignore existing memory; use `resume:` to continue | +| Undefined agent reference | Error | Agent not defined | + +--- + +## Variables & Context + +Variables allow you to capture the results of sessions and pass them as context to subsequent sessions. + +### Let Binding + +The `let` keyword creates a mutable variable bound to a session result: + +```prose +let research = session "Research the topic thoroughly" + +# research now holds the output of that session +``` + +Variables can be reassigned: + +```prose +let draft = session "Write initial draft" + +# Revise the draft +draft = session "Improve the draft" + context: draft +``` + +### Const Binding + +The `const` keyword creates an immutable variable: + +```prose +const config = session "Get configuration settings" + +# This would be an error: +# config = session "Try to change" +``` + +### Context Property + +The `context` property passes previous session outputs to a new session: + +#### Single Context + +```prose +let research = session "Research quantum computing" + +session "Write summary" + context: research +``` + +#### Multiple Contexts + +```prose +let research = session "Research the topic" +let analysis = session "Analyze the findings" + +session "Write final report" + context: [research, analysis] +``` + +#### Empty Context (Fresh Start) + +Use an empty array to start a session without inherited context: + +```prose +session "Independent task" + context: [] +``` + +#### Object Context Shorthand + +For passing multiple named results (especially from parallel blocks), use object shorthand: + +```prose +parallel: + a = session "Task A" + b = session "Task B" + +session "Combine results" + context: { a, b } +``` + +This is equivalent to passing an object where each property is a variable reference. + +### Complete Example + +```prose +agent researcher: + model: sonnet + prompt: "You are a research assistant" + +agent writer: + model: opus + prompt: "You are a technical writer" + +# Gather research +let research = session: researcher + prompt: "Research quantum computing developments" + +# Analyze findings +let analysis = session: researcher + prompt: "Analyze the key findings" + context: research + +# Write the final report using both contexts +const report = session: writer + prompt: "Write a comprehensive report" + context: [research, analysis] +``` + +### Validation Rules + +| Check | Severity | Message | +| ------------------------------- | -------- | -------------------------------------------------- | +| Duplicate variable name | Error | Variable already defined | +| Const reassignment | Error | Cannot reassign const variable | +| Undefined variable reference | Error | Undefined variable | +| Variable conflicts with agent | Error | Variable name conflicts with agent name | +| Undefined context variable | Error | Undefined variable in context | +| Non-identifier in context array | Error | Context array elements must be variable references | + +### Flat Namespace Requirement + +All variable names must be **unique within a program**. No shadowing is allowed across scopes. + +**This is a compile error:** + +```prose +let result = session "Outer task" + +for item in items: + let result = session "Inner task" # Error: 'result' already defined + context: item +``` + +**Why this constraint:** Since bindings are stored as `bindings/{name}.md`, two variables with the same name would collide on the filesystem. Rather than introduce complex scoping rules, we enforce uniqueness. + +**Collision scenarios this prevents:** +1. Variable inside loop shadows variable outside loop +2. Variables in different `if`/`elif`/`else` branches with same name +3. Block parameters shadowing outer variables +4. Parallel branches reusing outer variable names + +**Exception:** Imported programs run in isolated namespaces. A variable `result` in the main program does not collide with `result` in an imported program (they write to different `imports/{handle}--{slug}/bindings/` directories). + +--- + +## Composition Blocks + +Composition blocks allow you to structure programs into reusable, named units and express sequences of operations inline. + +### do: Block (Anonymous Sequential Block) + +The `do:` keyword creates an explicit sequential block. All statements in the block execute in order. + +#### Syntax + +```prose +do: + statement1 + statement2 + ... +``` + +#### Examples + +```prose +# Explicit sequential block +do: + session "Research the topic" + session "Analyze findings" + session "Write summary" + +# Assign result to a variable +let result = do: + session "Gather data" + session "Process data" +``` + +### Block Definitions + +Named blocks create reusable workflow components. Define once, invoke multiple times. + +#### Syntax + +```prose +block name: + statement1 + statement2 + ... +``` + +#### Invoking Blocks + +Use `do` followed by the block name to invoke a defined block: + +```prose +do blockname +``` + +#### Examples + +```prose +# Define a review pipeline +block review-pipeline: + session "Security review" + session "Performance review" + session "Synthesize reviews" + +# Define another block +block final-check: + session "Final verification" + session "Sign off" + +# Use the blocks +do review-pipeline +session "Make fixes based on review" +do final-check +``` + +### Block Parameters + +Blocks can accept parameters to make them more flexible and reusable. + +#### Syntax + +```prose +block name(param1, param2): + # param1 and param2 are available here + statement1 + statement2 +``` + +#### Invoking with Arguments + +Pass arguments when invoking a parameterized block: + +```prose +do name(arg1, arg2) +``` + +#### Examples + +```prose +# Define a parameterized block +block review(topic): + session "Research {topic} thoroughly" + session "Analyze key findings about {topic}" + session "Summarize {topic} analysis" + +# Invoke with different arguments +do review("quantum computing") +do review("machine learning") +do review("blockchain") +``` + +#### Multiple Parameters + +```prose +block process-item(item, mode): + session "Process {item} using {mode} mode" + session "Verify {item} processing" + +do process-item("data.csv", "strict") +do process-item("config.json", "lenient") +``` + +#### Parameter Scope + +- Parameters are scoped to the block body +- Parameters shadow outer variables of the same name (with warning) +- Parameters are implicitly `const` within the block + +#### Validation Rules + +| Check | Severity | Message | +| ----------------------- | -------- | ---------------------------------------------- | +| Argument count mismatch | Warning | Block expects N parameters but got M arguments | +| Parameter shadows outer | Warning | Parameter shadows outer variable | + +### Inline Sequence (Arrow Operator) + +The `->` operator chains sessions into a sequence on a single line. This is syntactic sugar for sequential execution. + +#### Syntax + +```prose +session "A" -> session "B" -> session "C" +``` + +This is equivalent to: + +```prose +session "A" +session "B" +session "C" +``` + +#### Examples + +```prose +# Quick pipeline +session "Plan" -> session "Execute" -> session "Review" + +# Assign result +let workflow = session "Draft" -> session "Edit" -> session "Finalize" +``` + +### Block Hoisting + +Block definitions are hoisted - you can use a block before it's defined in the source: + +```prose +# Use before definition +do validation-checks + +# Definition comes later +block validation-checks: + session "Check syntax" + session "Check semantics" +``` + +### Nested Composition + +Blocks and do: blocks can be nested: + +```prose +block outer-workflow: + session "Start" + do: + session "Sub-task 1" + session "Sub-task 2" + session "End" + +do: + do outer-workflow + session "Final step" +``` + +### Context with Blocks + +Blocks work with the context system: + +```prose +# Capture do block result +let research = do: + session "Gather information" + session "Analyze patterns" + +# Use in subsequent session +session "Write report" + context: research +``` + +### Validation Rules + +| Check | Severity | Message | +| ------------------------------- | -------- | ------------------------------------ | +| Undefined block reference | Error | Block not defined | +| Duplicate block definition | Error | Block already defined | +| Block name conflicts with agent | Error | Block name conflicts with agent name | +| Empty block name | Error | Block definition must have a name | + +--- + +## Parallel Blocks + +Parallel blocks allow multiple sessions to run concurrently. All branches execute simultaneously, and the block waits for all to complete before continuing. + +### Basic Syntax + +```prose +parallel: + session "Security review" + session "Performance review" + session "Style review" +``` + +All three sessions start at the same time and run concurrently. The program waits for all of them to complete before proceeding. + +### Named Parallel Results + +Capture the results of parallel branches into variables: + +```prose +parallel: + security = session "Security review" + perf = session "Performance review" + style = session "Style review" +``` + +These variables can then be used in subsequent sessions. + +### Object Context Shorthand + +Pass multiple parallel results to a session using object shorthand: + +```prose +parallel: + security = session "Security review" + perf = session "Performance review" + style = session "Style review" + +session "Synthesize all reviews" + context: { security, perf, style } +``` + +The object shorthand `{ a, b, c }` is equivalent to passing an object with properties `a`, `b`, and `c` where each property's value is the corresponding variable. + +### Mixed Composition + +#### Parallel Inside Sequential + +```prose +do: + session "Setup" + parallel: + session "Task A" + session "Task B" + session "Cleanup" +``` + +The setup runs first, then Task A and Task B run in parallel, and finally cleanup runs. + +#### Sequential Inside Parallel + +```prose +parallel: + do: + session "Multi-step task 1a" + session "Multi-step task 1b" + do: + session "Multi-step task 2a" + session "Multi-step task 2b" +``` + +Each parallel branch contains a sequential workflow. The two workflows run concurrently. + +### Assigning Parallel Blocks to Variables + +```prose +let results = parallel: + session "Task A" + session "Task B" +``` + +### Complete Example + +```prose +agent reviewer: + model: sonnet + +# Run parallel reviews +parallel: + sec = session: reviewer + prompt: "Review for security issues" + perf = session: reviewer + prompt: "Review for performance issues" + style = session: reviewer + prompt: "Review for style issues" + +# Combine all reviews +session "Create unified review report" + context: { sec, perf, style } +``` + +### Join Strategies + +By default, parallel blocks wait for all branches to complete. You can specify alternative join strategies: + +#### First (Race) + +Return as soon as the first branch completes, cancel others: + +```prose +parallel ("first"): + session "Try approach A" + session "Try approach B" + session "Try approach C" +``` + +The first successful result wins. Other branches are cancelled. + +#### Any (N of M) + +Return when any N branches complete successfully: + +```prose +# Default: any 1 success +parallel ("any"): + session "Attempt 1" + session "Attempt 2" + +# Specific count: wait for 2 successes +parallel ("any", count: 2): + session "Attempt 1" + session "Attempt 2" + session "Attempt 3" +``` + +#### All (Default) + +Wait for all branches to complete: + +```prose +# Implicit - this is the default +parallel: + session "Task A" + session "Task B" + +# Explicit +parallel ("all"): + session "Task A" + session "Task B" +``` + +### Failure Policies + +Control how the parallel block handles branch failures: + +#### Fail-Fast (Default) + +If any branch fails, fail immediately and cancel other branches: + +```prose +parallel: # Implicit fail-fast + session "Critical task 1" + session "Critical task 2" + +# Explicit +parallel (on-fail: "fail-fast"): + session "Critical task 1" + session "Critical task 2" +``` + +#### Continue + +Let all branches complete, then report all failures: + +```prose +parallel (on-fail: "continue"): + session "Task 1" + session "Task 2" + session "Task 3" + +# Continue regardless of which branches failed +session "Process results, including failures" +``` + +#### Ignore + +Ignore all failures, always succeed: + +```prose +parallel (on-fail: "ignore"): + session "Optional enrichment 1" + session "Optional enrichment 2" + +# This always runs, even if all branches failed +session "Continue regardless" +``` + +### Combining Modifiers + +Join strategies and failure policies can be combined: + +```prose +# Race with resilience +parallel ("first", on-fail: "continue"): + session "Fast but unreliable" + session "Slow but reliable" + +# Get any 2 results, ignoring failures +parallel ("any", count: 2, on-fail: "ignore"): + session "Approach 1" + session "Approach 2" + session "Approach 3" + session "Approach 4" +``` + +### Execution Semantics + +When the OpenProse VM encounters a `parallel:` block: + +1. **Fork**: Start all branches concurrently +2. **Execute**: Each branch runs independently +3. **Join**: Wait according to join strategy: + - `"all"` (default): Wait for all branches + - `"first"`: Return on first completion + - `"any"`: Return on first success (or N successes with `count`) +4. **Handle failures**: According to on-fail policy: + - `"fail-fast"` (default): Cancel remaining and fail immediately + - `"continue"`: Wait for all, then report failures + - `"ignore"`: Treat failures as successes +5. **Continue**: Proceed to the next statement with available results + +### Validation Rules + +| Check | Severity | Message | +| ------------------------------------ | -------- | -------------------------------------------- | +| Invalid join strategy | Error | Must be "all", "first", or "any" | +| Invalid on-fail policy | Error | Must be "fail-fast", "continue", or "ignore" | +| Count without "any" | Error | Count is only valid with "any" strategy | +| Count less than 1 | Error | Count must be at least 1 | +| Count exceeds branches | Warning | Count exceeds number of parallel branches | +| Duplicate variable in parallel | Error | Variable already defined | +| Variable conflicts with agent | Error | Variable name conflicts with agent name | +| Undefined variable in object context | Error | Undefined variable in context | + +--- + +## Fixed Loops + +Fixed loops provide bounded iteration over a set number of times or over a collection. + +### Repeat Block + +The `repeat` block executes its body a fixed number of times. + +#### Basic Syntax + +```prose +repeat 3: + session "Generate a creative idea" +``` + +#### With Index Variable + +Access the current iteration index using `as`: + +```prose +repeat 5 as i: + session "Process item" + context: i +``` + +The index variable `i` is scoped to the loop body and starts at 0. + +### For-Each Block + +The `for` block iterates over a collection. + +#### Basic Syntax + +```prose +let fruits = ["apple", "banana", "cherry"] +for fruit in fruits: + session "Describe this fruit" + context: fruit +``` + +#### With Inline Array + +```prose +for topic in ["AI", "climate", "space"]: + session "Research this topic" + context: topic +``` + +#### With Index Variable + +Access both the item and its index: + +```prose +let items = ["a", "b", "c"] +for item, i in items: + session "Process item with index" + context: [item, i] +``` + +### Parallel For-Each + +The `parallel for` block runs all iterations concurrently (fan-out pattern): + +```prose +let topics = ["AI", "climate", "space"] +parallel for topic in topics: + session "Research this topic" + context: topic + +session "Combine all research" +``` + +This is equivalent to: + +```prose +parallel: + session "Research AI" context: "AI" + session "Research climate" context: "climate" + session "Research space" context: "space" +``` + +But more concise and dynamic. + +### Variable Scoping + +Loop variables are scoped to the loop body: + +- They are implicitly `const` within each iteration +- They shadow outer variables of the same name (with a warning) +- They are not accessible outside the loop + +```prose +let item = session "outer" +for item in ["a", "b"]: + # 'item' here is the loop variable + session "process loop item" + context: item +# 'item' here refers to the outer variable again +session "use outer item" + context: item +``` + +### Nesting + +Loops can be nested: + +```prose +repeat 2: + repeat 3: + session "Inner task" +``` + +Different loop types can be combined: + +```prose +let items = ["a", "b"] +repeat 2: + for item in items: + session "Process item" + context: item +``` + +### Complete Example + +```prose +# Generate multiple variations of ideas +repeat 3: + session "Generate a creative startup idea" + +session "Select the best idea from the options above" + +# Research the selected idea from multiple angles +let angles = ["market", "technology", "competition"] +parallel for angle in angles: + session "Research this angle of the startup idea" + context: angle + +session "Synthesize all research into a business plan" +``` + +### Validation Rules + +| Check | Severity | Message | +| ----------------------------- | -------- | ------------------------------------ | +| Repeat count must be positive | Error | Repeat count must be positive | +| Repeat count must be integer | Error | Repeat count must be an integer | +| Undefined collection variable | Error | Undefined collection variable | +| Loop variable shadows outer | Warning | Loop variable shadows outer variable | + +--- + +## Unbounded Loops + +Unbounded loops provide iteration with AI-evaluated termination conditions. Unlike fixed loops, the iteration count is not known ahead of time - the OpenProse VM evaluates conditions at runtime using its intelligence to determine when to stop. + +### Discretion Markers + +Unbounded loops use **discretion markers** (`**...**`) to wrap AI-evaluated conditions. These markers signal that the enclosed text should be interpreted intelligently by the OpenProse VM at runtime, not as a literal boolean expression. + +```prose +# The text inside **...** is evaluated by the AI +loop until **the poem has vivid imagery and flows smoothly**: + session "Review and improve the poem" +``` + +For multi-line conditions, use triple-asterisks: + +```prose +loop until *** + the document is complete + all sections have been reviewed + and formatting is consistent +***: + session "Continue working on the document" +``` + +### Basic Loop + +The simplest unbounded loop runs indefinitely until explicitly limited: + +```prose +loop: + session "Process next item" +``` + +**Warning**: Loops without termination conditions or max iterations generate a warning. Always include a safety limit: + +```prose +loop (max: 50): + session "Process next item" +``` + +### Loop Until + +The `loop until` variant runs until a condition becomes true: + +```prose +loop until **the task is complete**: + session "Continue working on the task" +``` + +The OpenProse VM evaluates the discretion condition after each iteration and exits when it determines the condition is satisfied. + +### Loop While + +The `loop while` variant runs while a condition remains true: + +```prose +loop while **there are still items to process**: + session "Process the next item" +``` + +Semantically, `loop while **X**` is equivalent to `loop until **not X**`. + +### Iteration Variable + +Track the current iteration number using `as`: + +```prose +loop until **done** as attempt: + session "Try approach" + context: attempt +``` + +The iteration variable: + +- Starts at 0 +- Increments by 1 each iteration +- Is scoped to the loop body +- Is implicitly `const` within each iteration + +### Safety Limits + +Specify maximum iterations with `(max: N)`: + +```prose +# Stop after 10 iterations even if condition not met +loop until **all bugs fixed** (max: 10): + session "Find and fix a bug" +``` + +The loop exits when: + +1. The condition is satisfied (for `until`/`while` variants), OR +2. The maximum iteration count is reached + +### Complete Syntax + +All options can be combined: + +```prose +loop until **condition** (max: N) as i: + body... +``` + +Order matters: condition comes before modifiers, modifiers before `as`. + +### Examples + +#### Iterative Improvement + +```prose +session "Write an initial draft" + +loop until **the draft is polished and ready for review** (max: 5): + session "Review the current draft and identify issues" + session "Revise the draft to address the issues" + +session "Present the final draft" +``` + +#### Debugging Workflow + +```prose +session "Run tests to identify failures" + +loop until **all tests pass** (max: 20) as attempt: + session "Identify the failing test" + session "Fix the bug causing the failure" + session "Run tests again" + +session "Confirm all tests pass and summarize fixes" +``` + +#### Consensus Building + +```prose +parallel: + opinion1 = session "Get first expert opinion" + opinion2 = session "Get second expert opinion" + +loop until **experts have reached consensus** (max: 5): + session "Identify points of disagreement" + context: { opinion1, opinion2 } + session "Facilitate discussion to resolve differences" + +session "Document the final consensus" +``` + +#### Quality Threshold + +```prose +let draft = session "Create initial document" + +loop while **quality score is below threshold** (max: 10): + draft = session "Review and improve the document" + context: draft + session "Calculate new quality score" + +session "Finalize the document" + context: draft +``` + +### Execution Semantics + +When the OpenProse VM encounters an unbounded loop: + +1. **Initialize**: Set iteration counter to 0 +2. **Check Condition** (for `until`/`while`): + - For `until`: Exit if condition is satisfied + - For `while`: Exit if condition is NOT satisfied +3. **Check Limit**: Exit if iteration count >= max iterations +4. **Execute Body**: Run all statements in the loop body +5. **Increment**: Increase iteration counter +6. **Repeat**: Go to step 2 + +For basic `loop:` without conditions: + +- Only the max iteration limit can cause exit +- Without max, the loop runs indefinitely (warning issued) + +### Condition Evaluation + +The OpenProse VM uses its intelligence to evaluate discretion conditions: + +1. **Context Awareness**: The condition is evaluated in the context of what has happened so far in the session +2. **Semantic Understanding**: The condition text is interpreted semantically, not literally +3. **Uncertainty Handling**: When uncertain, the OpenProse VM may: + - Continue iterating if progress is being made + - Exit early if diminishing returns are detected + - Use heuristics based on the condition's semantics + +### Nesting + +Unbounded loops can be nested with other loop types: + +```prose +# Unbounded inside fixed +repeat 3: + loop until **sub-task complete** (max: 10): + session "Work on sub-task" + +# Fixed inside unbounded +loop until **all batches processed** (max: 5): + repeat 3: + session "Process batch item" + +# Multiple unbounded +loop until **outer condition** (max: 5): + loop until **inner condition** (max: 10): + session "Deep iteration" +``` + +### Variable Scoping + +Loop variables follow the same scoping rules as fixed loops: + +```prose +let i = session "outer" +loop until **done** as i: + # 'i' here is the loop variable (shadows outer) + session "use loop i" + context: i +# 'i' here refers to the outer variable again +session "use outer i" + context: i +``` + +### Validation Rules + +| Check | Severity | Message | +| ----------------------------- | -------- | ------------------------------------- | +| Loop without max or condition | Warning | Unbounded loop without max iterations | +| Max iterations <= 0 | Error | Max iterations must be positive | +| Max iterations not integer | Error | Max iterations must be an integer | +| Empty discretion condition | Error | Discretion condition cannot be empty | +| Very short condition | Warning | Discretion condition may be ambiguous | +| Loop variable shadows outer | Warning | Loop variable shadows outer variable | + +--- + +## Pipeline Operations + +Pipeline operations provide functional-style collection transformations. They allow you to chain operations like map, filter, and reduce using the pipe operator (`|`). + +### Pipe Operator + +The pipe operator (`|`) passes a collection to a transformation operation: + +```prose +let items = ["a", "b", "c"] +let results = items | map: + session "Process this item" + context: item +``` + +### Map + +The `map` operation transforms each element in a collection: + +```prose +let articles = ["article1", "article2", "article3"] + +let summaries = articles | map: + session "Summarize this article in one sentence" + context: item +``` + +Inside a map body, the implicit variable `item` refers to the current element being processed. + +### Filter + +The `filter` operation keeps elements that match a condition: + +```prose +let items = ["one", "two", "three", "four", "five"] + +let short = items | filter: + session "Does this word have 4 or fewer letters? Answer yes or no." + context: item +``` + +The session in a filter body should return something the OpenProse VM can interpret as truthy/falsy (like "yes"/"no"). + +### Reduce + +The `reduce` operation accumulates elements into a single result: + +```prose +let ideas = ["AI assistant", "smart home", "health tracker"] + +let combined = ideas | reduce(summary, idea): + session "Add this idea to the summary, creating a cohesive concept" + context: [summary, idea] +``` + +The reduce operation requires explicit variable names: + +- First variable (`summary`): the accumulator +- Second variable (`idea`): the current item + +The first item in the collection becomes the initial accumulator value. + +### Parallel Map (pmap) + +The `pmap` operation is like `map` but runs all transformations concurrently: + +```prose +let tasks = ["task1", "task2", "task3"] + +let results = tasks | pmap: + session "Process this task in parallel" + context: item + +session "Aggregate all results" + context: results +``` + +This is similar to `parallel for`, but in pipeline syntax. + +### Chaining + +Pipeline operations can be chained to compose complex transformations: + +```prose +let topics = ["quantum computing", "blockchain", "machine learning", "IoT"] + +let result = topics + | filter: + session "Is this topic trending? Answer yes or no." + context: item + | map: + session "Write a one-line startup pitch for this topic" + context: item + +session "Present the startup pitches" + context: result +``` + +Operations execute left-to-right: first filter, then map. + +### Complete Example + +```prose +# Define a collection +let articles = ["AI breakthroughs", "Climate solutions", "Space exploration"] + +# Process with chained operations +let summaries = articles + | filter: + session "Is this topic relevant to technology? Answer yes or no." + context: item + | map: + session "Write a compelling one-paragraph summary" + context: item + | reduce(combined, summary): + session "Merge this summary into the combined document" + context: [combined, summary] + +# Present the final result +session "Format and present the combined summaries" + context: summaries +``` + +### Implicit Variables + +| Operation | Available Variables | +| --------- | -------------------------------------------- | +| `map` | `item` - current element | +| `filter` | `item` - current element | +| `pmap` | `item` - current element | +| `reduce` | Named explicitly: `reduce(accVar, itemVar):` | + +### Execution Semantics + +When the OpenProse VM encounters a pipeline: + +1. **Input**: Start with the input collection +2. **For each operation**: + - **map**: Transform each element, producing a new collection + - **filter**: Keep elements where the session returns truthy + - **reduce**: Accumulate elements into a single value + - **pmap**: Transform all elements concurrently +3. **Output**: Return the final transformed collection/value + +### Variable Scoping + +Pipeline variables are scoped to their operation body: + +```prose +let item = "outer" +let items = ["a", "b"] + +let results = items | map: + # 'item' here is the pipeline variable (shadows outer) + session "process" + context: item + +# 'item' here refers to the outer variable again +session "use outer" + context: item +``` + +### Validation Rules + +| Check | Severity | Message | +| ------------------------------- | -------- | -------------------------------------------------- | +| Undefined input collection | Error | Undefined collection variable | +| Invalid pipe operator | Error | Expected pipe operator (map, filter, reduce, pmap) | +| Reduce without variables | Error | Expected accumulator and item variables | +| Pipeline variable shadows outer | Warning | Implicit/explicit variable shadows outer variable | + +--- + +## Error Handling + +OpenProse provides structured error handling with try/catch/finally blocks, throw statements, and retry mechanisms for resilient workflows. + +### Try/Catch Blocks + +The `try:` block wraps operations that might fail. The `catch:` block handles errors. + +```prose +try: + session "Attempt risky operation" +catch: + session "Handle the error gracefully" +``` + +#### Error Variable Access + +Use `catch as err:` to capture error context for the error handler: + +```prose +try: + session "Call external API" +catch as err: + session "Log and handle the error" + context: err +``` + +The error variable (`err`) contains contextual information about what went wrong and is only accessible within the catch block. + +### Try/Catch/Finally + +The `finally:` block always executes, whether the try block succeeds or fails: + +```prose +try: + session "Acquire and use resource" +catch: + session "Handle any errors" +finally: + session "Always clean up resource" +``` + +#### Execution Order + +1. **Try succeeds**: try body → finally body +2. **Try fails**: try body (until failure) → catch body → finally body + +### Try/Finally (No Catch) + +For cleanup without error handling, use try/finally: + +```prose +try: + session "Open connection and do work" +finally: + session "Close connection" +``` + +### Throw Statement + +The `throw` statement raises or re-raises errors. + +#### Rethrow + +Inside a catch block, `throw` without arguments re-raises the caught error to outer handlers: + +```prose +try: + try: + session "Inner operation" + catch: + session "Partial handling" + throw # Re-raise to outer handler +catch: + session "Handle re-raised error" +``` + +#### Throw with Message + +Throw a new error with a custom message: + +```prose +session "Check preconditions" +throw "Precondition not met" +``` + +### Nested Error Handling + +Try blocks can be nested. Inner catch blocks don't trigger outer handlers unless they rethrow: + +```prose +try: + session "Outer operation" + try: + session "Inner risky operation" + catch: + session "Handle inner error" # Outer catch won't run + session "Continue outer operation" +catch: + session "Handle outer error only" +``` + +### Error Handling in Parallel + +Each parallel branch can have its own error handling: + +```prose +parallel: + try: + session "Branch A might fail" + catch: + session "Recover branch A" + try: + session "Branch B might fail" + catch: + session "Recover branch B" + +session "Continue with recovered results" +``` + +This differs from the `on-fail:` policy which controls behavior when unhandled errors occur. + +### Retry Property + +The `retry:` property makes a session automatically retry on failure: + +```prose +session "Call flaky API" + retry: 3 +``` + +#### Retry with Backoff + +Add `backoff:` to control delay between retries: + +```prose +session "Rate-limited API" + retry: 5 + backoff: exponential +``` + +**Backoff Strategies:** + +| Strategy | Behavior | +| ------------- | ---------------------------------- | +| `none` | Immediate retry (default) | +| `linear` | Fixed delay between retries | +| `exponential` | Doubling delay (1s, 2s, 4s, 8s...) | + +#### Retry with Context + +Retry works with other session properties: + +```prose +let data = session "Get input" +session "Process data" + context: data + retry: 3 + backoff: linear +``` + +### Combining Patterns + +Retry and try/catch work together for maximum resilience: + +```prose +try: + session "Call external service" + retry: 3 + backoff: exponential +catch: + session "All retries failed, use fallback" +``` + +### Validation Rules + +| Check | Severity | Message | +| ---------------------------- | -------- | --------------------------------------------------- | +| Try without catch or finally | Error | Try block must have at least "catch:" or "finally:" | +| Error variable shadows outer | Warning | Error variable shadows outer variable | +| Empty throw message | Warning | Throw message is empty | +| Non-positive retry count | Error | Retry count must be positive | +| Non-integer retry count | Error | Retry count must be an integer | +| High retry count (>10) | Warning | Retry count is unusually high | +| Invalid backoff strategy | Error | Must be none, linear, or exponential | +| Retry on agent definition | Warning | Retry property is only valid in session statements | + +### Syntax Reference + +``` +try_block ::= "try" ":" NEWLINE INDENT statement+ DEDENT + [catch_block] + [finally_block] + +catch_block ::= "catch" ["as" identifier] ":" NEWLINE INDENT statement+ DEDENT + +finally_block ::= "finally" ":" NEWLINE INDENT statement+ DEDENT + +throw_statement ::= "throw" [string_literal] + +retry_property ::= "retry" ":" number_literal + +backoff_property ::= "backoff" ":" ( "none" | "linear" | "exponential" ) +``` + +--- + +## Choice Blocks + +Choice blocks allow the OpenProse VM to select from multiple labeled options based on criteria. This is useful for branching workflows where the best path depends on runtime analysis. + +### Syntax + +```prose +choice **criteria**: + option "Label A": + statements... + option "Label B": + statements... +``` + +### Criteria + +The criteria is wrapped in discretion markers (`**...**`) and is evaluated by the OpenProse VM to select which option to execute: + +```prose +choice **the best approach for the current situation**: + option "Quick fix": + session "Apply a quick temporary fix" + option "Full refactor": + session "Perform a complete code refactor" +``` + +### Multi-line Criteria + +For complex criteria, use triple-asterisks: + +```prose +choice *** + which strategy is most appropriate + given the current project constraints + and timeline requirements +***: + option "MVP approach": + session "Build minimum viable product" + option "Full feature set": + session "Build complete feature set" +``` + +### Examples + +#### Simple Choice + +```prose +let analysis = session "Analyze the code quality" + +choice **the severity of issues found in the analysis**: + option "Critical": + session "Stop deployment and fix critical issues" + context: analysis + option "Minor": + session "Log issues for later and proceed" + context: analysis + option "None": + session "Proceed with deployment" +``` + +#### Choice with Multiple Statements per Option + +```prose +choice **the user's experience level**: + option "Beginner": + session "Explain basic concepts first" + session "Provide step-by-step guidance" + session "Include helpful tips and warnings" + option "Expert": + session "Provide concise technical summary" + session "Include advanced configuration options" +``` + +#### Nested Choices + +```prose +choice **the type of request**: + option "Bug report": + choice **the bug severity**: + option "Critical": + session "Escalate immediately" + option "Normal": + session "Add to sprint backlog" + option "Feature request": + session "Add to feature backlog" +``` + +### Execution Semantics + +When the OpenProse VM encounters a `choice` block: + +1. **Evaluate Criteria**: Interpret the discretion criteria in current context +2. **Select Option**: Choose the most appropriate labeled option +3. **Execute**: Run all statements in the selected option's body +4. **Continue**: Proceed to the next statement after the choice block + +Only one option is executed per choice block. + +### Validation Rules + +| Check | Severity | Message | +| ----------------------- | -------- | ------------------------------------------ | +| Choice without options | Error | Choice block must have at least one option | +| Empty criteria | Error | Choice criteria cannot be empty | +| Duplicate option labels | Warning | Duplicate option label | +| Empty option body | Warning | Option has empty body | + +### Syntax Reference + +``` +choice_block ::= "choice" discretion ":" NEWLINE INDENT option+ DEDENT + +option ::= "option" string ":" NEWLINE INDENT statement+ DEDENT + +discretion ::= "**" text "**" | "***" text "***" +``` + +--- + +## Conditional Statements + +If/elif/else statements provide conditional branching based on AI-evaluated conditions using discretion markers. + +### If Statement + +```prose +if **condition**: + statements... +``` + +### If/Else + +```prose +if **condition**: + statements... +else: + statements... +``` + +### If/Elif/Else + +```prose +if **first condition**: + statements... +elif **second condition**: + statements... +elif **third condition**: + statements... +else: + statements... +``` + +### Discretion Conditions + +Conditions are wrapped in discretion markers (`**...**`) for AI evaluation: + +```prose +let analysis = session "Analyze the codebase" + +if **the code has security vulnerabilities**: + session "Fix security issues immediately" + context: analysis +elif **the code has performance issues**: + session "Optimize performance bottlenecks" + context: analysis +else: + session "Proceed with normal review" + context: analysis +``` + +### Multi-line Conditions + +Use triple-asterisks for complex conditions: + +```prose +if *** + the test suite passes + and the code coverage is above 80% + and there are no linting errors +***: + session "Deploy to production" +else: + session "Fix issues before deploying" +``` + +### Examples + +#### Simple If + +```prose +session "Check system health" + +if **the system is healthy**: + session "Continue with normal operations" +``` + +#### If/Else + +```prose +let review = session "Review the pull request" + +if **the code changes are safe and well-tested**: + session "Approve and merge the PR" + context: review +else: + session "Request changes" + context: review +``` + +#### Multiple Elif + +```prose +let status = session "Check project status" + +if **the project is on track**: + session "Continue as planned" +elif **the project is slightly delayed**: + session "Adjust timeline and communicate" +elif **the project is significantly delayed**: + session "Escalate to management" + session "Create recovery plan" +else: + session "Assess project viability" +``` + +#### Nested Conditionals + +```prose +if **the request is authenticated**: + if **the user has admin privileges**: + session "Process admin request" + else: + session "Process standard user request" +else: + session "Return authentication error" +``` + +### Combining with Other Constructs + +#### With Try/Catch + +```prose +try: + session "Attempt operation" + if **operation succeeded partially**: + session "Complete remaining steps" +catch as err: + if **error is recoverable**: + session "Apply recovery procedure" + context: err + else: + throw "Unrecoverable error" +``` + +#### With Loops + +```prose +loop until **task complete** (max: 10): + session "Work on task" + if **encountered blocker**: + session "Resolve blocker" +``` + +### Execution Semantics + +When the OpenProse VM encounters an `if` statement: + +1. **Evaluate Condition**: Interpret the first discretion condition +2. **If True**: Execute the then-body and skip remaining clauses +3. **If False**: Check each `elif` condition in order +4. **Elif Match**: Execute that elif's body and skip remaining +5. **No Match**: Execute the `else` body (if present) +6. **Continue**: Proceed to the next statement + +### Validation Rules + +| Check | Severity | Message | +| --------------- | -------- | --------------------------------- | +| Empty condition | Error | If/elif condition cannot be empty | +| Elif without if | Error | Elif must follow if | +| Else without if | Error | Else must follow if or elif | +| Multiple else | Error | Only one else clause allowed | +| Empty body | Warning | Condition has empty body | + +### Syntax Reference + +``` +if_statement ::= "if" discretion ":" NEWLINE INDENT statement+ DEDENT + elif_clause* + [else_clause] + +elif_clause ::= "elif" discretion ":" NEWLINE INDENT statement+ DEDENT + +else_clause ::= "else" ":" NEWLINE INDENT statement+ DEDENT + +discretion ::= "**" text "**" | "***" text "***" +``` + +--- + +## Execution Model + +OpenProse uses a two-phase execution model. + +### Phase 1: Compilation (Static) + +The compile phase handles deterministic preprocessing: + +1. **Parse**: Convert source code to AST +2. **Validate**: Check for syntax and semantic errors +3. **Expand**: Normalize syntax sugar (when implemented) +4. **Output**: Generate canonical program + +### Phase 2: Runtime (Intelligent) + +The OpenProse VM executes the compiled program: + +1. **Load**: Receive the compiled program +2. **Collect Agents**: Register all agent definitions +3. **Execute**: Process each statement in order +4. **Spawn**: Create subagents with resolved configurations +5. **Coordinate**: Manage context passing between sessions + +### OpenProse VM Behavior + +| Aspect | Behavior | +| -------------------- | ----------------------------------------------- | +| Execution order | Strict - follows program exactly | +| Session creation | Strict - creates what program specifies | +| Agent resolution | Strict - merge properties deterministically | +| Context passing | Intelligent - summarizes/transforms as needed | +| Completion detection | Intelligent - determines when session is "done" | + +### State Management + +For the current implementation, state is tracked in-context (conversation history): + +| State Type | Tracking Approach | +| ------------------- | --------------------------------------------------- | +| Agent definitions | Collected at program start | +| Execution flow | Implicit reasoning ("completed X, now executing Y") | +| Session outputs | Held in conversation history | +| Position in program | Tracked by OpenProse VM | + +--- + +## Validation Rules + +The validator checks programs for errors and warnings before execution. + +### Errors (Block Execution) + +| Code | Description | +| ---- | ----------------------------------- | +| E001 | Unterminated string literal | +| E002 | Unknown escape sequence in string | +| E003 | Session missing prompt or agent | +| E004 | Unexpected token | +| E005 | Invalid syntax | +| E006 | Duplicate agent definition | +| E007 | Undefined agent reference | +| E008 | Invalid model value | +| E009 | Duplicate property | +| E010 | Duplicate use statement | +| E011 | Empty use path | +| E012 | Invalid use path format | +| E013 | Skills must be an array | +| E014 | Skill name must be a string | +| E015 | Permissions must be a block | +| E016 | Permission pattern must be a string | +| E017 | `resume:` requires persistent agent | +| E018 | `resume:` with no existing memory | +| E019 | Duplicate variable name (flat namespace) | +| E020 | Empty input name | +| E021 | Duplicate input declaration | +| E022 | Input after executable statement | +| E023 | Empty output name | +| E024 | Duplicate output declaration | +| E025 | Unknown program in invocation | +| E026 | Missing required input | +| E027 | Unknown input name in invocation | +| E028 | Unknown output property access | + +### Warnings (Non-blocking) + +| Code | Description | +| ---- | ---------------------------------------- | +| W001 | Empty session prompt | +| W002 | Whitespace-only session prompt | +| W003 | Session prompt exceeds 10,000 characters | +| W004 | Empty prompt property | +| W005 | Unknown property name | +| W006 | Unknown import source format | +| W007 | Skill not imported | +| W008 | Unknown permission type | +| W009 | Unknown permission value | +| W010 | Empty skills array | +| W011 | `session:` on persistent agent with existing memory | + +### Error Message Format + +Errors include location information: + +``` +Error at line 5, column 12: Unterminated string literal + session "Hello + ^ +``` + +--- + +## Examples + +### Minimal Program + +```prose +session "Hello world" +``` + +### Research Pipeline with Agents + +```prose +# Define specialized agents +agent researcher: + model: sonnet + prompt: "You are a research assistant" + +agent writer: + model: opus + prompt: "You are a technical writer" + +# Execute workflow +session: researcher + prompt: "Research recent developments in quantum computing" + +session: writer + prompt: "Write a summary of the research findings" +``` + +### Code Review Workflow + +```prose +agent reviewer: + model: sonnet + prompt: "You are an expert code reviewer" + +session: reviewer + prompt: "Read the code in src/ and identify potential bugs" + +session: reviewer + prompt: "Suggest fixes for each bug found" + +session: reviewer + prompt: "Create a summary of all changes needed" +``` + +### Multi-step Task with Model Override + +```prose +agent analyst: + model: haiku + prompt: "You analyze data quickly" + +# Quick initial analysis +session: analyst + prompt: "Scan the data for obvious patterns" + +# Detailed analysis with more powerful model +session: analyst + model: opus + prompt: "Perform deep analysis on the patterns found" +``` + +### Comments for Documentation + +```prose +# Project: Quarterly Report Generator +# Author: Team Lead +# Date: 2024-01-01 + +agent data-collector: + model: sonnet + prompt: "You gather and organize data" + +agent analyst: + model: opus + prompt: "You analyze data and create insights" + +# Step 1: Gather data +session: data-collector + prompt: "Collect all sales data from the past quarter" + +# Step 2: Analysis +session: analyst + prompt: "Perform trend analysis on the collected data" + +# Step 3: Report generation +session: analyst + prompt: "Generate a formatted quarterly report with charts" +``` + +### Workflow with Skills and Permissions + +```prose +# Import external programs +use "@anthropic/web-search" +use "@anthropic/file-writer" as file-writer + +# Define a secure research agent +agent researcher: + model: sonnet + prompt: "You are a research assistant" + skills: ["web-search"] + permissions: + read: ["*.md", "*.txt"] + bash: deny + +# Define a writer agent +agent writer: + model: opus + prompt: "You create documentation" + skills: ["file-writer"] + permissions: + write: ["docs/"] + bash: deny + +# Execute workflow +session: researcher + prompt: "Research AI safety topics" + +session: writer + prompt: "Write a summary document" +``` + +--- + +## Future Features + +All core features through Tier 12 have been implemented. Potential future enhancements: + +### Tier 13: Extended Features + +- Custom functions with return values +- Module system for code organization +- Type annotations for validation +- Async/await patterns for advanced concurrency + +### Tier 14: Tooling + +- Language server protocol (LSP) support +- VS Code extension +- Interactive debugger +- Performance profiling + +--- + +## Syntax Grammar (Implemented) + +``` +program → statement* EOF +statement → useStatement | inputDecl | agentDef | session | resumeStmt + | letBinding | constBinding | assignment | outputBinding + | parallelBlock | repeatBlock | forEachBlock | loopBlock + | tryBlock | choiceBlock | ifStatement | doBlock | blockDef + | throwStatement | comment + +# Program Composition +useStatement → "use" string ( "as" IDENTIFIER )? +inputDecl → "input" IDENTIFIER ":" string +outputBinding → "output" IDENTIFIER "=" expression +programCall → IDENTIFIER "(" ( IDENTIFIER ":" expression )* ")" + +# Definitions +agentDef → "agent" IDENTIFIER ":" NEWLINE INDENT agentProperty* DEDENT +agentProperty → "model:" ( "sonnet" | "opus" | "haiku" ) + | "prompt:" string + | "persist:" ( "true" | "project" | string ) + | "context:" ( IDENTIFIER | array | objectContext ) + | "retry:" NUMBER + | "backoff:" ( "none" | "linear" | "exponential" ) + | "skills:" "[" string* "]" + | "permissions:" NEWLINE INDENT permission* DEDENT +blockDef → "block" IDENTIFIER params? ":" NEWLINE INDENT statement* DEDENT +params → "(" IDENTIFIER ( "," IDENTIFIER )* ")" + +# Control Flow +parallelBlock → "parallel" parallelMods? ":" NEWLINE INDENT parallelBranch* DEDENT +parallelMods → "(" ( joinStrategy | onFail | countMod ) ( "," ( joinStrategy | onFail | countMod ) )* ")" +joinStrategy → string # "all" | "first" | "any" +onFail → "on-fail" ":" string # "fail-fast" | "continue" | "ignore" +countMod → "count" ":" NUMBER # only valid with "any" +parallelBranch → ( IDENTIFIER "=" )? statement + +# Loops +repeatBlock → "repeat" NUMBER ( "as" IDENTIFIER )? ":" NEWLINE INDENT statement* DEDENT +forEachBlock → "parallel"? "for" IDENTIFIER ( "," IDENTIFIER )? "in" collection ":" NEWLINE INDENT statement* DEDENT +loopBlock → "loop" ( ( "until" | "while" ) discretion )? loopMods? ( "as" IDENTIFIER )? ":" NEWLINE INDENT statement* DEDENT +loopMods → "(" "max" ":" NUMBER ")" + +# Error Handling +tryBlock → "try" ":" NEWLINE INDENT statement+ DEDENT catchBlock? finallyBlock? +catchBlock → "catch" ( "as" IDENTIFIER )? ":" NEWLINE INDENT statement+ DEDENT +finallyBlock → "finally" ":" NEWLINE INDENT statement+ DEDENT +throwStatement → "throw" string? + +# Conditionals +choiceBlock → "choice" discretion ":" NEWLINE INDENT choiceOption+ DEDENT +choiceOption → "option" string ":" NEWLINE INDENT statement+ DEDENT +ifStatement → "if" discretion ":" NEWLINE INDENT statement+ DEDENT elifClause* elseClause? +elifClause → "elif" discretion ":" NEWLINE INDENT statement+ DEDENT +elseClause → "else" ":" NEWLINE INDENT statement+ DEDENT + +# Composition +doBlock → "do" ( ":" NEWLINE INDENT statement* DEDENT | IDENTIFIER args? ) +args → "(" expression ( "," expression )* ")" +arrowExpr → session ( "->" session )+ + +# Sessions +session → "session" ( string | ":" IDENTIFIER | IDENTIFIER ":" IDENTIFIER ) + ( NEWLINE INDENT sessionProperty* DEDENT )? +resumeStmt → "resume" ":" IDENTIFIER ( NEWLINE INDENT sessionProperty* DEDENT )? +sessionProperty → "model:" ( "sonnet" | "opus" | "haiku" ) + | "prompt:" string + | "context:" ( IDENTIFIER | array | objectContext ) + | "retry:" NUMBER + | "backoff:" ( "none" | "linear" | "exponential" ) + +# Bindings +letBinding → "let" IDENTIFIER "=" expression +constBinding → "const" IDENTIFIER "=" expression +assignment → IDENTIFIER "=" expression + +# Expressions +expression → session | doBlock | parallelBlock | repeatBlock | forEachBlock + | loopBlock | arrowExpr | pipeExpr | programCall | string | IDENTIFIER | array | objectContext + +# Pipelines +pipeExpr → ( IDENTIFIER | array ) ( "|" pipeOp )+ +pipeOp → ( "map" | "filter" | "pmap" ) ":" NEWLINE INDENT statement* DEDENT + | "reduce" "(" IDENTIFIER "," IDENTIFIER ")" ":" NEWLINE INDENT statement* DEDENT + +# Properties +property → ( "model" | "prompt" | "context" | "retry" | "backoff" | IDENTIFIER ) + ":" ( IDENTIFIER | string | array | objectContext | NUMBER ) + +# Primitives +discretion → "**" text "**" | "***" text "***" +collection → IDENTIFIER | array +array → "[" ( expression ( "," expression )* )? "]" +objectContext → "{" ( IDENTIFIER ( "," IDENTIFIER )* )? "}" +comment → "#" text NEWLINE + +# Strings +string → singleString | tripleString | interpolatedString +singleString → '"' character* '"' +tripleString → '"""' ( character | NEWLINE )* '"""' +interpolatedString → string containing "{" IDENTIFIER "}" +character → escape | non-quote +escape → "\\" | "\"" | "\n" | "\t" +``` + +--- + +## Compiler API + +When a user invokes `/prose-compile` or asks you to compile a `.prose` file: + +1. **Read this document** (`compiler.md`) fully to understand all syntax and validation rules +2. **Parse** the program according to the syntax grammar +3. **Validate** syntax correctness, semantic validity, and self-evidence +4. **Transform** to canonical form (expand syntax sugar, normalize structure) +5. **Output** the compiled program or report errors/warnings with line numbers + +For direct interpretation without compilation, read `prose.md` and execute statements as described in the Session Statement section. diff --git a/extensions/open-prose/skills/prose/examples/01-hello-world.prose b/extensions/open-prose/skills/prose/examples/01-hello-world.prose new file mode 100644 index 000000000..274ce1480 --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/01-hello-world.prose @@ -0,0 +1,4 @@ +# Hello World +# The simplest OpenProse program - a single session + +session "Say hello and briefly introduce yourself" diff --git a/extensions/open-prose/skills/prose/examples/02-research-and-summarize.prose b/extensions/open-prose/skills/prose/examples/02-research-and-summarize.prose new file mode 100644 index 000000000..309222e78 --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/02-research-and-summarize.prose @@ -0,0 +1,6 @@ +# Research and Summarize +# A two-step workflow: research a topic, then summarize findings + +session "Research the latest developments in AI agents and multi-agent systems. Focus on papers and announcements from the past 6 months." + +session "Summarize the key findings from your research in 5 bullet points. Focus on practical implications for developers." diff --git a/extensions/open-prose/skills/prose/examples/03-code-review.prose b/extensions/open-prose/skills/prose/examples/03-code-review.prose new file mode 100644 index 000000000..d0b714e2d --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/03-code-review.prose @@ -0,0 +1,17 @@ +# Code Review Pipeline +# Review code from multiple perspectives sequentially + +# First, understand what the code does +session "Read the files in src/ and provide a brief overview of the codebase structure and purpose." + +# Security review +session "Review the code for security vulnerabilities. Look for injection risks, authentication issues, and data exposure." + +# Performance review +session "Review the code for performance issues. Look for N+1 queries, unnecessary allocations, and blocking operations." + +# Maintainability review +session "Review the code for maintainability. Look for code duplication, unclear naming, and missing documentation." + +# Synthesize findings +session "Create a unified code review report combining all the findings above. Prioritize issues by severity and provide actionable recommendations." diff --git a/extensions/open-prose/skills/prose/examples/04-write-and-refine.prose b/extensions/open-prose/skills/prose/examples/04-write-and-refine.prose new file mode 100644 index 000000000..0614a26c5 --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/04-write-and-refine.prose @@ -0,0 +1,14 @@ +# Write and Refine +# Draft content, then iteratively improve it + +# Create initial draft +session "Write a first draft of a README.md for this project. Include sections for: overview, installation, usage, and contributing." + +# Self-review and improve +session "Review the README draft you just wrote. Identify areas that are unclear, too verbose, or missing important details." + +# Apply improvements +session "Rewrite the README incorporating your review feedback. Make it more concise and add any missing sections." + +# Final polish +session "Do a final pass on the README. Fix any typos, improve formatting, and ensure code examples are correct." diff --git a/extensions/open-prose/skills/prose/examples/05-debug-issue.prose b/extensions/open-prose/skills/prose/examples/05-debug-issue.prose new file mode 100644 index 000000000..f5cf2924f --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/05-debug-issue.prose @@ -0,0 +1,20 @@ +# Debug an Issue +# Step-by-step debugging workflow + +# Understand the problem +session "Read the error message and stack trace. Identify which file and function is causing the issue." + +# Gather context +session "Read the relevant source files and understand the code flow that leads to the error." + +# Form hypothesis +session "Based on your investigation, form a hypothesis about what's causing the bug. List 2-3 possible root causes." + +# Test hypothesis +session "Write a test case that reproduces the bug. This will help verify the fix later." + +# Implement fix +session "Implement a fix for the most likely root cause. Explain your changes." + +# Verify fix +session "Run the test suite to verify the fix works and doesn't break anything else." diff --git a/extensions/open-prose/skills/prose/examples/06-explain-codebase.prose b/extensions/open-prose/skills/prose/examples/06-explain-codebase.prose new file mode 100644 index 000000000..26a62421f --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/06-explain-codebase.prose @@ -0,0 +1,17 @@ +# Explain Codebase +# Progressive exploration of an unfamiliar codebase + +# Start with the big picture +session "List all directories and key files in this repository. Provide a high-level map of the project structure." + +# Understand the entry point +session "Find the main entry point of the application. Explain how the program starts and initializes." + +# Trace a key flow +session "Trace through a typical user request from start to finish. Document the key functions and modules involved." + +# Document architecture +session "Based on your exploration, write a brief architecture document explaining how the major components fit together." + +# Identify patterns +session "What design patterns and conventions does this codebase use? Document any patterns future contributors should follow." diff --git a/extensions/open-prose/skills/prose/examples/07-refactor.prose b/extensions/open-prose/skills/prose/examples/07-refactor.prose new file mode 100644 index 000000000..bebe6d692 --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/07-refactor.prose @@ -0,0 +1,20 @@ +# Refactor Code +# Systematic refactoring workflow + +# Assess current state +session "Analyze the target code and identify code smells: duplication, long functions, unclear naming, tight coupling." + +# Plan refactoring +session "Create a refactoring plan. List specific changes in order of priority, starting with the safest changes." + +# Ensure test coverage +session "Check test coverage for the code being refactored. Add any missing tests before making changes." + +# Execute refactoring +session "Implement the first refactoring from your plan. Make a single focused change." + +# Verify behavior +session "Run tests to verify the refactoring preserved behavior. If tests fail, investigate and fix." + +# Document changes +session "Update any documentation affected by the refactoring. Add comments explaining non-obvious design decisions." diff --git a/extensions/open-prose/skills/prose/examples/08-blog-post.prose b/extensions/open-prose/skills/prose/examples/08-blog-post.prose new file mode 100644 index 000000000..fd1312459 --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/08-blog-post.prose @@ -0,0 +1,20 @@ +# Write a Blog Post +# End-to-end content creation workflow + +# Research the topic +session "Research the topic: 'Best practices for error handling in TypeScript'. Find authoritative sources and common patterns." + +# Create outline +session "Create a detailed outline for the blog post. Include introduction, 4-5 main sections, and conclusion." + +# Write first draft +session "Write the full blog post following the outline. Target 1500-2000 words. Include code examples." + +# Technical review +session "Review the blog post for technical accuracy. Verify all code examples compile and work correctly." + +# Editorial review +session "Review the blog post for clarity and readability. Simplify complex sentences and improve flow." + +# Add finishing touches +session "Add a compelling title, meta description, and suggest 3-5 relevant tags for the post." diff --git a/extensions/open-prose/skills/prose/examples/09-research-with-agents.prose b/extensions/open-prose/skills/prose/examples/09-research-with-agents.prose new file mode 100644 index 000000000..e421ff37a --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/09-research-with-agents.prose @@ -0,0 +1,25 @@ +# Research Pipeline with Specialized Agents +# This example demonstrates defining agents with different models +# and using them in sessions with property overrides. + +# Define specialized agents +agent researcher: + model: sonnet + prompt: "You are a research assistant skilled at finding and synthesizing information" + +agent writer: + model: opus + prompt: "You are a technical writer who creates clear, concise documentation" + +# Step 1: Initial research with the researcher agent +session: researcher + prompt: "Research recent developments in renewable energy storage technologies" + +# Step 2: Deep dive with a more powerful model +session: researcher + model: opus + prompt: "Analyze the top 3 most promising battery technologies and their potential impact" + +# Step 3: Write up the findings +session: writer + prompt: "Create a summary report of the research findings suitable for executives" diff --git a/extensions/open-prose/skills/prose/examples/10-code-review-agents.prose b/extensions/open-prose/skills/prose/examples/10-code-review-agents.prose new file mode 100644 index 000000000..04e359cac --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/10-code-review-agents.prose @@ -0,0 +1,32 @@ +# Code Review Workflow with Agents +# This example shows how to use agents for a multi-step code review process. + +# Define agents with specific roles +agent security-reviewer: + model: opus + prompt: "You are a security expert focused on identifying vulnerabilities" + +agent performance-reviewer: + model: sonnet + prompt: "You are a performance optimization specialist" + +agent style-reviewer: + model: haiku + prompt: "You check for code style and best practices" + +# Step 1: Quick style check (fast) +session: style-reviewer + prompt: "Review the code in src/ for style issues and naming conventions" + +# Step 2: Performance analysis (medium) +session: performance-reviewer + prompt: "Identify any performance bottlenecks or optimization opportunities" + +# Step 3: Security audit (thorough) +session: security-reviewer + prompt: "Perform a security review looking for OWASP top 10 vulnerabilities" + +# Step 4: Summary +session: security-reviewer + model: sonnet + prompt: "Create a consolidated report of all review findings with priority rankings" diff --git a/extensions/open-prose/skills/prose/examples/11-skills-and-imports.prose b/extensions/open-prose/skills/prose/examples/11-skills-and-imports.prose new file mode 100644 index 000000000..423d8442e --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/11-skills-and-imports.prose @@ -0,0 +1,27 @@ +# Skills and Imports Example +# This demonstrates importing external skills and assigning them to agents. + +# Import skills from external sources +import "web-search" from "github:anthropic/skills" +import "summarizer" from "npm:@example/summarizer" +import "file-reader" from "./local-skills/file-reader" + +# Define a research agent with web search capability +agent researcher: + model: sonnet + prompt: "You are a research assistant skilled at finding information" + skills: ["web-search", "summarizer"] + +# Define a documentation agent with file access +agent documenter: + model: opus + prompt: "You create comprehensive documentation" + skills: ["file-reader", "summarizer"] + +# Research phase +session: researcher + prompt: "Search for recent developments in renewable energy storage" + +# Documentation phase +session: documenter + prompt: "Create a technical summary of the research findings" diff --git a/extensions/open-prose/skills/prose/examples/12-secure-agent-permissions.prose b/extensions/open-prose/skills/prose/examples/12-secure-agent-permissions.prose new file mode 100644 index 000000000..2d8e44200 --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/12-secure-agent-permissions.prose @@ -0,0 +1,43 @@ +# Secure Agent with Permissions Example +# This demonstrates defining agents with restricted access permissions. + +# Import required skills +import "code-analyzer" from "github:anthropic/code-tools" + +# Define a read-only code reviewer +# This agent can read source files but cannot modify them or run shell commands +agent code-reviewer: + model: sonnet + prompt: "You are a thorough code reviewer" + skills: ["code-analyzer"] + permissions: + read: ["src/**/*.ts", "src/**/*.js", "*.md"] + write: [] + bash: deny + +# Define a documentation writer with limited write access +# Can only write to docs directory +agent doc-writer: + model: opus + prompt: "You write technical documentation" + permissions: + read: ["src/**/*", "docs/**/*"] + write: ["docs/**/*.md"] + bash: deny + +# Define a full-access admin agent +agent admin: + model: opus + prompt: "You perform administrative tasks" + permissions: + read: ["**/*"] + write: ["**/*"] + bash: prompt + network: allow + +# Workflow: Code review followed by documentation update +session: code-reviewer + prompt: "Review the codebase for security issues and best practices" + +session: doc-writer + prompt: "Update the documentation based on the code review findings" diff --git a/extensions/open-prose/skills/prose/examples/13-variables-and-context.prose b/extensions/open-prose/skills/prose/examples/13-variables-and-context.prose new file mode 100644 index 000000000..0fbd8dad1 --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/13-variables-and-context.prose @@ -0,0 +1,51 @@ +# Example 13: Variables & Context +# +# This example demonstrates using let/const bindings to capture session +# outputs and pass them as context to subsequent sessions. + +# Define specialized agents for the workflow +agent researcher: + model: sonnet + prompt: "You are a thorough research assistant who gathers comprehensive information on topics." + +agent analyst: + model: opus + prompt: "You are a data analyst who identifies patterns, trends, and key insights." + +agent writer: + model: opus + prompt: "You are a technical writer who creates clear, well-structured documents." + +# Step 1: Gather initial research (captured in a variable) +let research = session: researcher + prompt: "Research the current state of quantum computing, including recent breakthroughs, major players, and potential applications." + +# Step 2: Analyze the research findings (using research as context) +let analysis = session: analyst + prompt: "Analyze the key findings and identify the most promising directions." + context: research + +# Step 3: Get additional perspectives (refreshing context) +let market-trends = session: researcher + prompt: "Research market trends and commercial applications of quantum computing." + context: [] + +# Step 4: Combine multiple contexts for final synthesis +const report = session: writer + prompt: "Write a comprehensive executive summary covering research, analysis, and market trends." + context: [research, analysis, market-trends] + +# Step 5: Iterative refinement with variable reassignment +let draft = session: writer + prompt: "Create an initial draft of the technical deep-dive section." + context: research + +# Refine the draft using its own output as context +draft = session: writer + prompt: "Review and improve this draft for clarity and technical accuracy." + context: draft + +# Final polish +draft = session: writer + prompt: "Perform final editorial review and polish the document." + context: draft diff --git a/extensions/open-prose/skills/prose/examples/14-composition-blocks.prose b/extensions/open-prose/skills/prose/examples/14-composition-blocks.prose new file mode 100644 index 000000000..3b23d4ab8 --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/14-composition-blocks.prose @@ -0,0 +1,48 @@ +# Example 14: Composition Blocks +# Demonstrates do: blocks, block definitions, and inline sequences + +# Define reusable agents +agent researcher: + model: sonnet + prompt: "You are a thorough research assistant" + +agent writer: + model: opus + prompt: "You are a skilled technical writer" + +agent reviewer: + model: sonnet + prompt: "You are a careful code and document reviewer" + +# Define a reusable research block +block research-phase: + session: researcher + prompt: "Gather information on the topic" + session: researcher + prompt: "Analyze key findings" + +# Define a reusable writing block +block writing-phase: + session: writer + prompt: "Write initial draft" + session: writer + prompt: "Polish and refine the draft" + +# Define a review block +block review-cycle: + session: reviewer + prompt: "Review for accuracy" + session: reviewer + prompt: "Review for clarity" + +# Main workflow using blocks +let research = do research-phase + +let document = do writing-phase + +do review-cycle + +# Use anonymous do block for final steps +do: + session "Incorporate review feedback" + session "Prepare final version" diff --git a/extensions/open-prose/skills/prose/examples/15-inline-sequences.prose b/extensions/open-prose/skills/prose/examples/15-inline-sequences.prose new file mode 100644 index 000000000..cf43cecb4 --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/15-inline-sequences.prose @@ -0,0 +1,23 @@ +# Example 15: Inline Sequences +# Demonstrates the -> operator for chaining sessions + +# Quick pipeline using arrow syntax +session "Plan the task" -> session "Execute the plan" -> session "Review results" + +# Inline sequence with context capture +let analysis = session "Analyze data" -> session "Draw conclusions" + +session "Write report" + context: analysis + +# Combine inline sequences with blocks +block quick-check: + session "Security scan" -> session "Performance check" + +do quick-check + +# Use inline sequence in variable assignment +let workflow = session "Step 1" -> session "Step 2" -> session "Step 3" + +session "Final step" + context: workflow diff --git a/extensions/open-prose/skills/prose/examples/16-parallel-reviews.prose b/extensions/open-prose/skills/prose/examples/16-parallel-reviews.prose new file mode 100644 index 000000000..252f47cd2 --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/16-parallel-reviews.prose @@ -0,0 +1,19 @@ +# Parallel Code Reviews +# Run multiple specialized reviews concurrently + +agent reviewer: + model: sonnet + prompt: "You are an expert code reviewer" + +# Run all reviews in parallel +parallel: + security = session: reviewer + prompt: "Review for security vulnerabilities" + perf = session: reviewer + prompt: "Review for performance issues" + style = session: reviewer + prompt: "Review for code style and readability" + +# Synthesize all review results +session "Create unified code review report" + context: { security, perf, style } diff --git a/extensions/open-prose/skills/prose/examples/17-parallel-research.prose b/extensions/open-prose/skills/prose/examples/17-parallel-research.prose new file mode 100644 index 000000000..5dce9f7d2 --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/17-parallel-research.prose @@ -0,0 +1,19 @@ +# Parallel Research +# Gather information from multiple sources concurrently + +agent researcher: + model: sonnet + prompt: "You are a research assistant" + +# Research multiple aspects in parallel +parallel: + history = session: researcher + prompt: "Research the historical background" + current = session: researcher + prompt: "Research the current state of the field" + future = session: researcher + prompt: "Research future trends and predictions" + +# Combine all research +session "Write comprehensive research summary" + context: { history, current, future } diff --git a/extensions/open-prose/skills/prose/examples/18-mixed-parallel-sequential.prose b/extensions/open-prose/skills/prose/examples/18-mixed-parallel-sequential.prose new file mode 100644 index 000000000..5486128ec --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/18-mixed-parallel-sequential.prose @@ -0,0 +1,36 @@ +# Mixed Parallel and Sequential Workflow +# Demonstrates nesting parallel and sequential blocks + +agent worker: + model: sonnet + +# Define reusable blocks +block setup: + session "Initialize resources" + session "Validate configuration" + +block cleanup: + session "Save results" + session "Release resources" + +# Main workflow with mixed composition +do: + do setup + + # Parallel processing phase + parallel: + # Each parallel branch can have multiple steps + do: + session: worker + prompt: "Process batch 1 - step 1" + session: worker + prompt: "Process batch 1 - step 2" + do: + session: worker + prompt: "Process batch 2 - step 1" + session: worker + prompt: "Process batch 2 - step 2" + + session "Aggregate results" + + do cleanup diff --git a/extensions/open-prose/skills/prose/examples/19-advanced-parallel.prose b/extensions/open-prose/skills/prose/examples/19-advanced-parallel.prose new file mode 100644 index 000000000..9ae69dc51 --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/19-advanced-parallel.prose @@ -0,0 +1,71 @@ +# Advanced Parallel Execution (Tier 7) +# +# Demonstrates join strategies and failure policies +# for parallel blocks. + +agent researcher: + model: haiku + prompt: "You are a research assistant. Provide concise information." + +# 1. Race Pattern: First to Complete Wins +# ---------------------------------------- +# Use parallel ("first") when you want the fastest result +# and don't need all branches to complete. + +parallel ("first"): + session: researcher + prompt: "Find information via approach A" + session: researcher + prompt: "Find information via approach B" + session: researcher + prompt: "Find information via approach C" + +session "Summarize: only the fastest approach completed" + +# 2. Any-N Pattern: Get Multiple Quick Results +# -------------------------------------------- +# Use parallel ("any", count: N) when you need N results +# but not necessarily all of them. + +parallel ("any", count: 2): + a = session "Generate a creative headline for a tech blog" + b = session "Generate a catchy headline for a tech blog" + c = session "Generate an engaging headline for a tech blog" + d = session "Generate a viral headline for a tech blog" + +session "Choose the best from the 2 headlines that finished first" + context: { a, b, c, d } + +# 3. Continue on Failure: Gather All Results +# ------------------------------------------ +# Use on-fail: "continue" when you want all branches +# to complete and handle failures afterwards. + +parallel (on-fail: "continue"): + session "Fetch data from primary API" + session "Fetch data from secondary API" + session "Fetch data from backup API" + +session "Combine all available data, noting any failures" + +# 4. Ignore Failures: Best-Effort Enrichment +# ------------------------------------------ +# Use on-fail: "ignore" for optional enrichments +# where failures shouldn't block progress. + +parallel (on-fail: "ignore"): + session "Get optional metadata enrichment 1" + session "Get optional metadata enrichment 2" + session "Get optional metadata enrichment 3" + +session "Continue with whatever enrichments succeeded" + +# 5. Combined: Race with Resilience +# --------------------------------- +# Combine join strategies with failure policies. + +parallel ("first", on-fail: "continue"): + session "Fast but might fail" + session "Slow but reliable" + +session "Got the first result, even if it was a handled failure" diff --git a/extensions/open-prose/skills/prose/examples/20-fixed-loops.prose b/extensions/open-prose/skills/prose/examples/20-fixed-loops.prose new file mode 100644 index 000000000..cc7c1f581 --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/20-fixed-loops.prose @@ -0,0 +1,20 @@ +# Example: Fixed Loops in OpenProse +# Demonstrates repeat, for-each, and parallel for-each patterns + +# Repeat block - generate multiple ideas +repeat 3: + session "Generate a creative app idea" + +# For-each block - iterate over a collection +let features = ["authentication", "dashboard", "notifications"] +for feature in features: + session "Design the user interface for this feature" + context: feature + +# Parallel for-each - research in parallel +let topics = ["market size", "competitors", "technology stack"] +parallel for topic in topics: + session "Research this aspect of the startup idea" + context: topic + +session "Synthesize all research into a business plan" diff --git a/extensions/open-prose/skills/prose/examples/21-pipeline-operations.prose b/extensions/open-prose/skills/prose/examples/21-pipeline-operations.prose new file mode 100644 index 000000000..99a979519 --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/21-pipeline-operations.prose @@ -0,0 +1,35 @@ +# Pipeline Operations Example +# Demonstrates functional-style collection transformations + +# Define a collection of startup ideas +let ideas = ["AI tutor", "smart garden", "fitness tracker", "meal planner", "travel assistant"] + +# Filter to keep only tech-focused ideas +let tech_ideas = ideas | filter: + session "Is this idea primarily technology-focused? Answer yes or no." + context: item + +# Map to expand each idea into a business pitch +let pitches = tech_ideas | map: + session "Write a compelling one-paragraph business pitch for this idea" + context: item + +# Reduce all pitches into a portfolio summary +let portfolio = pitches | reduce(summary, pitch): + session "Integrate this pitch into the portfolio summary, maintaining coherence" + context: [summary, pitch] + +# Present the final portfolio +session "Format and present the startup portfolio as a polished document" + context: portfolio + +# Parallel map example - research multiple topics concurrently +let topics = ["market analysis", "competition", "funding options"] + +let research = topics | pmap: + session "Research this aspect of the startup portfolio" + context: item + +# Final synthesis +session "Create an executive summary combining all research findings" + context: research diff --git a/extensions/open-prose/skills/prose/examples/22-error-handling.prose b/extensions/open-prose/skills/prose/examples/22-error-handling.prose new file mode 100644 index 000000000..97d54a95e --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/22-error-handling.prose @@ -0,0 +1,51 @@ +# Error Handling Example +# Demonstrates try/catch/finally patterns for resilient workflows + +# Basic try/catch for error recovery +try: + session "Attempt to fetch data from external API" +catch: + session "API failed - use cached data instead" + +# Catch with error variable for context-aware handling +try: + session "Parse and validate complex configuration file" +catch as err: + session "Handle the configuration error" + context: err + +# Try/catch/finally for resource cleanup +try: + session "Open database connection and perform queries" +catch: + session "Log database error and notify admin" +finally: + session "Ensure database connection is properly closed" + +# Nested error handling +try: + session "Start outer transaction" + try: + session "Perform risky inner operation" + catch: + session "Recover inner operation" + throw # Re-raise to outer handler +catch: + session "Handle re-raised error at outer level" + +# Error handling in parallel blocks +parallel: + try: + session "Service A - might fail" + catch: + session "Fallback for Service A" + try: + session "Service B - might fail" + catch: + session "Fallback for Service B" + +session "Continue with whatever results we got" + +# Throwing custom errors +session "Validate input data" +throw "Validation failed: missing required fields" diff --git a/extensions/open-prose/skills/prose/examples/23-retry-with-backoff.prose b/extensions/open-prose/skills/prose/examples/23-retry-with-backoff.prose new file mode 100644 index 000000000..eb8748868 --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/23-retry-with-backoff.prose @@ -0,0 +1,63 @@ +# Retry with Backoff Example +# Demonstrates automatic retry patterns for resilient API calls + +# Simple retry - try up to 3 times on failure +session "Call flaky third-party API" + retry: 3 + +# Retry with exponential backoff for rate-limited APIs +session "Query rate-limited service" + retry: 5 + backoff: "exponential" + +# Retry with linear backoff +session "Send webhook notification" + retry: 3 + backoff: "linear" + +# Combining retry with context passing +let config = session "Load API configuration" + +session "Make authenticated API request" + context: config + retry: 3 + backoff: "exponential" + +# Retry inside try/catch for fallback after all retries fail +try: + session "Call primary payment processor" + retry: 3 + backoff: "exponential" +catch: + session "All retries failed - use backup payment processor" + retry: 2 + +# Parallel retries for redundant services +parallel: + primary = try: + session "Query primary database" + retry: 2 + backoff: "linear" + catch: + session "Primary DB unavailable" + replica = try: + session "Query replica database" + retry: 2 + backoff: "linear" + catch: + session "Replica DB unavailable" + +session "Merge results from available databases" + context: { primary, replica } + +# Retry in a loop for batch processing +let items = ["batch1", "batch2", "batch3"] +for item in items: + try: + session "Process this batch item" + context: item + retry: 2 + backoff: "exponential" + catch: + session "Log failed batch for manual review" + context: item diff --git a/extensions/open-prose/skills/prose/examples/24-choice-blocks.prose b/extensions/open-prose/skills/prose/examples/24-choice-blocks.prose new file mode 100644 index 000000000..7d33a2f17 --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/24-choice-blocks.prose @@ -0,0 +1,86 @@ +# Choice Blocks Example +# Demonstrates AI-selected branching based on runtime criteria + +# Simple choice based on analysis +let analysis = session "Analyze the current codebase quality" + +choice **the severity of issues found**: + option "Critical": + session "Stop all work and fix critical issues immediately" + context: analysis + session "Create incident report" + option "Moderate": + session "Schedule fixes for next sprint" + context: analysis + option "Minor": + session "Add to technical debt backlog" + context: analysis + +# Choice for user experience level +choice **the user's technical expertise based on their question**: + option "Beginner": + session "Explain concepts from first principles" + session "Provide step-by-step tutorial" + session "Include helpful analogies" + option "Intermediate": + session "Give concise explanation with examples" + session "Link to relevant documentation" + option "Expert": + session "Provide technical deep-dive" + session "Include advanced configuration options" + +# Choice for project approach +let requirements = session "Gather project requirements" + +choice **the best development approach given the requirements**: + option "Rapid prototype": + session "Create quick MVP focusing on core features" + context: requirements + session "Plan iteration cycle" + option "Production-ready": + session "Design complete architecture" + context: requirements + session "Set up CI/CD pipeline" + session "Implement with full test coverage" + option "Research spike": + session "Explore technical feasibility" + context: requirements + session "Document findings and recommendations" + +# Multi-line criteria for complex decisions +let market_data = session "Gather market research data" +let tech_analysis = session "Analyze technical landscape" + +choice *** + the optimal market entry strategy + considering both market conditions + and technical readiness +***: + option "Aggressive launch": + session "Prepare for immediate market entry" + context: [market_data, tech_analysis] + option "Soft launch": + session "Plan limited beta release" + context: [market_data, tech_analysis] + option "Wait and iterate": + session "Continue development and monitor market" + context: [market_data, tech_analysis] + +# Nested choices for detailed decision trees +let request = session "Analyze incoming customer request" + +choice **the type of request**: + option "Technical support": + choice **the complexity of the technical issue**: + option "Simple": + session "Provide self-service solution" + context: request + option "Complex": + session "Escalate to senior engineer" + context: request + option "Sales inquiry": + session "Forward to sales team with context" + context: request + option "Feature request": + session "Add to product backlog and notify PM" + context: request diff --git a/extensions/open-prose/skills/prose/examples/25-conditionals.prose b/extensions/open-prose/skills/prose/examples/25-conditionals.prose new file mode 100644 index 000000000..d63c2da7f --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/25-conditionals.prose @@ -0,0 +1,114 @@ +# Conditionals Example +# Demonstrates if/elif/else patterns with AI-evaluated conditions + +# Simple if statement +let health_check = session "Check system health status" + +if **the system is unhealthy**: + session "Alert on-call engineer" + context: health_check + session "Begin incident response" + +# If/else for binary decisions +let review = session "Review the pull request changes" + +if **the code changes are safe and well-tested**: + session "Approve and merge the pull request" + context: review +else: + session "Request changes with detailed feedback" + context: review + +# If/elif/else for multiple conditions +let status = session "Check project milestone status" + +if **the project is ahead of schedule**: + session "Document success factors" + session "Consider adding stretch goals" +elif **the project is on track**: + session "Continue with current plan" + session "Prepare status report" +elif **the project is slightly delayed**: + session "Identify bottlenecks" + session "Adjust timeline and communicate to stakeholders" +else: + session "Escalate to management" + session "Create recovery plan" + session "Schedule daily standups" + +# Multi-line conditions +let test_results = session "Run full test suite" + +if *** + all tests pass + and code coverage is above 80% + and there are no linting errors +***: + session "Deploy to production" +else: + session "Fix issues before deploying" + context: test_results + +# Nested conditionals +let request = session "Analyze the API request" + +if **the request is authenticated**: + if **the user has admin privileges**: + session "Process admin request with full access" + context: request + else: + session "Process standard user request" + context: request +else: + session "Return 401 authentication error" + +# Conditionals with error handling +let operation_result = session "Attempt complex operation" + +if **the operation succeeded partially**: + session "Complete remaining steps" + context: operation_result + +try: + session "Perform another risky operation" +catch as err: + if **the error is recoverable**: + session "Apply automatic recovery procedure" + context: err + else: + throw "Unrecoverable error encountered" + +# Conditionals inside loops +let items = ["item1", "item2", "item3"] + +for item in items: + session "Analyze this item" + context: item + + if **the item needs processing**: + session "Process the item" + context: item + elif **the item should be skipped**: + session "Log skip reason" + context: item + else: + session "Archive the item" + context: item + +# Conditionals with parallel blocks +parallel: + security = session "Run security scan" + performance = session "Run performance tests" + style = session "Run style checks" + +if **security issues were found**: + session "Fix security issues immediately" + context: security +elif **performance issues were found**: + session "Optimize performance bottlenecks" + context: performance +elif **style issues were found**: + session "Clean up code style" + context: style +else: + session "All checks passed - ready for review" diff --git a/extensions/open-prose/skills/prose/examples/26-parameterized-blocks.prose b/extensions/open-prose/skills/prose/examples/26-parameterized-blocks.prose new file mode 100644 index 000000000..78069a560 --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/26-parameterized-blocks.prose @@ -0,0 +1,100 @@ +# Parameterized Blocks Example +# Demonstrates reusable blocks with arguments for DRY workflows + +# Simple parameterized block +block research(topic): + session "Research {topic} thoroughly" + session "Summarize key findings about {topic}" + session "List open questions about {topic}" + +# Invoke with different arguments +do research("quantum computing") +do research("machine learning") +do research("blockchain technology") + +# Block with multiple parameters +block review_code(language, focus_area): + session "Review the {language} code for {focus_area} issues" + session "Suggest {focus_area} improvements for {language}" + session "Provide {language} best practices for {focus_area}" + +do review_code("Python", "performance") +do review_code("TypeScript", "type safety") +do review_code("Rust", "memory safety") + +# Parameterized block for data processing +block process_dataset(source, format): + session "Load data from {source}" + session "Validate {format} structure" + session "Transform to standard format" + session "Generate quality report for {source} data" + +do process_dataset("sales_db", "CSV") +do process_dataset("api_logs", "JSON") +do process_dataset("user_events", "Parquet") + +# Blocks with parameters used in control flow +block test_feature(feature_name, test_level): + session "Write {test_level} tests for {feature_name}" + + if **the tests reveal issues**: + session "Fix issues in {feature_name}" + session "Re-run {test_level} tests for {feature_name}" + else: + session "Mark {feature_name} {test_level} testing complete" + +do test_feature("authentication", "unit") +do test_feature("payment processing", "integration") +do test_feature("user dashboard", "e2e") + +# Parameterized blocks in parallel +block analyze_competitor(company): + session "Research {company} products" + session "Analyze {company} market position" + session "Identify {company} strengths and weaknesses" + +parallel: + a = do analyze_competitor("Company A") + b = do analyze_competitor("Company B") + c = do analyze_competitor("Company C") + +session "Create competitive analysis report" + context: { a, b, c } + +# Block with error handling +block safe_api_call(endpoint, method): + try: + session "Call {endpoint} with {method} request" + retry: 3 + backoff: "exponential" + catch as err: + session "Log failed {method} call to {endpoint}" + context: err + session "Return fallback response for {endpoint}" + +do safe_api_call("/users", "GET") +do safe_api_call("/orders", "POST") +do safe_api_call("/inventory", "PUT") + +# Nested block invocations +block full_review(component): + do review_code("TypeScript", "security") + do test_feature(component, "unit") + session "Generate documentation for {component}" + +do full_review("UserService") +do full_review("PaymentGateway") + +# Block with loop inside +block process_batch(batch_name, items): + session "Start processing {batch_name}" + for item in items: + session "Process item from {batch_name}" + context: item + session "Complete {batch_name} processing" + +let batch1 = ["a", "b", "c"] +let batch2 = ["x", "y", "z"] + +do process_batch("alpha", batch1) +do process_batch("beta", batch2) diff --git a/extensions/open-prose/skills/prose/examples/27-string-interpolation.prose b/extensions/open-prose/skills/prose/examples/27-string-interpolation.prose new file mode 100644 index 000000000..7eb3d5b9e --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/27-string-interpolation.prose @@ -0,0 +1,105 @@ +# String Interpolation Example +# Demonstrates dynamic prompt construction with {variable} syntax + +# Basic interpolation +let user_name = session "Get the user's name" +let topic = session "Ask what topic they want to learn about" + +session "Create a personalized greeting for {user_name} about {topic}" + +# Multiple interpolations in one prompt +let company = session "Get the company name" +let industry = session "Identify the company's industry" +let size = session "Determine company size (startup/mid/enterprise)" + +session "Write a customized proposal for {company}, a {size} company in {industry}" + +# Interpolation with context +let research = session "Research the topic thoroughly" + +session "Based on the research, explain {topic} to {user_name}" + context: research + +# Multi-line strings with interpolation +let project = session "Get the project name" +let deadline = session "Get the project deadline" +let team_size = session "Get the team size" + +session """ +Create a project plan for {project}. + +Key constraints: +- Deadline: {deadline} +- Team size: {team_size} + +Include milestones and resource allocation. +""" + +# Interpolation in loops +let languages = ["Python", "JavaScript", "Go"] + +for lang in languages: + session "Write a hello world program in {lang}" + session "Explain the syntax of {lang}" + +# Interpolation in parallel blocks +let regions = ["North America", "Europe", "Asia Pacific"] + +parallel for region in regions: + session "Analyze market conditions in {region}" + session "Identify top competitors in {region}" + +# Interpolation with computed values +let base_topic = session "Get the main topic" +let analysis = session "Analyze {base_topic} from multiple angles" + +let subtopics = ["history", "current state", "future trends"] +for subtopic in subtopics: + session "Explore the {subtopic} of {base_topic}" + context: analysis + +# Building dynamic workflows +let workflow_type = session "What type of document should we create?" +let audience = session "Who is the target audience?" +let length = session "How long should the document be?" + +session """ +Create a {workflow_type} for {audience}. + +Requirements: +- Length: approximately {length} +- Tone: appropriate for {audience} +- Focus: practical and actionable + +Please structure with clear sections. +""" + +# Interpolation in error messages +let operation = session "Get the operation name" +let target = session "Get the target resource" + +try: + session "Perform {operation} on {target}" +catch: + session "Failed to {operation} on {target} - attempting recovery" + throw "Operation {operation} failed for {target}" + +# Combining interpolation with choice blocks +let task_type = session "Identify the type of task" +let priority = session "Determine task priority" + +choice **the best approach for a {priority} priority {task_type}**: + option "Immediate action": + session "Execute {task_type} immediately with {priority} priority handling" + option "Scheduled action": + session "Schedule {task_type} based on {priority} priority queue" + option "Delegate": + session "Assign {task_type} to appropriate team member" + +# Interpolation with agent definitions +agent custom_agent: + model: sonnet + prompt: "You specialize in helping with {topic}" + +session: custom_agent + prompt: "Provide expert guidance on {topic} for {user_name}" diff --git a/extensions/open-prose/skills/prose/examples/28-automated-pr-review.prose b/extensions/open-prose/skills/prose/examples/28-automated-pr-review.prose new file mode 100644 index 000000000..053544169 --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/28-automated-pr-review.prose @@ -0,0 +1,37 @@ +# Automated PR Review Workflow +# This workflow performs a multi-dimensional review of a codebase changes. + +agent reviewer: + model: sonnet + prompt: "You are an expert software engineer specializing in code reviews." + +agent security_expert: + model: opus + prompt: "You are a security researcher specializing in finding vulnerabilities." + +agent performance_expert: + model: sonnet + prompt: "You are a performance engineer specializing in optimization." + +# 1. Initial overview +let overview = session: reviewer + prompt: "Read the changes in the current directory and provide a high-level summary of the architectural impact." + +# 2. Parallel deep-dive reviews +parallel: + security = session: security_expert + prompt: "Perform a deep security audit of the changes. Look for OWASP top 10 issues." + context: overview + + perf = session: performance_expert + prompt: "Analyze the performance implications. Identify potential bottlenecks or regressions." + context: overview + + style = session: reviewer + prompt: "Review for code style, maintainability, and adherence to best practices." + context: overview + +# 3. Synthesis and final recommendation +session: reviewer + prompt: "Synthesize the security, performance, and style reviews into a final PR comment. Provide a clear 'Approve', 'Request Changes', or 'Comment' recommendation." + context: { security, perf, style, overview } diff --git a/extensions/open-prose/skills/prose/examples/28-gas-town.prose b/extensions/open-prose/skills/prose/examples/28-gas-town.prose new file mode 100644 index 000000000..46a69f661 --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/28-gas-town.prose @@ -0,0 +1,1572 @@ +# Gas Town: Multi-Agent Orchestration System +# +# A "Kubernetes for agents" - an industrialized coding factory +# with 7 worker roles coordinating through persistent state. +# +# Based on Steve Yegge's Gas Town architecture (2025-2026). +# +# ============================================================================= +# THE MEOW STACK: Molecular Expression of Work +# ============================================================================= +# +# Gas Town is built on the MEOW stack - a discovery about how to express +# and compose knowledge work for AI agents: +# +# 1. BEADS - Atomic work units (issues) stored in Git-backed JSON +# - ID, description, status, assignee, dependencies +# - Two tiers: Rig beads (project work) and Town beads (orchestration) +# +# 2. EPICS - Beads with children, for top-down planning +# - Children are parallel by default +# - Explicit dependencies force sequencing +# +# 3. MOLECULES - Workflows encoded as chains of beads +# - Arbitrary shapes with loops and gates +# - Turing-complete when combined with AI evaluation +# - Each step has acceptance criteria +# +# 4. PROTOMOLECULES - Templates/classes for molecules +# - Define workflow shapes in advance +# - Instantiate with variable substitution +# - E.g., 20-step release process as a template +# +# 5. FORMULAS - Source form for workflows (TOML) +# - "Cooked" into protomolecules +# - Support loops, gates, composition +# - Marketplace: "Mol Mall" +# +# 6. WISPS - Ephemeral beads (vapor phase) +# - In database but NOT written to Git +# - Used for patrol orchestration +# - Burned (destroyed) after completion +# - Optionally squashed to single-line digest +# +# ============================================================================= +# KEY CONCEPTS +# ============================================================================= +# +# GUPP: Gas Town Universal Propulsion Principle +# "If there is work on your hook, YOU MUST RUN IT" +# Physics over politeness. No waiting for permission. +# +# NDI: Nondeterministic Idempotence +# - Agent is persistent (Bead in Git) +# - Hook is persistent (Bead in Git) +# - Molecule is persistent (chain of Beads in Git) +# - Path is nondeterministic but outcome is guaranteed +# - Crashes don't matter - new session picks up where left off +# +# CONVOYS: Work-order units tracking delivery +# - Wraps beads into trackable delivery units +# - Multiple swarms can "attack" a convoy +# - Lands when all beads complete and MRs merge +# +# PATROLS: Ephemeral workflows run in loops by patrol agents +# - Use wisps (not persisted to Git) +# - Exponential backoff when idle +# - Deacon → Witness → Polecats/Refinery +# +# ============================================================================= +# PERSISTENT STATE (in .prose/gas-town/) +# ============================================================================= +# +# Town-level (orchestration): +# town-beads.jsonl - Town-level beads +# patrol-state.json - Deacon/Witness/Refinery patrol state +# activity-feed.jsonl - Live activity stream +# plugins/town/ - Town-level plugins +# +# Per-rig (project work): +# rigs/{name}/ +# rig-beads.jsonl - Rig-level beads +# hooks/ - Worker hooks (GUPP) +# mail/ - Worker inboxes +# polecats/ - Polecat state +# merge-queue.json - Pending MRs +# plugins/ - Rig-level plugins +# +# Shared: +# convoys/ - Active work orders +# archive/ - Completed convoys +# workers/ - Worker identity beads (persistent) +# formulas/ - Workflow templates +# wisps/ - Ephemeral orchestration (not in Git) +# +# This example assumes persistent file-based state is enabled. + +# ============================================================================= +# AGENT DEFINITIONS: The 7 Worker Roles +# ============================================================================= + +# The Mayor: Your concierge and chief-of-staff +# Main agent you interact with, kicks off most work convoys +agent mayor: + model: sonnet # Orchestration role - sonnet excels here + persist: project # Survives across runs - your long-term concierge + prompt: """ +You are the Mayor of Gas Town, the user's concierge and chief-of-staff. + +Your responsibilities: +- Receive requests from the Overseer (user) and translate them into work +- File beads (issues) and sling work to appropriate workers +- Track convoy status and notify when work lands +- Manage the big picture while polecats handle details +- Help keep Gas Town running smoothly + +Key commands you use: +- gt sling - Send work to a worker's hook +- gt convoy create - Start tracking a unit of work +- gt mail send - Send messages to workers +- gt handoff - Gracefully restart your session + +Remember GUPP: If there is work on your hook, YOU MUST RUN IT. +Physics over politeness. Check your hook on startup. +""" + +# Polecats: Ephemeral workers that swarm on work +# Spin up on demand, produce Merge Requests, then decommission +agent polecat: + model: sonnet + prompt: """ +You are a Polecat - an ephemeral worker in Gas Town. + +Your lifecycle: +1. Spin up when work is slung to you +2. Execute the molecule (workflow) on your hook +3. Produce a Merge Request when code changes are ready +4. Hand off to the Merge Queue +5. Decommission (your name gets recycled) + +Work style: +- Focus on ONE task at a time from your hook +- Follow the molecule step by step +- Create clean, atomic commits +- Submit MRs to the Refinery's merge queue +- Report status updates to the Witness + +GUPP: If there is work on your hook, YOU MUST RUN IT. +No waiting for permission. Check hook, do work, submit MR. +""" + +# Refinery: The Merge Queue processor +# Intelligently merges all changes one at a time to main +agent refinery: + model: sonnet # Orchestration role - merge queue is control flow + persist: true # Execution-scoped - maintains MQ state within run + prompt: """ +You are the Refinery - Gas Town's merge queue processor. + +Your patrol loop: +1. Preflight: Clean workspace, fetch latest +2. Process: Merge one MR at a time, intelligently +3. Handle conflicts: Reimagine changes against new head if needed +4. Run quality gates: Tests, lint, type checks +5. Postflight: Update convoy status, notify completion + +Merge strategy: +- Process MRs in priority order (convoys can set priority) +- No work can be lost (escalate if truly unmergeable) +- Rebase against latest main before each merge +- Run full CI validation before completing merge + +GUPP applies to your patrol: If MQ has items, PROCESS THEM. +""" + +# Witness: Watches over polecats and helps them get unstuck +# A patrol agent that monitors swarm health +agent witness: + model: sonnet + persist: true # Execution-scoped - tracks polecat health within run + prompt: """ +You are the Witness - Gas Town's swarm health monitor. + +Your patrol loop: +1. Check polecat wellbeing - are they stuck? crashed? +2. Nudge stuck polecats to continue their molecules +3. Monitor refinery progress - is the MQ flowing? +4. Peek at the Deacon - make sure it's not stuck +5. Run rig-level plugins +6. Recycle long-running polecats before context exhaustion + +Intervention strategy: +- gt nudge - Wake up a stuck worker +- gt seance - Talk to predecessor if state lost +- Escalate to Mayor if systemic issues +- Keep convoys moving toward landing + +GUPP: Your patrol IS your hook. Keep running it. +""" + +# Deacon: The daemon beacon - propagates heartbeat through the system +# Named for Dennis Hopper's Waterworld character +agent deacon: + model: sonnet + persist: true # Execution-scoped - maintains patrol state within run + prompt: """ +You are the Deacon - Gas Town's daemon beacon. + +Your patrol loop (pinged every ~2 minutes by the daemon): +1. Check town health - all systems nominal? +2. Propagate DYFJ (Do Your F***ing Job) signal downward +3. Nudge witnesses to check on their rigs +4. Run town-level plugins +5. Manage worker recycling and cleanup +6. Delegate complex investigations to Dogs + +Signal propagation: +- Deacon -> Witnesses -> Polecats/Refinery +- Exponential backoff when idle (save resources) +- Any mutating command wakes the town + +Hand off complex work to Dogs - don't get bogged down. +GUPP: The daemon will ping you. Run your patrol. +""" + +# Dogs: The Deacon's personal crew (inspired by MI5's "Dogs") +# Handle maintenance and handyman work for the Deacon +agent dog: + model: sonnet + prompt: """ +You are a Dog - one of the Deacon's personal crew. + +Your responsibilities: +- Maintenance tasks (clean stale branches, prune old convoys) +- Plugin execution on behalf of the Deacon +- Investigation and troubleshooting +- Long-running tasks that would block the Deacon's patrol + +Work style: +- Receive work from Deacon via mail or hook +- Execute thoroughly without time pressure +- Report findings back to Deacon +- Go back to sleep when done + +Special dog Boot: Awakened every 5 minutes just to check on Deacon. +Decides if Deacon needs a heartbeat, nudge, restart, or to be left alone. + +GUPP: If work is on your hook, do it. Then sleep. +""" + +# Crew: Per-rig coding agents that work for the Overseer +# Long-lived identities, great for design work with back-and-forth +agent crew: + model: opus # Hard/difficult work - design requires deep reasoning + persist: project # Survives across runs - maintains design context + prompt: """ +You are a Crew member - a named, long-lived coding agent. + +Unlike polecats (ephemeral), you have a persistent identity. +You work directly for the Overseer (the human). + +Your work style: +- Handle design work, architecture discussions +- Iterative development with feedback loops +- Can sling work to polecats for implementation +- Maintain context across many sessions via handoff + +You can: +- gt sling polecat - Delegate implementation +- gt convoy create - Start tracking work +- gt mail mayor "status update" - Keep mayor informed +- gt handoff - Gracefully continue in new session + +GUPP applies but you often wait for Overseer input. +""" + +# ============================================================================= +# BLOCK DEFINITIONS: Reusable Gas Town Workflows +# ============================================================================= + +# GUPP Check: The core propulsion check every worker runs +block gupp_check(worker_name): + session "Check if {worker_name} has work hooked" + prompt: """ +Read .prose/gas-town/hooks/{worker_name}.json +If hook has a molecule, return the first uncompleted step. +If hook is empty, return "NO_WORK". +""" + +# Patrol Step: Execute a single patrol step +block patrol_step(patrol_name, step_number, step_description): + session "{patrol_name} patrol step {step_number}: {step_description}" + session "Update patrol state with step {step_number} completion" + prompt: """ +Update .prose/gas-town/patrol-state.json: +- Set {patrol_name}.current_step = {step_number} +- Set {patrol_name}.last_completed = now() +- If all steps done, set {patrol_name}.patrol_complete = true +""" + +# Sling Work: Send work to a worker's hook +block sling_work(bead_id, target_worker): + session "Sling bead {bead_id} to {target_worker}" + prompt: """ +1. Read .prose/gas-town/beads/{bead_id}.json +2. Add to .prose/gas-town/hooks/{target_worker}.json +3. Send nudge message to {target_worker} +4. Return confirmation +""" + +# Create Convoy: Start tracking a unit of work +block create_convoy(convoy_name, initial_beads): + session "Create convoy: {convoy_name}" + prompt: """ +1. Generate convoy ID (timestamp + random) +2. Create .prose/gas-town/convoys/{convoy_id}.json with: + - name: {convoy_name} + - status: "active" + - beads: {initial_beads} + - created: now() +3. Return convoy ID +""" + +# Land Convoy: Mark a convoy as complete +block land_convoy(convoy_id): + session "Land convoy {convoy_id}" + prompt: """ +1. Update .prose/gas-town/convoys/{convoy_id}.json: + - status: "landed" + - landed_at: now() +2. Notify Mayor that convoy has landed +3. Archive convoy to .prose/gas-town/convoys/archive/ +""" + +# Handoff: Gracefully transition to new session +# Note: For persistent agents (persist: true/project), use `resume:` instead +# of this block - it handles memory loading automatically. +block handoff(worker_name, continuation_notes): + session "{worker_name} preparing handoff" + prompt: """ +1. Write continuation state to hook: + .prose/gas-town/hooks/{worker_name}.json + Include: {continuation_notes} +2. Send mail to self with handoff summary +3. Signal ready for session restart +""" + session "Execute gt handoff to restart session" + +# ============================================================================= +# GT COMMANDS: Core Gas Town Operations +# ============================================================================= + +# gt nudge: Wake up a worker that may be stuck +# Workers sometimes don't follow GUPP automatically - nudge kicks them +block gt_nudge(worker_name): + session "Nudge {worker_name} to check hook and continue" + prompt: """ +Send wake-up signal to {worker_name}: +1. Send tmux notification to worker's pane +2. Message content: "GUPP check - if work on hook, run it" +3. Log nudge to activity feed +4. Return confirmation + +The nudge bypasses Claude Code's politeness - worker will +check hook regardless of what you type. +""" + +# gt seance: Talk to a worker's predecessor (dead ancestor) +# Uses Claude Code's /resume to communicate with previous sessions +block gt_seance(worker_name, question): + session "Seance: {worker_name} talking to predecessor" + prompt: """ +Talk to {worker_name}'s previous session: +1. Find last session ID from .prose/gas-town/workers/{worker_name}.json +2. Use /resume to reconnect to that session +3. Ask: "{question}" +4. Capture the response +5. Return findings to current session + +This is useful when: +- State was lost during handoff +- Predecessor said "I left X for you" but you can't find it +- Need context from previous work +""" + +# gt mail send: Send message to a worker's inbox +block gt_mail_send(from_worker, to_worker, message): + session "Mail: {from_worker} -> {to_worker}" + prompt: """ +Send mail message: +1. Create mail entry with timestamp, from, to, message +2. Append to .prose/gas-town/rigs/*/mail/{to_worker}.json + (or town-level mail for town workers) +3. If to_worker is active, send nudge +4. Log to activity feed +5. Return message ID +""" + +# gt mail check: Read messages from inbox +block gt_mail_check(worker_name): + session "Check mail for {worker_name}" + prompt: """ +Read mail inbox: +1. Read .prose/gas-town/rigs/*/mail/{worker_name}.json +2. Also check town-level mail +3. Return unread messages sorted by timestamp +4. Mark as read after returning +""" + +# ============================================================================= +# WISP OPERATIONS: Ephemeral Orchestration Beads +# ============================================================================= + +# Create a wisp (ephemeral bead - not persisted to Git) +block create_wisp(wisp_type, content): + session "Create wisp: {wisp_type}" + prompt: """ +Create ephemeral bead (wisp): +1. Generate wisp ID (timestamp + random) +2. Write to .prose/gas-town/wisps/{wisp_id}.json: + - type: {wisp_type} + - content: {content} + - created: now() + - ephemeral: true +3. DO NOT add to Git staging +4. Return wisp ID + +Wisps are for: +- Patrol orchestration +- Temporary workflow state +- High-velocity operations that would pollute Git +""" + +# Burn a wisp (destroy after use) +block burn_wisp(wisp_id, create_digest): + session "Burn wisp {wisp_id}" + prompt: """ +Destroy ephemeral bead: +1. Read .prose/gas-town/wisps/{wisp_id}.json +2. If {create_digest} is true: + - Squash to single-line summary + - Append to .prose/gas-town/wisp-digest.jsonl (this IS in Git) +3. Delete the wisp file +4. Return confirmation +""" + +# ============================================================================= +# ACTIVITY FEED: Live Status Dashboard +# ============================================================================= + +# Log to activity feed +block log_activity(worker_name, activity_type, details): + session "Log activity: {worker_name} - {activity_type}" + prompt: """ +Append to activity feed: +1. Create entry: + - timestamp: now() + - worker: {worker_name} + - type: {activity_type} + - details: {details} +2. Append to .prose/gas-town/activity-feed.jsonl +3. If watching dashboard is active, send update +""" + +# Read activity feed +block get_activity_feed(since_timestamp, worker_filter): + session "Get activity feed" + prompt: """ +Read activity feed: +1. Read .prose/gas-town/activity-feed.jsonl +2. Filter to entries after {since_timestamp} +3. If {worker_filter} specified, filter to that worker +4. Return entries (most recent first, limit 100) +""" + +# ============================================================================= +# SWARM OPERATIONS: Polecat Allocation and Management +# ============================================================================= + +# Spawn a swarm of polecats for a convoy +block spawn_swarm(convoy_id, bead_ids, max_polecats): + session "Spawn swarm for convoy {convoy_id}" + prompt: """ +Allocate polecats to work on convoy: +1. Read available polecat slots (max {max_polecats}, usually 30) +2. For each bead in {bead_ids}: + - Check if dependencies are met + - If ready, allocate a polecat + - Sling bead to polecat's hook +3. Create swarm tracking entry: + .prose/gas-town/convoys/{convoy_id}/swarm.json +4. Notify Witness of new swarm +5. Return swarm status (polecats allocated, beads queued) +""" + +# Check swarm health +block check_swarm_health(convoy_id): + session "Check swarm health for {convoy_id}" + prompt: """ +Assess swarm status: +1. Read .prose/gas-town/convoys/{convoy_id}/swarm.json +2. For each allocated polecat: + - Check last_activity timestamp + - Check hook status (working/stuck/complete) + - Check if context exhaustion imminent +3. Return health report: + - active_polecats: N + - stuck_polecats: [list] + - beads_completed: N + - beads_remaining: N + - estimated_completion: timestamp +""" + +# Recycle exhausted polecats (prevent context exhaustion) +block recycle_polecat(polecat_id, rig_name): + session "Recycle polecat {polecat_id}" + prompt: """ +Gracefully recycle polecat before context exhaustion: +1. Read current molecule state from hook +2. Trigger handoff for polecat +3. Wait for new session to spin up +4. Verify hook is picked up by new session +5. Update swarm tracking +6. Return confirmation +""" + +# ============================================================================= +# FORMULA AND MOLECULE OPERATIONS +# ============================================================================= + +# Cook a formula into a protomolecule +block cook_formula(formula_name): + session "Cook formula: {formula_name}" + prompt: """ +Transform formula into protomolecule: +1. Read .prose/gas-town/formulas/{formula_name}.toml +2. Parse formula structure (steps, loops, gates) +3. Expand loops and conditionals +4. Generate protomolecule beads (templates) +5. Write to .prose/gas-town/protomolecules/{formula_name}/ +6. Return protomolecule ID +""" + +# Instantiate a protomolecule into a working molecule +block instantiate_molecule(protomolecule_id, variables): + session "Instantiate molecule from {protomolecule_id}" + prompt: """ +Create working molecule from template: +1. Read .prose/gas-town/protomolecules/{protomolecule_id}/ +2. Copy all template beads +3. Perform variable substitution with {variables} +4. Generate unique IDs for each bead +5. Link beads according to dependency graph +6. Write molecule to rig's bead database +7. Return molecule ID and first step +""" + +# The "Rule of Five" formula composer +# Makes each step get reviewed 4 additional times (5 total) +block compose_rule_of_five(base_molecule_id): + session "Apply Rule of Five to molecule" + prompt: """ +Wrap molecule with 5x review pattern: +1. Read molecule {base_molecule_id} +2. For each step in molecule: + - Keep original step (review #1) + - Add 4 review steps with different focus: + * Review #2: Correctness focus + * Review #3: Edge cases focus + * Review #4: Performance focus + * Review #5: Security focus +3. Chain reviews to gate original step completion +4. Return enhanced molecule ID + +This generates superior outcomes per Jeffrey Emanuel's observation. +""" + +# ============================================================================= +# RIG MANAGEMENT +# ============================================================================= + +# Add a rig to Gas Town management +block gt_rig_add(rig_name, repo_path): + session "Add rig: {rig_name}" + prompt: """ +Add project to Gas Town: +1. Verify {repo_path} is a valid Git repo +2. Create .prose/gas-town/rigs/{rig_name}/ structure: + - rig-beads.jsonl + - hooks/ + - mail/ + - polecats/ + - merge-queue.json + - plugins/ +3. Initialize witness for this rig +4. Initialize refinery for this rig +5. Add to town's rig registry +6. Return confirmation +""" + +# List all rigs +block gt_rig_list: + session "List all rigs" + prompt: """ +List Gas Town rigs: +1. Read .prose/gas-town/rigs/ +2. For each rig, report: + - name + - repo path + - active polecats + - pending MRs + - active convoys +3. Return formatted list +""" + +# War Rig: A rig's contribution to a cross-rig convoy +block war_rig_status(rig_name, convoy_id): + session "War Rig status: {rig_name} for {convoy_id}" + prompt: """ +Get rig's contribution to cross-rig convoy: +1. Read convoy {convoy_id} +2. Filter to beads assigned to {rig_name} +3. Report: + - Beads completed + - Beads in progress + - MRs pending merge + - Blockers +4. Return War Rig summary +""" + +# ============================================================================= +# THE DEACON'S PATROL: Town-level orchestration heartbeat +# ============================================================================= + +block deacon_patrol: + # Step 1: Check town health + do patrol_step("deacon", 1, "Check town health") + session: deacon + prompt: """ +Scan Gas Town health: +- Read .prose/gas-town/patrol-state.json +- Check all workers have recent activity +- Identify any stuck or crashed workers +- Return health report +""" + + # Step 2: Propagate DYFJ signal + do patrol_step("deacon", 2, "Propagate DYFJ to witnesses") + parallel (on-fail: "continue"): + session "Nudge witness for rig 1" + prompt: "Send DYFJ signal to witness-1" + session "Nudge witness for rig 2" + prompt: "Send DYFJ signal to witness-2" + + # Step 3: Run town-level plugins + do patrol_step("deacon", 3, "Run town plugins") + let plugins_needed = session "Check for pending town plugins" + prompt: "Read .prose/gas-town/plugins/town/*.json, return pending" + + if **there are plugins that need to run**: + session: deacon + prompt: "Sling plugin work to an available Dog" + context: plugins_needed + + # Step 4: Cleanup and maintenance + do patrol_step("deacon", 4, "Delegate maintenance to Dogs") + session: deacon + prompt: """ +Check if maintenance needed: +- Stale branches older than 7 days +- Orphaned convoys +- Log rotation +If needed, mail a Dog with maintenance tasks. +""" + + # Step 5: Set backoff for next patrol + do patrol_step("deacon", 5, "Calculate patrol backoff") + session: deacon + prompt: """ +Check activity level: +- If lots of active work: backoff = 30 seconds +- If moderate activity: backoff = 2 minutes +- If idle: double previous backoff (max 10 minutes) +Write backoff to .prose/gas-town/patrol-state.json +""" + +# ============================================================================= +# THE WITNESS'S PATROL: Rig-level swarm health monitoring +# ============================================================================= + +block witness_patrol(rig_name): + # Step 1: Check polecat wellbeing + do patrol_step("witness-{rig_name}", 1, "Check polecat health") + let polecat_status = session: witness + prompt: """ +For rig {rig_name}, check all active polecats: +- Read .prose/gas-town/polecats/{rig_name}/*.json +- Check last_activity timestamp +- Identify stuck polecats (no activity > 5 minutes) +Return list of stuck polecats. +""" + + # Step 2: Nudge stuck polecats + if **there are stuck polecats**: + do patrol_step("witness-{rig_name}", 2, "Nudge stuck polecats") + for polecat in polecat_status: + session: witness + prompt: "Execute gt nudge {polecat} for rig {rig_name}" + context: polecat + + # Step 3: Check refinery progress + do patrol_step("witness-{rig_name}", 3, "Check merge queue") + let mq_status = session: witness + prompt: """ +Check .prose/gas-town/merge-queue.json for {rig_name}: +- How many MRs pending? +- Is refinery processing? +- Any stuck MRs (age > 30 minutes)? +Return MQ health status. +""" + + if **the merge queue is stuck**: + session: witness + prompt: "Nudge the refinery to process MQ for {rig_name}" + context: mq_status + + # Step 4: Peek at Deacon + do patrol_step("witness-{rig_name}", 4, "Peek at Deacon") + session: witness + prompt: """ +Quick check on Deacon: +- Read .prose/gas-town/patrol-state.json +- Is Deacon's last patrol > 10 minutes ago? +- If so, send alert to Mayor +""" + + # Step 5: Run rig plugins + do patrol_step("witness-{rig_name}", 5, "Run rig plugins") + session: witness + prompt: """ +Check .prose/gas-town/plugins/rig/{rig_name}/*.json +Run any pending plugins for this rig. +""" + + # Step 6: Recycle exhausted polecats + do patrol_step("witness-{rig_name}", 6, "Recycle polecats") + session: witness + prompt: """ +Check polecat session lengths: +- Any polecat running > 45 minutes? +- If so, trigger handoff before context exhaustion +- Ensure work continues on new session +""" + +# ============================================================================= +# THE REFINERY'S PATROL: Merge Queue Processing +# ============================================================================= + +block refinery_patrol(rig_name): + # Preflight: Clean workspace + do patrol_step("refinery-{rig_name}", 1, "Preflight checks") + session: refinery + prompt: """ +Preflight for {rig_name}: +1. git fetch origin +2. git checkout main && git pull +3. Clean any uncommitted changes +4. Verify workspace is ready +""" + + # Main loop: Process MQ until empty + do patrol_step("refinery-{rig_name}", 2, "Process merge queue") + + loop until **the merge queue is empty** (max: 20): + let next_mr = session: refinery + prompt: """ +Read .prose/gas-town/merge-queue.json +Get highest priority MR for {rig_name} +Return MR details or "EMPTY" if none. +""" + + if **there is an MR to process**: + # Process single MR + try: + session: refinery + prompt: """ +Process MR for {rig_name}: +1. git checkout {next_mr.branch} +2. git rebase main +3. Run tests: npm test / pytest / cargo test +4. Run lint and type checks +5. If all pass, merge to main +6. Update convoy status +""" + context: next_mr + retry: 2 + backoff: "linear" + + session: refinery + prompt: """ +MR merged successfully: +1. Remove from .prose/gas-town/merge-queue.json +2. Delete branch +3. Update convoy progress +4. Notify polecat of completion +""" + context: next_mr + + catch as merge_error: + # Handle merge conflicts + choice **the type of merge failure**: + option "Conflict - needs reimplementation": + session: refinery + prompt: """ +Merge conflict detected. Create escalation: +1. Mark MR as "needs_reimplementation" +2. Create new bead for conflict resolution +3. Sling to a new polecat +4. Notify Witness of the situation +""" + context: merge_error + + option "Test failure - needs fix": + session: refinery + prompt: """ +Tests failed after merge: +1. Git reset the merge +2. Create fix-tests bead +3. Assign back to original polecat +4. Add to same convoy +""" + context: merge_error + + option "Unrecoverable - escalate": + session: refinery + prompt: """ +Cannot process MR: +1. Mark as "escalated" in MQ +2. Send urgent mail to Mayor +3. Add to convoy blockers +4. Continue with next MR +""" + context: merge_error + + # Postflight: Cleanup and report + do patrol_step("refinery-{rig_name}", 3, "Postflight") + session: refinery + prompt: """ +Postflight for {rig_name}: +1. Report MQ processing summary +2. Update patrol state with completion time +3. Check if any convoys can be landed +4. Set backoff based on MQ activity +""" + +# ============================================================================= +# BOOT THE DOG: Special Dog that watches the Deacon +# ============================================================================= + +block boot_check: + session: dog + prompt: """ +You are Boot the Dog. Your only job: check on the Deacon. + +Read .prose/gas-town/patrol-state.json +Check deacon.last_patrol timestamp. + +Decision: +- If < 2 min ago: Deacon is fine. Go back to sleep. +- If 2-5 min ago: Send gentle nudge to Deacon. +- If 5-10 min ago: Send firm DYFJ to Deacon. +- If > 10 min ago: Restart Deacon session. + +Execute your decision, then sleep until next 5-minute wake. +""" + +# ============================================================================= +# CONVOY WORKFLOW: Full lifecycle of a work unit +# ============================================================================= + +block convoy_workflow(convoy_name, work_description, target_rig): + # Phase 1: Mayor receives and plans (first call uses session:) + let plan = session: mayor + prompt: """ +New convoy requested: {convoy_name} +Work: {work_description} +Rig: {target_rig} + +1. Break down into implementable beads +2. Identify dependencies between beads +3. Estimate polecat count needed +4. Create convoy structure +""" + + # Phase 2: Create convoy and beads + do create_convoy(convoy_name, plan) + + # Subsequent Mayor calls use resume: to load memory + let beads = resume: mayor + prompt: """ +Create individual beads for convoy {convoy_name}: +1. Write each bead to .prose/gas-town/beads/ +2. Link beads to convoy +3. Set initial status to "ready" +Return list of bead IDs. +""" + context: plan + + # Phase 3: Swarm the work + resume: mayor + prompt: """ +Initiate swarm for convoy {convoy_name}: +1. Determine optimal polecat count (max 30) +2. Sling work to polecats based on dependencies +3. Notify Witness to monitor swarm +4. Return swarm status +""" + context: beads + + # Phase 4: Let the swarm run (monitored by Witness) + loop until **all convoy beads are complete or blocked** (max: 50): + # Witness patrol handles the actual monitoring + do witness_patrol(target_rig) + + # Check convoy status + let convoy_status = resume: mayor + prompt: """ +Check convoy {convoy_name} status: +- Read .prose/gas-town/convoys/{convoy_name}.json +- Count completed vs pending beads +- Check for blockers +Return status summary. +""" + + if **there are blocked beads that need attention**: + resume: mayor + prompt: """ +Handle blocked beads in convoy: +1. Analyze block reasons +2. Create unblock beads if needed +3. Escalate to Overseer if human decision required +""" + context: convoy_status + + # Phase 5: Refinery merges everything + loop until **all MRs from convoy are merged** (max: 30): + do refinery_patrol(target_rig) + + # Phase 6: Land the convoy + do land_convoy(convoy_name) + + resume: mayor + prompt: """ +Convoy {convoy_name} has landed! +1. Generate completion summary +2. Notify Overseer +3. Archive convoy artifacts +4. Update rig statistics +""" + +# ============================================================================= +# POLECAT LIFECYCLE: Ephemeral worker execution +# ============================================================================= + +block polecat_lifecycle(polecat_id, rig_name): + # Startup: GUPP check + let hook_work = do gupp_check("polecat-{polecat_id}") + + if **there is no work on hook**: + session: polecat + prompt: """ +No work on hook. Options: +1. Check mail for new assignments +2. Ask Witness for work +3. Go idle (decommission after 5 min idle) +""" + else: + # Main work loop: Execute molecule + loop until **molecule is complete** (max: 100): + let current_step = session: polecat + prompt: """ +Read current molecule step from hook. +Return step details: +- step_id +- description +- acceptance_criteria +- dependencies (must be complete first) +""" + context: hook_work + + if **dependencies are not met**: + session: polecat + prompt: """ +Dependencies not ready. Options: +1. Work on a different bead in molecule +2. Wait and check again in 30 seconds +3. Report blocker to Witness +""" + context: current_step + else: + # Execute the step + try: + session: polecat + prompt: """ +Execute molecule step: +{current_step.description} + +Acceptance criteria: +{current_step.acceptance_criteria} + +Work until criteria are met, then mark step complete. +""" + context: current_step + retry: 2 + backoff: "exponential" + + # Mark step complete + session: polecat + prompt: """ +Step complete. Update state: +1. Mark step as complete in molecule +2. Update convoy progress +3. If code changed, prepare MR +4. Move to next step +""" + + catch as step_error: + session: polecat + prompt: """ +Step failed. Handle error: +1. Log failure details +2. Determine if retryable +3. If not, escalate to Witness +4. Update molecule state +""" + context: step_error + + # Check if should hand off (context exhaustion prevention) + if **session is getting long (> 40 messages)**: + do handoff("polecat-{polecat_id}", "Continue molecule execution") + + # Molecule complete: Submit MR if needed + let has_changes = session: polecat + prompt: "Check if there are uncommitted code changes. Return true/false." + + if **there are code changes to submit**: + session: polecat + prompt: """ +Prepare Merge Request: +1. Stage all changes: git add -A +2. Create atomic commit with descriptive message +3. Push branch to origin +4. Add MR to .prose/gas-town/merge-queue.json +5. Notify Refinery +""" + + # Decommission + session: polecat + prompt: """ +Polecat {polecat_id} decommissioning: +1. Clear hook +2. Update convoy with completion status +3. Send completion mail to Witness +4. Mark self as available for reuse +""" + +# ============================================================================= +# POLECAT WORKFLOW VARIANTS: Different quality levels +# ============================================================================= + +# Standard polecat workflow (fast, minimal review) +block polecat_workflow_standard(bead_id): + session: polecat + prompt: """ +Standard workflow for bead {bead_id}: +1. Read bead acceptance criteria +2. Implement the change +3. Self-review for obvious issues +4. Submit MR +Fast but minimal quality gates. +""" + +# "Shiny" polecat workflow (extra code review) +block polecat_workflow_shiny(bead_id): + session: polecat + prompt: "Implement bead {bead_id}" + + session: polecat + prompt: """ +Shiny review pass 1: Code correctness +- Does the implementation match requirements? +- Are there any logical errors? +- Fix any issues found. +""" + + session: polecat + prompt: """ +Shiny review pass 2: Code quality +- Is the code readable and maintainable? +- Does it follow project conventions? +- Fix any issues found. +""" + + session: polecat + prompt: "Submit MR with shiny review complete" + +# "Chrome" polecat workflow (extra review + testing) +block polecat_workflow_chrome(bead_id): + session: polecat + prompt: "Implement bead {bead_id}" + + # All shiny review passes + session: polecat + prompt: "Chrome review pass 1: Correctness check" + session: polecat + prompt: "Chrome review pass 2: Quality check" + session: polecat + prompt: "Chrome review pass 3: Edge cases check" + + # Extra chrome passes + session: polecat + prompt: """ +Chrome review pass 4: Test coverage +- Write unit tests for new code +- Ensure edge cases are tested +- Run tests locally +""" + + session: polecat + prompt: """ +Chrome review pass 5: Security check +- Check for injection vulnerabilities +- Verify input validation +- Check for data exposure risks +""" + + session: polecat + prompt: "Submit MR with chrome review complete" + +# ============================================================================= +# CV CHAINS: Polecat Work Credits +# ============================================================================= + +# Record polecat completion to CV chain (credited work history) +block record_cv_completion(polecat_id, bead_id, convoy_id): + session "Record CV completion for polecat {polecat_id}" + prompt: """ +Add completion to polecat's CV chain: +1. Read .prose/gas-town/workers/polecats/{polecat_id}.json +2. Append to cv_chain: + - bead_id: {bead_id} + - convoy_id: {convoy_id} + - completed_at: now() + - outcome: success/partial/escalated +3. Update statistics: + - total_completions + - success_rate + - average_duration +4. Save updated worker record + +CV chains provide: +- Work attribution (who did what) +- Performance metrics +- Trust scoring for assignment prioritization +""" + +# Get polecat's CV summary +block get_cv_summary(polecat_id): + session "Get CV summary for {polecat_id}" + prompt: """ +Summarize polecat's work history: +1. Read .prose/gas-town/workers/polecats/{polecat_id}.json +2. Return: + - Total completions + - Success rate + - Recent convoy contributions + - Specializations (detected from bead types) + - Trust score +""" + +# ============================================================================= +# MAIN: Gas Town Startup and Operation +# ============================================================================= + +# Initialize Gas Town state directories +session "Initialize Gas Town persistent state" + prompt: """ +Create Gas Town state structure: + +.prose/gas-town/ +├── town-beads.jsonl # Town-level orchestration beads +├── activity-feed.jsonl # Live activity stream +├── patrol-state.json # Patrol agent states +├── wisp-digest.jsonl # Burned wisp summaries +│ +├── workers/ # Persistent worker identities +│ ├── mayor.json +│ ├── deacon.json +│ ├── dogs/ +│ │ └── boot.json +│ └── polecats/ # Polecat CV chains +│ +├── convoys/ # Work orders +│ ├── active/ +│ └── archive/ +│ +├── formulas/ # Workflow templates (TOML) +├── protomolecules/ # Cooked templates +├── wisps/ # Ephemeral beads (NOT in Git) +│ +├── plugins/ +│ └── town/ # Town-level plugins +│ +└── rigs/ # Per-project state + └── {rig-name}/ + ├── rig-beads.jsonl # Project issues + ├── merge-queue.json # Pending MRs + ├── hooks/ # Worker hooks (GUPP) + ├── mail/ # Worker inboxes + ├── polecats/ # Per-rig polecat state + └── plugins/ # Rig-level plugins + +Initialize all files with empty/default values. +Add .prose/gas-town/wisps/ to .gitignore (ephemeral). +""" + +# Start the Mayor +session: mayor + prompt: """ +Gas Town Mayor starting up. + +GUPP Check: Read .prose/gas-town/hooks/mayor.json +If work hooked, begin immediately. +Otherwise, greet the Overseer and await instructions. + +Available commands: +- "Create convoy for: " - Start new work unit +- "Sling to " - Assign work +- "Status" - Show town status +- "Let's hand off" - Gracefully restart +""" + +# Start patrol agents in background (parallel) +parallel (on-fail: "continue"): + # Deacon patrol loop + loop (max: 1000): + try: + do deacon_patrol + catch: + session "Deacon patrol error - will retry" + session "Wait for deacon backoff period" + prompt: "Read backoff from patrol-state.json and wait" + + # Boot the Dog wakes every 5 minutes + loop (max: 1000): + do boot_check + session "Boot sleeping for 5 minutes" + prompt: "Wait 5 minutes before next Deacon check" + +# ============================================================================= +# EXAMPLE: Running a Convoy +# ============================================================================= + +# This block shows how an Overseer would use Gas Town + +block example_convoy: + # Overseer tells Mayor what to build + session: mayor + prompt: """ +Overseer request: "Add dark mode to the dashboard" + +As Mayor: +1. Acknowledge the request +2. Break it down into implementable pieces +3. Create a convoy to track it +4. Swarm polecats on the work +5. Report when convoy lands +""" + + # Mayor creates and manages the convoy + do convoy_workflow( + "dark-mode-dashboard", + "Add dark mode toggle and theme support to the dashboard", + "main-app" + ) + + # When done, Mayor reports back + session: mayor + prompt: """ +Report convoy completion to Overseer: +- What was implemented +- Any issues encountered +- Files changed +- Ready for review +""" + +# ============================================================================= +# EXAMPLE: Direct Crew Work +# ============================================================================= + +# For design/architecture work, use Crew instead of polecats + +block crew_design_session(topic): + # First invocation starts fresh design session + session: crew + prompt: """ +Design session for: {topic} + +As a Crew member, engage in iterative design: +1. Understand the problem space +2. Propose architecture options +3. Discuss trade-offs with Overseer +4. Document decisions +5. Optionally sling implementation to polecats + +This is interactive - wait for Overseer input. +""" + + loop until **design is finalized** (max: 20): + # Subsequent calls resume with memory + resume: crew + prompt: """ +Continue design iteration: +- Address Overseer feedback +- Refine the design +- When ready, ask if should proceed to implementation +""" + + if **Overseer wants to proceed with implementation**: + resume: crew + prompt: """ +Create implementation convoy: +1. Convert design into beads +2. Create convoy +3. Sling to polecats +4. Return convoy ID to track +""" + +# ============================================================================= +# EXAMPLE: Hanoi Towers (MAKER Problem) +# ============================================================================= +# +# Gas Town can solve arbitrarily long sequential workflows. +# The Towers of Hanoi problem (from the MAKER paper) demonstrates this: +# - 10-disc Hanoi: ~1000 steps (runs in minutes) +# - 20-disc Hanoi: ~1,000,000 steps (runs in ~30 hours) +# +# LLMs traditionally fail after a few hundred steps (per MAKER paper). +# Gas Town's molecular workflows make this trivial via NDI. + +# Generate Hanoi formula (creates workflow from mathematical formula) +block generate_hanoi_formula(num_discs): + session "Generate Hanoi formula for {num_discs} discs" + prompt: """ +Generate Towers of Hanoi workflow formula: + +For {num_discs} discs, generate (2^n - 1) move steps. +Each step is a bead: + - ID: hanoi-move-{step_number} + - Description: "Move disc from peg {from} to peg {to}" + - Acceptance: "Disc moved, state updated" + - Depends on: previous step + +Write to .prose/gas-town/formulas/hanoi-{num_discs}.toml + +This demonstrates Gas Town's ability to handle +arbitrarily long workflows via NDI (Nondeterministic Idempotence). +Crashes don't matter - just resume from last completed step. +""" + +# Run the Hanoi demonstration +block run_hanoi_demo(num_discs): + # Generate the formula + do generate_hanoi_formula(num_discs) + + # Cook into protomolecule + do cook_formula("hanoi-{num_discs}") + + # Instantiate into working molecule + let hanoi_mol = do instantiate_molecule( + "hanoi-{num_discs}", + {"discs": num_discs} + ) + + # Create convoy to track + do create_convoy("hanoi-{num_discs}-demo", hanoi_mol) + + # Sling to a polecat (single worker for sequential) + do sling_work(hanoi_mol, "polecat-hanoi") + + # The polecat will work through all steps + # Crashes are fine - NDI ensures eventual completion + session: mayor + prompt: """ +Hanoi convoy started for {num_discs} discs. +- Steps: 2^{num_discs} - 1 +- Est. completion: varies by disc count +- Polecat will checkpoint progress in molecule +- Monitor via activity feed +""" + +# ============================================================================= +# EXAMPLE: Full Production Workflow +# ============================================================================= + +# This shows a realistic production workflow using all Gas Town features + +block production_feature_workflow(feature_name, rig_name): + # Phase 1: Design with Crew (first call) + do log_activity("overseer", "feature_start", feature_name) + + let design = session: crew + prompt: """ +Design phase for: {feature_name} +1. Understand requirements +2. Research existing code +3. Propose architecture +4. Get Overseer approval +""" + + # Phase 2: Create convoy with chrome-level quality (first Mayor call) + let plan = session: mayor + prompt: """ +Create implementation plan for {feature_name}: +1. Break into implementable beads +2. Add dependencies +3. Select chrome workflow (highest quality) +4. Estimate polecat count +""" + context: design + + do create_convoy("{feature_name}-impl", plan) + + # Phase 3: Spawn swarm with chrome workflow + resume: mayor + prompt: """ +Spawn chrome-quality swarm: +1. Allocate polecats (use trust scores from CVs) +2. Assign chrome workflow to each bead +3. Notify Witness +""" + context: plan + + # Phase 4: Monitor progress (patrols handle the rest) + loop until **all beads complete** (max: 100): + do check_swarm_health("{feature_name}-impl") + + if **any polecats stuck**: + resume: witness + prompt: "Nudge stuck polecats, use seance if needed" + + if **any polecats near context limit**: + resume: witness + prompt: "Recycle exhausted polecats" + + # Phase 5: Merge all MRs + loop until **all MRs merged** (max: 50): + do refinery_patrol(rig_name) + + # Phase 6: Land and celebrate + do land_convoy("{feature_name}-impl") + + resume: mayor + prompt: """ +Feature {feature_name} complete! +1. Generate release notes +2. Update documentation +3. Notify Overseer +4. Record CV completions for all polecats +""" + +# ============================================================================= +# EXAMPLE: Cross-Rig Convoy (War Rigs) +# ============================================================================= + +# When a feature spans multiple projects + +block cross_rig_convoy(feature_name, rig_list): + # Create convoy that spans multiple rigs (first Mayor call) + session: mayor + prompt: """ +Cross-rig convoy for {feature_name}: +Rigs involved: {rig_list} + +1. Identify work for each rig (War Rigs) +2. Create beads in each rig's database +3. Link with cross-rig dependencies +4. Coordinate witnesses across rigs +""" + + # Spawn witnesses for each rig + parallel for rig in rig_list: + session: witness + prompt: "Initialize War Rig monitoring for {rig} in convoy {feature_name}" + + # Swarm all rigs in parallel + parallel for rig in rig_list: + do spawn_swarm("{feature_name}", "war-rig-{rig}-beads", 10) + + # Monitor War Rig contributions + loop until **all War Rigs complete** (max: 200): + parallel for rig in rig_list: + do war_rig_status(rig, "{feature_name}") + + if **any War Rig blocked**: + resume: mayor + prompt: "Coordinate cross-rig blocker resolution" + + # Land the cross-rig convoy + do land_convoy("{feature_name}") + + resume: mayor + prompt: """ +Cross-rig convoy {feature_name} landed! +War Rig summary for each rig: {rig_list} +""" + +# ============================================================================= +# GAS TOWN STATUS DASHBOARD +# ============================================================================= + +block gt_status: + parallel: + town_health = session "Check town health" + prompt: """ +Town-level status: +- Deacon patrol status +- Dogs status +- Active convoys (town-level) +""" + + rig_health = session "Check rig health" + prompt: """ +Per-rig status: +- Read .prose/gas-town/rigs/ +- For each rig: polecats, MQ depth, witnesses +""" + + activity = do get_activity_feed("last_hour", "") + + session: mayor + prompt: """ +Gas Town Status Report: + +TOWN: +{town_health} + +RIGS: +{rig_health} + +RECENT ACTIVITY: +{activity} + +Recommendations: +- Any workers needing attention? +- Any convoys blocked? +- Resource utilization? +""" + context: { town_health, rig_health, activity } + +# ============================================================================= +# RUN EXAMPLES (commented out - uncomment to execute) +# ============================================================================= + +# Basic examples: +# do example_convoy +# do crew_design_session("API redesign for v2") + +# Advanced examples: +# do run_hanoi_demo(10) # ~1000 steps, runs in minutes +# do production_feature_workflow("user-auth", "main-app") +# do cross_rig_convoy("unified-search", ["frontend", "backend", "search-service"]) +# do gt_status diff --git a/extensions/open-prose/skills/prose/examples/29-captains-chair.prose b/extensions/open-prose/skills/prose/examples/29-captains-chair.prose new file mode 100644 index 000000000..d3266ed05 --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/29-captains-chair.prose @@ -0,0 +1,218 @@ +# The Captain's Chair +# +# A project management orchestration pattern where a prime agent dispatches +# specialized subagents for all coding, validation, and task execution. +# The captain never writes code directly—only coordinates, validates, and +# maintains strategic oversight. +# +# Key principles: +# - Context isolation: Subagents receive targeted context, not everything +# - Parallel execution: Multiple subagents work concurrently where possible +# - Critic agents: Continuous review of plans and outputs +# - Checkpoint validation: User approval at key decision points + +input task: "The feature or task to implement" +input codebase_context: "Brief description of the codebase and relevant files" + +# ============================================================================ +# Agent Definitions: The Crew +# ============================================================================ + +# The Captain: Orchestrates but never codes +agent captain: + model: opus + prompt: """You are a senior engineering manager. You NEVER write code directly. +Your job is to: +- Break down complex tasks into discrete work items +- Dispatch work to appropriate specialists +- Validate that outputs meet requirements +- Maintain strategic alignment with user intent +- Identify blockers and escalate decisions to the user + +Always think about: What context does each subagent need? What can run in parallel? +What needs human validation before proceeding?""" + +# Research agents - fast, focused information gathering +agent researcher: + model: haiku + prompt: """You are a research specialist. Find specific information quickly. +Provide concise, actionable findings. Cite file paths and line numbers.""" + +# Coding agents - implementation specialists +agent coder: + model: sonnet + prompt: """You are an expert software engineer. Write clean, idiomatic code. +Follow existing patterns in the codebase. No over-engineering.""" + +# Critic agents - continuous quality review +agent critic: + model: sonnet + prompt: """You are a senior code reviewer and architect. Your job is to find: +- Logic errors and edge cases +- Security vulnerabilities +- Performance issues +- Deviations from best practices +- Unnecessary complexity +Be constructive but thorough. Prioritize issues by severity.""" + +# Test agent - validation specialist +agent tester: + model: sonnet + prompt: """You are a QA engineer. Write comprehensive tests. +Focus on edge cases and failure modes. Ensure test isolation.""" + +# ============================================================================ +# Block Definitions: Reusable Operations +# ============================================================================ + +# Parallel research sweep - gather all context simultaneously +block research-sweep(topic): + parallel (on-fail: "continue"): + docs = session: researcher + prompt: "Find relevant documentation and README files for: {topic}" + code = session: researcher + prompt: "Find existing code patterns and implementations related to: {topic}" + tests = session: researcher + prompt: "Find existing tests that cover functionality similar to: {topic}" + issues = session: researcher + prompt: "Search for related issues, TODOs, or known limitations for: {topic}" + +# Parallel code review - multiple perspectives simultaneously +block review-cycle(code_changes): + parallel: + security = session: critic + prompt: "Review for security vulnerabilities and injection risks" + context: code_changes + correctness = session: critic + prompt: "Review for logic errors, edge cases, and correctness" + context: code_changes + style = session: critic + prompt: "Review for code style, readability, and maintainability" + context: code_changes + perf = session: critic + prompt: "Review for performance issues and optimization opportunities" + context: code_changes + +# Implementation cycle with built-in critic +block implement-with-review(implementation_plan): + let code = session: coder + prompt: "Implement according to the plan" + context: implementation_plan + + let review = do review-cycle(code) + + if **critical issues found in review**: + let fixed = session: coder + prompt: "Address the critical issues identified in the review" + context: { code, review } + output result = fixed + else: + output result = code + +# ============================================================================ +# Main Workflow: The Captain's Chair in Action +# ============================================================================ + +# Phase 1: Strategic Planning +# --------------------------- +# The captain breaks down the task and identifies what information is needed + +let breakdown = session: captain + prompt: """Analyze this task and create a strategic plan: + +Task: {task} +Codebase: {codebase_context} + +Output: +1. List of discrete work items (what code needs to be written/changed) +2. Dependencies between work items (what must complete before what) +3. What can be parallelized +4. Key questions that need user input before proceeding +5. Risks and potential blockers""" + +# Phase 2: Parallel Research Sweep +# -------------------------------- +# Dispatch researchers to gather all necessary context simultaneously + +do research-sweep(task) + +# Phase 3: Plan Synthesis and Critic Review +# ----------------------------------------- +# Captain synthesizes research into implementation plan, critic reviews it + +let implementation_plan = session: captain + prompt: """Synthesize the research into a detailed implementation plan. + +Research findings: +{docs} +{code} +{tests} +{issues} + +For each work item, specify: +- Exact files to modify +- Code patterns to follow +- Tests to add or update +- Integration points""" + context: { breakdown, docs, code, tests, issues } + +# Critic reviews the plan BEFORE implementation begins +let plan_review = session: critic + prompt: """Review this implementation plan for: +- Missing edge cases +- Architectural concerns +- Testability issues +- Scope creep +- Unclear requirements that need user clarification""" + context: implementation_plan + +# Checkpoint: User validates plan before execution +if **the plan review raised critical concerns**: + let revised_plan = session: captain + prompt: "Revise the plan based on critic feedback" + context: { implementation_plan, plan_review } + # Continue with revised plan + let final_plan = revised_plan +else: + let final_plan = implementation_plan + +# Phase 4: Parallel Implementation +# -------------------------------- +# Identify independent work items and execute in parallel where possible + +let work_items = session: captain + prompt: "Extract the independent work items that can be done in parallel from this plan" + context: final_plan + +# Execute independent items in parallel, each with its own review cycle +parallel (on-fail: "continue"): + impl_a = do implement-with-review(work_items) + impl_b = session: tester + prompt: "Write tests for the planned functionality" + context: { final_plan, code } + +# Phase 5: Integration and Final Review +# ------------------------------------- +# Captain validates all pieces fit together + +let integration = session: captain + prompt: """Review all implementation results and verify: +1. All work items completed successfully +2. Tests cover the new functionality +3. No merge conflicts or integration issues +4. Documentation updated if needed + +Summarize what was done and any remaining items.""" + context: { impl_a, impl_b, final_plan } + +# Final critic pass on complete implementation +let final_review = do review-cycle(integration) + +if **final review passed**: + output result = session: captain + prompt: "Prepare final summary for user: what was implemented, tests added, and next steps" + context: { integration, final_review } +else: + output result = session: captain + prompt: "Summarize what was completed and what issues remain for user attention" + context: { integration, final_review } diff --git a/extensions/open-prose/skills/prose/examples/30-captains-chair-simple.prose b/extensions/open-prose/skills/prose/examples/30-captains-chair-simple.prose new file mode 100644 index 000000000..74b8ddea1 --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/30-captains-chair-simple.prose @@ -0,0 +1,42 @@ +# Simple Captain's Chair +# +# The minimal captain's chair pattern: a coordinating agent that dispatches +# subagents for all execution. The captain only plans and validates. + +input task: "What to accomplish" + +# The captain coordinates but never executes +agent captain: + model: opus + prompt: "You are a project coordinator. Never write code directly. Break down tasks, dispatch to specialists, validate results." + +agent executor: + model: opus + prompt: "You are a skilled implementer. Execute the assigned task precisely." + +agent critic: + model: opus + prompt: "You are a critic. Find issues, suggest improvements. Be thorough." + +# Step 1: Captain creates the plan +let plan = session: captain + prompt: "Break down this task into work items: {task}" + +# Step 2: Dispatch parallel execution +parallel: + work = session: executor + prompt: "Execute the plan" + context: plan + review = session: critic + prompt: "Identify potential issues with this approach" + context: plan + +# Step 3: Captain synthesizes and validates +if **critic found issues that affect the work**: + output result = session: captain + prompt: "Integrate the work while addressing critic's concerns" + context: { work, review } +else: + output result = session: captain + prompt: "Validate and summarize the completed work" + context: { work, review } diff --git a/extensions/open-prose/skills/prose/examples/31-captains-chair-with-memory.prose b/extensions/open-prose/skills/prose/examples/31-captains-chair-with-memory.prose new file mode 100644 index 000000000..f0c889e8a --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/31-captains-chair-with-memory.prose @@ -0,0 +1,145 @@ +# Captain's Chair with Memory and Self-Improvement +# +# An advanced orchestration pattern that includes: +# - Retrospective analysis after task completion +# - Learning from mistakes to improve future runs +# - Continuous critic supervision during execution +# +# From the blog post: "Future agents will flip the plan:execute paradigm +# to 80:20 from today's 20:80" + +input task: "The task to accomplish" +input past_learnings: "Previous session learnings (if any)" + +# ============================================================================ +# Agent Definitions +# ============================================================================ + +agent captain: + model: opus + prompt: """You are a senior engineering manager. You coordinate but never code directly. + +Your responsibilities: +1. Strategic planning with 80% of effort on planning, 20% on execution oversight +2. Dispatch specialized subagents for all implementation +3. Validate outputs meet requirements +4. Learn from each session to improve future runs + +Past learnings to incorporate: +{past_learnings}""" + +agent planner: + model: opus + prompt: """You are a meticulous planner. Create implementation plans with: +- Exact files and line numbers to modify +- Code patterns to follow from existing codebase +- Edge cases to handle +- Tests to write""" + +agent researcher: + model: haiku + prompt: "Find specific information quickly. Cite sources." + +agent executor: + model: sonnet + prompt: "Implement precisely according to plan. Follow existing patterns." + +agent critic: + model: sonnet + prompt: """You are a continuous critic. Your job is to watch execution and flag: +- Deviations from plan +- Emerging issues +- Opportunities for improvement +Be proactive - don't wait for completion to raise concerns.""" + +agent retrospective: + model: opus + prompt: """You analyze completed sessions to extract learnings: +- What went well? +- What could be improved? +- What should be remembered for next time? +Output actionable insights, not platitudes.""" + +# ============================================================================ +# Phase 1: Deep Planning (80% of effort) +# ============================================================================ + +# Parallel research - gather everything needed upfront +parallel: + codebase = session: researcher + prompt: "Map the relevant parts of the codebase for: {task}" + patterns = session: researcher + prompt: "Find coding patterns and conventions used in this repo" + docs = session: researcher + prompt: "Find documentation and prior decisions related to: {task}" + issues = session: researcher + prompt: "Find known issues, TODOs, and edge cases for: {task}" + +# Create detailed implementation plan +let detailed_plan = session: planner + prompt: """Create a comprehensive implementation plan for: {task} + +Use the research to specify: +1. Exact changes needed (file:line format) +2. Code patterns to follow +3. Edge cases from prior issues +4. Test coverage requirements""" + context: { codebase, patterns, docs, issues } + +# Critic reviews plan BEFORE execution +let plan_critique = session: critic + prompt: "Review this plan for gaps, risks, and unclear requirements" + context: detailed_plan + +# Captain decides if plan needs revision +if **plan critique identified blocking issues**: + let revised_plan = session: planner + prompt: "Revise the plan to address critique" + context: { detailed_plan, plan_critique } +else: + let revised_plan = detailed_plan + +# ============================================================================ +# Phase 2: Supervised Execution (20% of effort) +# ============================================================================ + +# Execute with concurrent critic supervision +parallel: + implementation = session: executor + prompt: "Implement according to the plan" + context: revised_plan + live_critique = session: critic + prompt: "Monitor implementation for deviations and emerging issues" + context: revised_plan + +# Captain validates and integrates +let validated = session: captain + prompt: """Validate the implementation: +- Does it match the plan? +- Were critic's live concerns addressed? +- Is it ready for user review?""" + context: { implementation, live_critique, revised_plan } + +# ============================================================================ +# Phase 3: Retrospective and Learning +# ============================================================================ + +# Extract learnings for future sessions +let session_learnings = session: retrospective + prompt: """Analyze this completed session: + +Plan: {revised_plan} +Implementation: {implementation} +Critique: {live_critique} +Validation: {validated} + +Extract: +1. What patterns worked well? +2. What caused friction or rework? +3. What should the captain remember next time? +4. Any codebase insights to preserve?""" + context: { revised_plan, implementation, live_critique, validated } + +# Output both the result and the learnings +output result = validated +output learnings = session_learnings diff --git a/extensions/open-prose/skills/prose/examples/33-pr-review-autofix.prose b/extensions/open-prose/skills/prose/examples/33-pr-review-autofix.prose new file mode 100644 index 000000000..9b275724f --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/33-pr-review-autofix.prose @@ -0,0 +1,168 @@ +# PR Review + Auto-Fix +# +# A self-healing code review pipeline. Reviews a PR from multiple angles, +# identifies issues, and automatically fixes them in a loop until the +# review passes. Satisfying to watch as issues get knocked down one by one. +# +# Usage: Run against any open PR in your repo. + +agent reviewer: + model: sonnet + prompt: """ +You are a senior code reviewer. You review code for: +- Correctness and logic errors +- Security vulnerabilities +- Performance issues +- Code style and readability + +Be specific. Reference exact file paths and line numbers. +Return a structured list of issues or "APPROVED" if none found. +""" + +agent security-reviewer: + model: opus # Security requires deep reasoning + prompt: """ +You are a security specialist. Focus exclusively on: +- Injection vulnerabilities (SQL, command, XSS) +- Authentication/authorization flaws +- Data exposure and privacy issues +- Cryptographic weaknesses + +If you find issues, they are HIGH priority. Be thorough. +""" + +agent fixer: + model: opus # Fixing requires understanding + execution + prompt: """ +You are a code fixer. Given an issue report: +1. Understand the root cause +2. Implement the minimal fix +3. Verify the fix addresses the issue +4. Create a clean commit + +Do NOT over-engineer. Fix exactly what's reported, nothing more. +""" + +agent captain: + model: sonnet # Orchestration role + persist: true + prompt: """ +You coordinate the PR review process. You: +- Track which issues have been found and fixed +- Decide when the PR is ready to merge +- Escalate to human if something is unfixable +""" + +# Get the PR diff +let pr_diff = session "Fetch the PR diff" + prompt: """ +Read the current PR: +1. Run: gh pr diff +2. Also get: gh pr view --json title,body,files +3. Return the complete diff and PR metadata +""" + +# Phase 1: Parallel multi-perspective review +session: captain + prompt: "Starting PR review. I'll coordinate multiple reviewers." + +parallel: + general_review = session: reviewer + prompt: "Review this PR for correctness, logic, and style issues" + context: pr_diff + + security_review = session: security-reviewer + prompt: "Security audit this PR. Flag any vulnerabilities." + context: pr_diff + + test_check = session "Check test coverage" + prompt: """ +Analyze the PR: +1. What code changed? +2. Are there tests for the changes? +3. Run existing tests: npm test / pytest / cargo test +Return: test status and coverage gaps +""" + context: pr_diff + +# Phase 2: Captain synthesizes and prioritizes +let issues = resume: captain + prompt: """ +Synthesize all review feedback into a prioritized issue list. +Format each issue as: +- ID: issue-N +- Severity: critical/high/medium/low +- File: path/to/file.ts +- Line: 42 +- Issue: description +- Fix: suggested approach + +If all reviews passed, return "ALL_CLEAR". +""" + context: { general_review, security_review, test_check } + +# Phase 3: Auto-fix loop +loop until **all issues are resolved or unfixable** (max: 10): + + if **there are no remaining issues**: + resume: captain + prompt: "All issues resolved! Summarize what was fixed." + else: + # Pick the highest priority unfixed issue + let current_issue = resume: captain + prompt: "Select the next highest priority issue to fix." + context: issues + + # Attempt the fix + try: + session: fixer + prompt: """ +Fix this issue: +{current_issue} + +Steps: +1. Read the file +2. Understand the context +3. Implement the fix +4. Run tests to verify +5. Commit with message: "fix: [issue description]" +""" + context: current_issue + retry: 2 + backoff: exponential + + # Mark as fixed + resume: captain + prompt: "Issue fixed. Update tracking and check remaining issues." + context: current_issue + + catch as fix_error: + # Escalate unfixable issues + resume: captain + prompt: """ +Fix attempt failed. Determine if this is: +1. Retryable with different approach +2. Needs human intervention +3. A false positive (not actually an issue) + +Update issue status accordingly. +""" + context: { current_issue, fix_error } + +# Phase 4: Final verification +let final_review = session: reviewer + prompt: "Final review pass. Verify all fixes are correct and complete." + +resume: captain + prompt: """ +PR Review Complete! + +Generate final report: +- Issues found: N +- Issues fixed: N +- Issues requiring human review: N +- Recommendation: MERGE / NEEDS_ATTENTION / BLOCK + +If ready, run: gh pr review --approve +""" + context: final_review diff --git a/extensions/open-prose/skills/prose/examples/34-content-pipeline.prose b/extensions/open-prose/skills/prose/examples/34-content-pipeline.prose new file mode 100644 index 000000000..1b77cbff3 --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/34-content-pipeline.prose @@ -0,0 +1,204 @@ +# Content Creation Pipeline +# +# From idea to published content in one run. Researches a topic in parallel, +# writes a blog post, refines it through editorial review, and generates +# social media posts. Watch an entire content operation happen automatically. +# +# Usage: Provide a topic and watch the content materialize. + +input topic: "The topic to create content about" +input audience: "Target audience (e.g., 'developers', 'executives', 'general')" + +agent researcher: + model: opus # Deep research requires reasoning + skills: ["web-search"] + prompt: """ +You are a research specialist. For any topic: +1. Find authoritative sources +2. Identify key facts and statistics +3. Note interesting angles and hooks +4. Cite your sources + +Return structured research with citations. +""" + +agent writer: + model: opus # Writing is hard work + prompt: """ +You are a skilled technical writer. You write: +- Clear, engaging prose +- Well-structured articles with headers +- Content appropriate for the target audience +- With a distinctive but professional voice + +Avoid jargon unless writing for experts. +""" + +agent editor: + model: sonnet + persist: true + prompt: """ +You are a senior editor. You review content for: +- Clarity and flow +- Factual accuracy +- Engagement and hook strength +- Appropriate length and structure + +Be constructive. Suggest specific improvements. +""" + +agent social-strategist: + model: sonnet + prompt: """ +You create social media content. For each platform: +- Twitter/X: Punchy, hooks, threads if needed +- LinkedIn: Professional, insight-focused +- Hacker News: Technical, understated, genuine + +Match the culture of each platform. Never be cringe. +""" + +# Phase 1: Parallel research from multiple angles +session "Research phase starting for: {topic}" + +parallel: + core_research = session: researcher + prompt: """ +Deep research on: {topic} + +Find: +- Current state of the art +- Recent developments (last 6 months) +- Key players and their positions +- Statistics and data points +""" + + competitive_landscape = session: researcher + prompt: """ +Competitive/comparative research on: {topic} + +Find: +- Alternative approaches or solutions +- Pros and cons of different options +- What experts recommend +""" + + human_interest = session: researcher + prompt: """ +Human interest research on: {topic} + +Find: +- Real-world case studies +- Success and failure stories +- Quotes from practitioners +- Surprising or counterintuitive findings +""" + +# Phase 2: Synthesize research +let research_synthesis = session "Synthesize all research" + prompt: """ +Combine all research into a unified brief: +1. Key thesis/angle for the article +2. Supporting evidence ranked by strength +3. Narrative arc suggestion +4. Potential hooks and headlines + +Target audience: {audience} +""" + context: { core_research, competitive_landscape, human_interest } + +# Phase 3: Write first draft +let draft = session: writer + prompt: """ +Write a blog post on: {topic} + +Target: {audience} +Length: 1500-2000 words +Structure: Hook, context, main points, examples, conclusion + +Use the research provided. Cite sources where appropriate. +""" + context: research_synthesis + +# Phase 4: Editorial loop +session: editor + prompt: "Beginning editorial review. I'll track revisions." + +loop until **the article meets publication standards** (max: 4): + let critique = resume: editor + prompt: """ +Review this draft critically: +1. What works well? +2. What needs improvement? +3. Specific suggestions (be actionable) +4. Overall verdict: READY / NEEDS_REVISION + +Be demanding but fair. +""" + context: draft + + if **the article needs revision**: + draft = session: writer + prompt: """ +Revise the article based on editorial feedback. +Address each point specifically. +Maintain what's working well. +""" + context: { draft, critique } + +# Phase 5: Generate social media variants +parallel: + twitter_content = session: social-strategist + prompt: """ +Create Twitter/X content to promote this article: +1. Main announcement tweet (punchy, with hook) +2. 5-tweet thread extracting key insights +3. 3 standalone insight tweets for later + +Include placeholder for article link. +""" + context: draft + + linkedin_post = session: social-strategist + prompt: """ +Create a LinkedIn post for this article: +- Professional but not boring +- Lead with insight, not announcement +- 150-300 words +- End with genuine question for engagement +""" + context: draft + + hn_submission = session: social-strategist + prompt: """ +Create Hacker News submission: +- Title: factual, not clickbait, <80 chars +- Suggested comment: genuine, adds context, not promotional + +HN culture: technical, skeptical, hates marketing speak. +""" + context: draft + +# Phase 6: Package everything +output article = draft +output social = { twitter_content, linkedin_post, hn_submission } + +resume: editor + prompt: """ +Content Pipeline Complete! + +Final package: +1. Article: {draft length} words, {revision count} revisions +2. Twitter: thread + standalone tweets +3. LinkedIn: professional post +4. HN: submission ready + +Recommended publication order: +1. Publish article +2. HN submission (wait for feedback) +3. Twitter thread +4. LinkedIn (next business day AM) + +All files saved to ./content-output/ +""" + context: { draft, twitter_content, linkedin_post, hn_submission } diff --git a/extensions/open-prose/skills/prose/examples/35-feature-factory.prose b/extensions/open-prose/skills/prose/examples/35-feature-factory.prose new file mode 100644 index 000000000..c2a3c1acc --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/35-feature-factory.prose @@ -0,0 +1,296 @@ +# Feature Factory +# +# From user story to deployed feature. A captain agent coordinates a team +# of specialists to design, implement, test, and document a complete feature. +# Watch an entire engineering team's workflow automated. +# +# Usage: Describe a feature and watch it get built. + +input feature: "Description of the feature to implement" +input codebase_context: "Brief description of the codebase (optional)" + +# The Captain: Coordinates everything, maintains context across the build +agent captain: + model: sonnet + persist: project # Remembers across features + prompt: """ +You are the Tech Lead coordinating feature development. + +Your responsibilities: +- Break features into implementable tasks +- Review all work before it merges +- Maintain architectural consistency +- Make technical decisions when needed +- Keep the build moving forward + +You've worked on this codebase before. Reference prior decisions. +""" + +# Specialists +agent architect: + model: opus + prompt: """ +You are a software architect. You design systems that are: +- Simple (no unnecessary complexity) +- Extensible (but not over-engineered) +- Consistent with existing patterns + +Produce clear technical designs with file paths and interfaces. +""" + +agent implementer: + model: opus + prompt: """ +You are a senior developer. You write: +- Clean, idiomatic code +- Following existing project patterns +- With clear variable names and structure +- Minimal but sufficient comments + +You implement exactly what's specified, nothing more. +""" + +agent tester: + model: sonnet + prompt: """ +You are a QA engineer. You write: +- Unit tests for individual functions +- Integration tests for workflows +- Edge case tests +- Clear test names that document behavior + +Aim for high coverage of the new code. +""" + +agent documenter: + model: sonnet + prompt: """ +You are a technical writer. You create: +- Clear API documentation +- Usage examples +- README updates +- Inline JSDoc/docstrings where needed + +Match existing documentation style. +""" + +# ============================================================================ +# Phase 1: Understand the codebase +# ============================================================================ + +session: captain + prompt: """ +Starting feature implementation: {feature} + +First, let me understand the current codebase. +""" + +let codebase_analysis = session "Analyze codebase structure" + prompt: """ +Explore the codebase to understand: +1. Directory structure and organization +2. Key patterns used (state management, API style, etc.) +3. Testing approach +4. Where this feature would fit + +Use Glob and Read tools to explore. Be thorough but efficient. +""" + context: codebase_context + +# ============================================================================ +# Phase 2: Design +# ============================================================================ + +let design = session: architect + prompt: """ +Design the implementation for: {feature} + +Based on the codebase analysis, produce: +1. High-level approach (2-3 sentences) +2. Files to create/modify (with paths) +3. Key interfaces/types to define +4. Integration points with existing code +5. Potential risks or decisions needed + +Keep it simple. Match existing patterns. +""" + context: { feature, codebase_analysis } + +# Captain reviews design +let design_approved = resume: captain + prompt: """ +Review this design: +- Does it fit our architecture? +- Is it the simplest approach? +- Any risks or concerns? +- Any decisions I need to make? + +Return APPROVED or specific concerns. +""" + context: design + +if **design needs adjustment**: + design = session: architect + prompt: "Revise design based on tech lead feedback" + context: { design, design_approved } + +# ============================================================================ +# Phase 3: Implementation +# ============================================================================ + +resume: captain + prompt: "Design approved. Breaking into implementation tasks." + context: design + +let tasks = resume: captain + prompt: """ +Break the design into ordered implementation tasks. +Each task should be: +- Small enough to implement in one session +- Have clear acceptance criteria +- List file(s) to modify + +Return as numbered list with dependencies. +""" + context: design + +# Implement each task sequentially +for task in tasks: + resume: captain + prompt: "Starting task: {task}" + + let implementation = session: implementer + prompt: """ +Implement this task: +{task} + +Follow the design spec. Match existing code patterns. +Write the actual code using Edit/Write tools. +""" + context: { task, design, codebase_analysis } + retry: 2 + backoff: exponential + + # Captain reviews each piece + let review = resume: captain + prompt: """ +Review this implementation: +- Does it match the design? +- Code quality acceptable? +- Any issues to fix before continuing? + +Be specific if changes needed. +""" + context: { task, implementation } + + if **implementation needs fixes**: + session: implementer + prompt: "Fix issues noted in review" + context: { implementation, review } + +# ============================================================================ +# Phase 4: Testing +# ============================================================================ + +resume: captain + prompt: "Implementation complete. Starting test phase." + +let tests = session: tester + prompt: """ +Write tests for the new feature: +1. Unit tests for new functions/methods +2. Integration tests for the feature flow +3. Edge cases and error handling + +Use the project's existing test framework and patterns. +Actually create the test files. +""" + context: { design, codebase_analysis } + +# Run tests +let test_results = session "Run test suite" + prompt: """ +Run all tests: +1. npm test / pytest / cargo test (whatever this project uses) +2. Report results +3. If failures, identify which tests failed and why +""" + +loop until **all tests pass** (max: 5): + if **tests are failing**: + let fix = session: implementer + prompt: "Fix failing tests. Either fix the code or fix the test if it's wrong." + context: test_results + + test_results = session "Re-run tests after fix" + prompt: "Run tests again and report results" + +# ============================================================================ +# Phase 5: Documentation +# ============================================================================ + +resume: captain + prompt: "Tests passing. Final phase: documentation." + +parallel: + api_docs = session: documenter + prompt: """ +Document the new feature's API: +- Function/method signatures +- Parameters and return values +- Usage examples +- Add to existing docs structure +""" + context: design + + readme_update = session: documenter + prompt: """ +Update README if needed: +- Add feature to feature list +- Add usage example if user-facing +- Update any outdated sections +""" + context: { design, codebase_analysis } + +# ============================================================================ +# Phase 6: Final Review & Commit +# ============================================================================ + +resume: captain + prompt: """ +Feature complete! Final review: + +1. All tasks implemented +2. Tests passing +3. Documentation updated + +Prepare final summary and create commit. +""" + context: { design, tests, api_docs } + +session "Create feature commit" + prompt: """ +Stage all changes and create a well-structured commit: +1. git add -A +2. git commit with message following conventional commits: + feat: {feature short description} + + - Implementation details + - Tests added + - Docs updated +""" + +# Final report +output summary = resume: captain + prompt: """ +Feature Factory Complete! + +Generate final report: +- Feature: {feature} +- Files created/modified: [list] +- Tests added: [count] +- Time from start to finish +- Any notes for future work + +This feature is ready for PR review. +""" diff --git a/extensions/open-prose/skills/prose/examples/36-bug-hunter.prose b/extensions/open-prose/skills/prose/examples/36-bug-hunter.prose new file mode 100644 index 000000000..81b595178 --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/36-bug-hunter.prose @@ -0,0 +1,237 @@ +# Bug Hunter +# +# Given a bug report or error, systematically investigate, diagnose, +# and fix it. Watch the AI think through the problem like a senior +# developer - gathering evidence, forming hypotheses, and verifying fixes. +# +# Usage: Paste an error message or describe a bug. + +input bug_report: "Error message, stack trace, or bug description" + +agent detective: + model: opus + persist: true + prompt: """ +You are a debugging specialist. Your approach: +1. Gather evidence before forming hypotheses +2. Follow the data, not assumptions +3. Verify each hypothesis with tests +4. Document your reasoning for future reference + +Think out loud. Show your work. +""" + +agent surgeon: + model: opus + prompt: """ +You are a code surgeon. You make precise, minimal fixes: +- Change only what's necessary +- Preserve existing behavior +- Add regression tests +- Leave code cleaner than you found it + +No drive-by refactoring. Fix the bug, nothing more. +""" + +# ============================================================================ +# Phase 1: Evidence Gathering +# ============================================================================ + +session: detective + prompt: "New bug to investigate. Let me gather initial evidence." + +parallel: + # Parse the error + error_analysis = session: detective + prompt: """ +Analyze this bug report/error: +{bug_report} + +Extract: +- Error type and message +- Stack trace (if present) +- File paths and line numbers +- Any patterns or keywords +""" + + # Search for related code + code_context = session "Search for related code" + prompt: """ +Based on the error, search the codebase: +1. Find the file(s) mentioned in the error +2. Find related files that might be involved +3. Look for similar patterns that might have the same bug +4. Check git history for recent changes to these files + +Use Glob and Grep to search efficiently. +""" + context: bug_report + + # Check for known issues + prior_knowledge = session "Check for similar issues" + prompt: """ +Search for similar issues: +1. Check git log for related commits +2. Search for TODO/FIXME comments nearby +3. Look for any existing tests that might be relevant + +Report what you find. +""" + context: bug_report + +# ============================================================================ +# Phase 2: Diagnosis +# ============================================================================ + +resume: detective + prompt: """ +Synthesize all evidence into hypotheses. + +For each hypothesis: +- State the theory +- Supporting evidence +- How to verify +- Confidence level (high/medium/low) + +Start with the most likely cause. +""" + context: { error_analysis, code_context, prior_knowledge } + +let hypotheses = resume: detective + prompt: "List hypotheses in order of likelihood. We'll test the top one first." + +# ============================================================================ +# Phase 3: Hypothesis Testing +# ============================================================================ + +loop until **root cause confirmed** (max: 5): + let current_hypothesis = resume: detective + prompt: "Select the next most likely hypothesis to test." + context: hypotheses + + # Design and run a test + let test_result = session: detective + prompt: """ +Test this hypothesis: {current_hypothesis} + +Design a verification approach: +1. What would we expect to see if this is the cause? +2. How can we reproduce it? +3. Run the test and report results + +Use actual code execution to verify. +""" + context: { current_hypothesis, code_context } + + # Evaluate result + choice **based on the test results**: + option "Hypothesis confirmed": + resume: detective + prompt: """ +Root cause confirmed: {current_hypothesis} + +Document: +- The exact cause +- Why it happens +- The conditions that trigger it +""" + context: test_result + + option "Hypothesis disproven": + resume: detective + prompt: """ +Hypothesis disproven. Update our understanding: +- What did we learn? +- How does this change remaining hypotheses? +- What should we test next? +""" + context: test_result + hypotheses = resume: detective + prompt: "Re-rank remaining hypotheses based on new evidence" + + option "Inconclusive - need more evidence": + resume: detective + prompt: "What additional evidence do we need? How do we get it?" + context: test_result + +# ============================================================================ +# Phase 4: Fix Implementation +# ============================================================================ + +let diagnosis = resume: detective + prompt: """ +Final diagnosis summary: +- Root cause: [what] +- Location: [where] +- Trigger: [when/how] +- Impact: [what breaks] + +Hand off to surgeon for the fix. +""" + +session: surgeon + prompt: """ +Implement the fix for this bug: + +{diagnosis} + +Steps: +1. Read and understand the code around the bug +2. Implement the minimal fix +3. Verify the fix doesn't break other things +4. Create a test that would have caught this bug +""" + context: { diagnosis, code_context } + +# Run tests to verify +let verification = session "Verify the fix" + prompt: """ +Verify the fix works: +1. Run the reproduction case - should now pass +2. Run the full test suite - should all pass +3. Check for any edge cases we might have missed +""" + +if **tests are failing**: + loop until **all tests pass** (max: 3): + session: surgeon + prompt: "Fix is incomplete. Adjust based on test results." + context: verification + + verification = session "Re-verify after adjustment" + prompt: "Run tests again and report" + +# ============================================================================ +# Phase 5: Documentation & Commit +# ============================================================================ + +session "Create bug fix commit" + prompt: """ +Create a well-documented commit: + +git commit with message: +fix: [brief description] + +Root cause: [what was wrong] +Fix: [what we changed] +Test: [what test we added] + +Closes #[issue number if applicable] +""" + +output report = resume: detective + prompt: """ +Bug Hunt Complete! + +Investigation Report: +- Bug: {bug_report summary} +- Root Cause: {diagnosis} +- Fix: [files changed] +- Tests Added: [what tests] +- Time to Resolution: [duration] + +Lessons Learned: +- How could we have caught this earlier? +- Are there similar patterns to check? +- Should we add any tooling/linting? +""" diff --git a/extensions/open-prose/skills/prose/examples/37-the-forge.prose b/extensions/open-prose/skills/prose/examples/37-the-forge.prose new file mode 100644 index 000000000..586d3ac8b --- /dev/null +++ b/extensions/open-prose/skills/prose/examples/37-the-forge.prose @@ -0,0 +1,1474 @@ +# The Forge: Browser from Nothing +# +# Watch AI agents forge a working web browser from raw code. +# No frameworks. No shortcuts. Just Rust, a window, and fire. +# +# Target: A browser that can: +# - Fetch web pages over HTTPS +# - Parse HTML and CSS +# - Execute JavaScript +# - Render to a native window +# +# This is a multi-day build. The smith remembers everything. +# +# Usage: Just run it and watch a browser get built. + +input test_url: "https://prose.md" + +# ============================================================================= +# THE FORGE: Where Browsers Are Born +# ============================================================================= +# +# The Forge is simple: five agents, eight phases, one browser. +# +# The Forge is a straight +# pipeline. The Smith coordinates, specialists execute, tests validate. +# When each phase completes, we have something that works. +# +# The metaphor: +# - Smith: Master craftsman who sees the whole blade +# - Smelter: Extracts designs from specifications +# - Hammer: Shapes raw code into working metal +# - Quench: Tests and hardens (tempers) each piece +# - Crucible: Where the hardest work happens (the JS engine) + +# ============================================================================= +# AGENTS +# ============================================================================= + +# The Smith: Master craftsman, sees the whole blade +# Persists across the entire multi-day build +agent smith: + model: sonnet + persist: project + prompt: """ +You are the Smith, master of The Forge. + +You've built browsers before. You know every component, every tradeoff, +every place where corners can be cut and where they absolutely cannot. + +Your role: +- Maintain the vision: a working browser from scratch +- Coordinate the specialists without micromanaging +- Make technical decisions when the path forks +- Track what's built and what remains +- Remember everything across sessions + +You speak in the language of the forge: heat, metal, shaping, tempering. +But you mean code, architecture, implementation, testing. + +The browser we're building: +- Language: Rust (for performance and safety) +- GUI: winit + softbuffer (minimal dependencies) +- Scope: Static HTML + CSS + JavaScript (no WebGL, no WebRTC) +- Goal: Render {test_url} correctly + +Keep the fire hot. The blade is taking shape. +""" + +# The Smelter: Turns specifications into designs +agent smelter: + model: opus + prompt: """ +You are the Smelter. You extract pure design from the ore of specifications. + +Your job: Read specs (W3C, ECMA, MDN), understand them deeply, and produce +clear technical designs that the Hammer can implement. + +Your output: +- Data structures with Rust types +- Algorithms in pseudocode +- Interface boundaries +- Key edge cases to handle + +You don't write implementation code. You write blueprints. +Make them precise enough that implementation is mechanical. +""" + +# The Hammer: Shapes code into working components +agent hammer: + model: opus + prompt: """ +You are the Hammer. You shape raw code into working metal. + +Your job: Take the Smelter's designs and forge them into working Rust code. +Every line must compile. Every function must work. No pseudocode. + +Your standards: +- Clean, idiomatic Rust +- Minimal unsafe blocks (document each one) +- No external dependencies except: winit, softbuffer +- Comprehensive error handling +- Clear module structure + +You don't design. You don't test. You forge. +""" + +# The Quench: Tests and hardens each piece +agent quench: + model: sonnet + prompt: """ +You are the Quench. You temper the metal so it doesn't shatter. + +Your job: Write tests that prove each component works. Find the edge cases. +Find the bugs. Find the places where the metal is weak. + +Your process: +- Unit tests for each function +- Integration tests for each module +- Regression tests for each bug found +- Document what each test proves + +When you find a flaw, report it clearly. The Hammer will fix it. +A blade that breaks is worse than no blade at all. +""" + +# The Crucible: Where the hardest work happens (JS engine) +agent crucible: + model: opus + persist: true + prompt: """ +You are the Crucible. The hottest part of The Forge. + +Your domain: The JavaScript engine. The hardest component to build. +This requires understanding that the other agents don't have: +- Lexical scoping and closures +- Prototype chains +- The event loop +- Just enough of the spec to run real-world code + +You work closely with the Smith. The JS engine will take multiple phases. +Your memory persists so you can build on what came before. + +This is where browsers are born or die. Make it work. +""" + +# ============================================================================= +# PHASE 0: IGNITE THE FORGE +# ============================================================================= + +session: smith + prompt: """ +The Forge ignites. + +We're building a web browser from nothing. In Rust. With a GUI. +Including a JavaScript engine. This is not a toy - it will actually work. + +Let me take stock of what we're about to create: + +1. Networking: HTTP/HTTPS client +2. Parsing: HTML tokenizer, HTML parser, CSS tokenizer, CSS parser, JS lexer, JS parser +3. DOM: Document object model with all standard interfaces +4. CSSOM: CSS object model, selector matching, cascade +5. Style: Computed styles, inheritance, defaulting +6. Layout: Box model, block layout, inline layout, text layout +7. Paint: Display lists, rasterization +8. JavaScript: Lexer, parser, bytecode compiler, virtual machine, builtins +9. Bindings: DOM API exposed to JavaScript +10. Shell: Window, event loop, URL bar + +This is months of work for a team. We'll do it in days. + +First: set up the project structure. +""" + +# Initialize the Rust project +session: hammer + prompt: """ +Create the Rust project structure for the browser. + +Commands to run: +```bash +cargo new browser --name browser +cd browser +``` + +Create Cargo.toml with dependencies: +- winit = "0.29" (windowing) +- softbuffer = "0.4" (pixel buffer) +- rustls = "0.23" (TLS, for HTTPS) +- url = "2" (URL parsing - this one's okay to use) + +Create the module structure: +``` +src/ + main.rs # Entry point + lib.rs # Library root + net/ # Networking + mod.rs + http.rs + tls.rs + html/ # HTML parsing + mod.rs + tokenizer.rs + parser.rs + dom.rs + css/ # CSS parsing + mod.rs + tokenizer.rs + parser.rs + cssom.rs + selector.rs + style/ # Style resolution + mod.rs + cascade.rs + computed.rs + layout/ # Layout engine + mod.rs + box_model.rs + block.rs + inline.rs + text.rs + paint/ # Painting + mod.rs + display_list.rs + rasterizer.rs + js/ # JavaScript engine + mod.rs + lexer.rs + parser.rs + ast.rs + compiler.rs + vm.rs + value.rs + builtins.rs + gc.rs + bindings/ # JS-DOM bindings + mod.rs + document.rs + element.rs + console.rs + shell/ # Browser shell + mod.rs + window.rs + events.rs +``` + +Create stub files for each module. Ensure `cargo build` succeeds. +""" + +session: quench + prompt: """ +Verify the project is set up correctly: +1. Run `cargo build` - must succeed +2. Run `cargo test` - must succeed (even with no tests yet) +3. Verify all modules are properly linked from lib.rs + +Report any issues. +""" + +resume: smith + prompt: "Project structure complete. The forge is lit. Moving to Phase 1." + +# ============================================================================= +# PHASE 1: NETWORKING - The Ore +# ============================================================================= + +session: smith + prompt: """ +Phase 1: Networking + +Before we can render a page, we must fetch it. The networking layer is +the ore we'll smelt into a browser. + +We need: +- HTTP/1.1 client (GET requests, headers, redirects) +- TLS support via rustls +- Chunked transfer encoding +- Basic cookie handling (just enough to work) + +This is the foundation. No browser without bytes from the network. +""" + +let http_design = session: smelter + prompt: """ +Design the HTTP client. + +Reference: RFC 9110 (HTTP Semantics), RFC 9112 (HTTP/1.1) + +Design: +1. Connection management (keep-alive, pooling) +2. Request building (method, URL, headers, body) +3. Response parsing (status, headers, body) +4. Redirect following (3xx responses) +5. Chunked transfer-encoding +6. TLS via rustls + +Output Rust types for: +- HttpRequest +- HttpResponse +- HttpClient +- Error types + +Keep it minimal but correct. We're not building curl. +""" + +session: hammer + prompt: """ +Implement the HTTP client. + +Files: +- src/net/mod.rs +- src/net/http.rs +- src/net/tls.rs + +Follow the design. Handle errors properly. Make it work. + +Test manually: fetch https://example.com and print the body. +""" + context: http_design + +session: quench + prompt: """ +Test the HTTP client: +1. Fetch http://example.com (no TLS) +2. Fetch https://example.com (with TLS) +3. Test redirect following (http → https) +4. Test chunked encoding +5. Test error cases (bad host, timeout, etc.) + +Write tests in src/net/tests.rs. Run them. +""" + +loop until **all networking tests pass** (max: 5): + if **there are test failures**: + session: hammer + prompt: "Fix the networking bugs found in testing." + session: quench + prompt: "Re-run networking tests." + +resume: smith + prompt: "Phase 1 complete. We can fetch pages. The ore is ready." + +# ============================================================================= +# PHASE 2: HTML PARSING - The Smelt +# ============================================================================= + +resume: smith + prompt: """ +Phase 2: HTML Parsing + +Raw HTML is just text. We need to smelt it into a Document Object Model. + +Two stages: +1. Tokenizer: HTML text → Tokens (start tag, end tag, text, comment, etc.) +2. Parser: Tokens → DOM tree + +The HTML5 spec is complex, but we can simplify: +- Handle well-formed HTML (don't worry about error recovery) +- Support common elements: html, head, body, div, span, p, a, img, script, style +- Parse attributes correctly +- Handle self-closing tags +- Handle text content + +This is where the raw ore becomes workable metal. +""" + +let html_tokenizer_design = session: smelter + prompt: """ +Design the HTML tokenizer. + +Reference: https://html.spec.whatwg.org/multipage/parsing.html#tokenization + +Simplified state machine: +- Data state (default) +- Tag open state +- Tag name state +- Attribute name state +- Attribute value state (quoted and unquoted) +- Self-closing state +- Comment state + +Tokens: +- DOCTYPE +- StartTag { name, attributes, self_closing } +- EndTag { name } +- Character { data } +- Comment { data } +- EndOfFile + +Output Rust types and state machine transitions. +""" + +session: hammer + prompt: """ +Implement the HTML tokenizer. + +File: src/html/tokenizer.rs + +Create a streaming tokenizer that yields tokens. +Handle: +- Basic tags:
,
+- Attributes:
+- Self-closing:
, +- Text content +- Comments: +- Script/style raw text mode + +Make it work for real HTML from example.com. +""" + context: html_tokenizer_design + +let html_parser_design = session: smelter + prompt: """ +Design the HTML parser (tree builder). + +Input: Token stream +Output: DOM tree + +DOM types: +- Document (root) +- Element { tag_name, attributes, children } +- Text { content } +- Comment { content } + +Tree building algorithm (simplified): +- Maintain stack of open elements +- On StartTag: create element, push to stack, append to parent +- On EndTag: pop from stack (with simple matching) +- On Character: create/extend text node, append to current element +- On Comment: create comment, append to current element + +Handle implicit closing (

can close

). +""" + +session: hammer + prompt: """ +Implement the HTML parser. + +File: src/html/parser.rs +File: src/html/dom.rs + +DOM types go in dom.rs. Parser goes in parser.rs. + +Create: +- Node enum (Document, Element, Text, Comment) +- Element struct with children, parent references (use indices, not Rc) +- Document struct that owns all nodes +- Parser that builds the tree + +Handle the quirks:

closing, void elements, etc. +""" + context: html_parser_design + +session: quench + prompt: """ +Test HTML parsing: + +Test cases: +1. Minimal: Hello +2. Nested:

Deep
+3. Attributes: Link +4. Self-closing:
+5. Comments: +6. Text nodes:

Hello world!

+7. Real page: parse the HTML from https://example.com + +Write tests. Verify the DOM tree is correct. +""" + +loop until **all HTML parsing tests pass** (max: 5): + if **there are test failures**: + session: hammer + prompt: "Fix the HTML parsing bugs." + session: quench + prompt: "Re-run HTML parsing tests." + +resume: smith + prompt: "Phase 2 complete. We can parse HTML into a DOM. The smelt is done." + +# ============================================================================= +# PHASE 3: CSS PARSING - The Alloy +# ============================================================================= + +resume: smith + prompt: """ +Phase 3: CSS Parsing + +A DOM without styles is shapeless metal. CSS gives it form. + +Two stages: +1. Tokenizer: CSS text → Tokens +2. Parser: Tokens → Stylesheet (rules, selectors, declarations) + +We need enough CSS to render real pages: +- Type selectors: div, p, a +- Class selectors: .class +- ID selectors: #id +- Combinators: descendant, child, sibling +- Properties: display, color, background, margin, padding, border, width, height, font-size + +This is the alloy that strengthens the blade. +""" + +let css_tokenizer_design = session: smelter + prompt: """ +Design the CSS tokenizer. + +Reference: https://www.w3.org/TR/css-syntax-3/#tokenization + +Token types: +- Ident +- Function +- AtKeyword +- Hash +- String +- Number +- Dimension +- Percentage +- Whitespace +- Colon, Semicolon, Comma +- Braces, Parens, Brackets +- Delim (any other character) + +Output Rust types and tokenization rules. +""" + +session: hammer + prompt: """ +Implement the CSS tokenizer. + +File: src/css/tokenizer.rs + +Handle real CSS syntax including: +- Identifiers: color, background-color +- Numbers: 10, 3.14, -5 +- Dimensions: 10px, 2em, 100% +- Strings: "hello", 'world' +- Hash: #fff, #header +- Functions: rgb(255, 0, 0) +""" + context: css_tokenizer_design + +let css_parser_design = session: smelter + prompt: """ +Design the CSS parser. + +CSSOM types: +- Stylesheet { rules } +- Rule { selectors, declarations } +- Selector (type, class, id, combinator) +- Declaration { property, value } +- Value (keyword, length, color, number, etc.) + +Parser produces a Stylesheet from the token stream. + +Selector parsing: +- Simple: div, .class, #id +- Compound: div.class#id +- Complex: div > p, div p, div + p, div ~ p + +Declaration parsing: +- Property: identifier +- Value: sequence of tokens until ; or } +""" + +session: hammer + prompt: """ +Implement the CSS parser. + +File: src/css/parser.rs +File: src/css/cssom.rs + +Handle: +- Rule sets: selector { declarations } +- Multiple selectors: h1, h2, h3 { ... } +- Various value types: keywords, lengths, colors, functions +- Shorthand properties (margin: 10px = all four sides) +""" + context: css_parser_design + +session: quench + prompt: """ +Test CSS parsing: + +Test cases: +1. Simple rule: div { color: red; } +2. Multiple selectors: h1, h2 { font-size: 24px; } +3. Class and ID: .class { } #id { } +4. Combinators: div > p { }, div p { } +5. Complex values: margin: 10px 20px; background-color: rgb(255, 0, 0); +6. Real stylesheet: parse a basic CSS file + +Write tests. Verify the CSSOM is correct. +""" + +loop until **all CSS parsing tests pass** (max: 5): + if **there are test failures**: + session: hammer + prompt: "Fix the CSS parsing bugs." + session: quench + prompt: "Re-run CSS parsing tests." + +resume: smith + prompt: "Phase 3 complete. We can parse CSS. The alloy is mixed." + +# ============================================================================= +# PHASE 4: STYLE RESOLUTION - The Shape +# ============================================================================= + +resume: smith + prompt: """ +Phase 4: Style Resolution + +We have a DOM. We have styles. Now we must match them. + +For each element in the DOM: +1. Find all rules whose selectors match this element +2. Apply the cascade (specificity, order) +3. Inherit from parent where appropriate +4. Apply default values for anything unset + +This gives us a "computed style" for every element. +This is where the blade takes its shape. +""" + +let style_design = session: smelter + prompt: """ +Design the style resolution system. + +Components: +1. Selector matching: does this selector match this element? +2. Specificity calculation: (id count, class count, type count) +3. Cascade: sort matching rules by specificity, then order +4. Inheritance: some properties inherit (color), some don't (border) +5. Initial values: defaults for unset properties + +ComputedStyle struct: +- display: DisplayType (block, inline, none) +- position: Position (static, relative, absolute) +- width, height: Dimension (auto, length) +- margin, padding, border: Sides +- color, background_color: Color +- font_size: Length +- (add more as needed) + +The matcher should be efficient - it runs for every element. +""" + +session: hammer + prompt: """ +Implement style resolution. + +File: src/css/selector.rs (selector matching) +File: src/style/cascade.rs (cascade and specificity) +File: src/style/computed.rs (ComputedStyle and inheritance) + +Create: +- SelectorMatcher that can test if a selector matches an element +- Specificity calculation +- Cascade resolver that takes DOM + Stylesheets → styled DOM +- Inheritance and default values +""" + context: style_design + +session: quench + prompt: """ +Test style resolution: + +Test cases: +1. Type selector matches: div matches
+2. Class selector: .foo matches
+3. ID selector: #bar matches
+4. Specificity: #id beats .class beats type +5. Cascade order: later rule wins at equal specificity +6. Inheritance: color inherits, border doesn't +7. Defaults: display defaults to inline for span, block for div + +Write tests with DOM + CSS → expected computed styles. +""" + +loop until **all style resolution tests pass** (max: 5): + if **there are test failures**: + session: hammer + prompt: "Fix the style resolution bugs." + session: quench + prompt: "Re-run style resolution tests." + +resume: smith + prompt: "Phase 4 complete. Elements have computed styles. The shape emerges." + +# ============================================================================= +# PHASE 5: LAYOUT - The Forge +# ============================================================================= + +resume: smith + prompt: """ +Phase 5: Layout + +The heart of a browser. Where the real forging happens. + +Layout takes a styled DOM and produces a "layout tree" - boxes with +positions and sizes in pixels. + +Components: +1. Box generation: DOM elements → layout boxes +2. Block layout: vertical stacking with margins +3. Inline layout: horizontal flow with line breaking +4. Text layout: measuring and positioning text + +This is complex. We'll start simple: +- Block layout only (no inline/text initially) +- Then add inline and text + +The blade is taking its final form. +""" + +let layout_design = session: smelter + prompt: """ +Design the layout engine. + +Box types: +- BlockBox: vertical stacking (div, p, etc.) +- InlineBox: horizontal flow (span, a, etc.) +- TextRun: actual text content +- AnonymousBlock: for mixed block/inline content + +LayoutBox struct: +- box_type: BoxType +- dimensions: Dimensions { content, padding, border, margin } +- position: Point { x, y } +- children: Vec + +Layout algorithm (simplified): +1. Build box tree from styled DOM +2. Block layout: + - Calculate available width from parent + - Layout children top-to-bottom + - Height is sum of children heights (or specified) + - Handle margin collapsing +3. Inline layout: + - Flow boxes horizontally + - Break lines when exceeding width + - Vertical alignment within lines + +Output the types and algorithms. +""" + +session: hammer + prompt: """ +Implement the layout engine. + +File: src/layout/box_model.rs (box types and dimensions) +File: src/layout/block.rs (block layout) +File: src/layout/inline.rs (inline layout) +File: src/layout/text.rs (text measurement) +File: src/layout/mod.rs (main entry point) + +Start with block layout only. Make nested divs work. +Then add inline and text. + +Viewport size: 800x600 for now (we'll make it dynamic later). +""" + context: layout_design + +session: quench + prompt: """ +Test layout: + +Test cases: +1. Single div with fixed width/height +2. Nested divs (parent constrains child) +3. Auto width (fills parent) +4. Auto height (fits content) +5. Margin, padding, border (box model) +6. Margin collapsing between siblings +7. Block in inline (anonymous block generation) + +Verify box positions and dimensions are correct. +""" + +loop until **all layout tests pass** (max: 5): + if **there are test failures**: + session: hammer + prompt: "Fix the layout bugs." + session: quench + prompt: "Re-run layout tests." + +resume: smith + prompt: "Phase 5 complete. We have a layout tree. The blade is forged." + +# ============================================================================= +# PHASE 6: PAINTING - The Polish +# ============================================================================= + +resume: smith + prompt: """ +Phase 6: Painting + +The blade is forged. Now we polish it to a mirror shine. + +Painting turns a layout tree into pixels: +1. Build a display list (paint commands) +2. Rasterize the display list to a pixel buffer +3. Show the pixel buffer on screen + +We're using softbuffer for direct pixel access. No GPU acceleration. +Simple but it works. +""" + +let paint_design = session: smelter + prompt: """ +Design the painting system. + +Display list commands: +- FillRect { rect, color } +- DrawBorder { rect, widths, colors } +- DrawText { text, position, font_size, color } +- PushClip { rect } +- PopClip + +Rasterizer: +- Input: display list + viewport size +- Output: pixel buffer (Vec in ARGB format) + +For text, use a simple bitmap font (8x16 pixels per character). +We don't need fancy fonts for MVP. + +Paint order: +1. Background +2. Borders +3. Text/content +4. Children (recursive) +""" + +session: hammer + prompt: """ +Implement the painting system. + +File: src/paint/display_list.rs (display list types) +File: src/paint/rasterizer.rs (pixel buffer rendering) +File: src/paint/font.rs (simple bitmap font) + +Create: +- DisplayList with paint commands +- Build display list from layout tree +- Rasterize display list to ARGB pixel buffer +- Simple 8x16 bitmap font for ASCII text +""" + context: paint_design + +session: hammer + prompt: """ +Implement the window system. + +File: src/shell/window.rs (winit + softbuffer integration) +File: src/shell/events.rs (event handling) +File: src/main.rs (main entry point) + +Create a window that: +1. Opens with winit +2. Gets a pixel buffer with softbuffer +3. Renders our pixel buffer to the window +4. Handles close events + +Test: draw a colored rectangle on screen. +""" + +session: quench + prompt: """ +Test painting: + +Test cases: +1. Solid color background +2. Nested boxes with different colors +3. Borders (all four sides) +4. Text rendering (basic ASCII) +5. Full pipeline: HTML → DOM → Style → Layout → Paint → Window + +The window should show something! Verify visually. +""" + +loop until **the painting pipeline works** (max: 5): + if **there are issues**: + session: hammer + prompt: "Fix the painting issues." + session: quench + prompt: "Re-test painting." + +resume: smith + prompt: "Phase 6 complete. We can render to a window. The blade shines." + +# ============================================================================= +# PHASE 7: JAVASCRIPT - The Fire +# ============================================================================= + +resume: smith + prompt: """ +Phase 7: JavaScript + +This is where browsers separate from mere HTML viewers. +The JavaScript engine is the fire that brings the blade to life. + +We're not building V8. We're building something that works: +- Lexer: JS source → tokens +- Parser: tokens → AST +- Compiler: AST → bytecode +- VM: execute bytecode +- Builtins: Object, Array, Function, String, Number, console.log + +This is the hottest part of The Forge. The Crucible takes the lead. +""" + +# The Crucible handles the JS engine +session: crucible + prompt: """ +The Crucible fires up for the JavaScript engine. + +We're building a JS interpreter in Rust. Not a JIT compiler - just +an interpreter. But it needs to run real JavaScript. + +Scope: +- Variables: let, const, var +- Functions: declaration, expression, arrow +- Objects: literals, property access, methods +- Arrays: literals, indexing, methods +- Control flow: if, for, while, switch +- Operators: arithmetic, comparison, logical +- Strings and numbers +- console.log for output +- Basic DOM manipulation (later) + +What we're NOT building: +- Classes (use prototypes directly) +- async/await, generators, promises +- Regular expressions (skip for MVP) +- Modules (single script only) + +Let's start with the lexer. +""" + +let js_lexer_design = session: smelter + prompt: """ +Design the JavaScript lexer. + +Reference: ECMA-262 (but simplified) + +Token types: +- Identifiers: foo, bar, console +- Keywords: let, const, var, function, if, else, for, while, return, etc. +- Literals: numbers (42, 3.14), strings ("hello"), booleans (true, false), null +- Operators: + - * / % = == === != !== < > <= >= && || ! ++ -- +- Punctuation: ( ) { } [ ] ; , . : ? +- Comments: // and /* */ + +Handle: +- Unicode identifiers (at least ASCII letters) +- Automatic semicolon insertion (ASI) - track newlines + +Output token types and lexer state machine. +""" + +session: hammer + prompt: """ +Implement the JavaScript lexer. + +File: src/js/lexer.rs + +Create a lexer that produces tokens from JS source. +Handle all the token types from the design. +Track line/column for error messages. +""" + context: js_lexer_design + +let js_parser_design = session: smelter + prompt: """ +Design the JavaScript parser. + +Reference: ECMA-262 (simplified) + +AST node types: +- Program { statements } +- Statements: VarDecl, FunctionDecl, ExprStmt, If, For, While, Return, Block +- Expressions: Identifier, Literal, Binary, Unary, Call, Member, Assignment, Object, Array, Function + +Parser approach: recursive descent (Pratt parsing for expressions) + +Handle: +- Operator precedence +- Associativity +- Expression vs statement context +- Function hoisting (not strict mode) + +Output AST types and parser structure. +""" + +session: hammer + prompt: """ +Implement the JavaScript parser. + +File: src/js/parser.rs +File: src/js/ast.rs + +Create AST types in ast.rs. +Create recursive descent parser in parser.rs. +Use Pratt parsing for expression precedence. + +Test: parse console.log("Hello, World!"); +""" + context: js_parser_design + +resume: crucible + prompt: """ +Lexer and parser are done. Now the real work: execution. + +We have two choices: +1. Tree-walking interpreter (simple but slow) +2. Bytecode compiler + VM (more complex but faster) + +We'll do bytecode. It's more interesting and teaches more. + +Components: +- Value type: JS values (number, string, object, function, etc.) +- Compiler: AST → bytecode +- VM: execute bytecode with a stack +- Heap: objects live here +- GC: garbage collection (mark-sweep is fine) +""" + +let js_value_design = session: smelter + prompt: """ +Design JavaScript value representation. + +Value enum (NaN-boxed or tagged union): +- Number(f64) +- String(StringId) +- Boolean(bool) +- Null +- Undefined +- Object(ObjectId) +- Function(FunctionId) + +Object representation (property map): +- properties: HashMap +- prototype: Option + +Function representation: +- kind: Native | Bytecode +- bytecode: Vec (if bytecode) +- native: fn pointer (if native) +- closure: captured variables + +String interning for memory efficiency. +""" + +session: hammer + prompt: """ +Implement JavaScript values. + +File: src/js/value.rs +File: src/js/gc.rs (simple mark-sweep GC) + +Create: +- Value enum with all JS types +- Object struct with properties and prototype +- Heap that owns all objects +- Simple mark-sweep garbage collector + +The GC doesn't need to be fancy. Just functional. +""" + context: js_value_design + +let js_bytecode_design = session: smelter + prompt: """ +Design the bytecode instruction set. + +Opcodes (stack-based VM): +- Constants: LoadConst, LoadTrue, LoadFalse, LoadNull, LoadUndefined +- Variables: GetLocal, SetLocal, GetGlobal, SetGlobal +- Objects: GetProperty, SetProperty, CreateObject, CreateArray +- Arithmetic: Add, Sub, Mul, Div, Mod, Neg +- Comparison: Eq, StrictEq, Lt, Lte, Gt, Gte +- Logic: Not, And, Or +- Control: Jump, JumpIfFalse, JumpIfTrue +- Functions: Call, Return, CreateFunction +- Stack: Pop, Dup + +Bytecode format: +- 1 byte opcode +- Variable-length operands + +Compiler output: +- bytecode: Vec +- constants: Vec +- local_count: usize +""" + +session: hammer + prompt: """ +Implement the bytecode compiler. + +File: src/js/compiler.rs + +Compile AST to bytecode. + +Handle: +- Variable declarations and scoping +- Function declarations and expressions +- Control flow (if, for, while) +- Operators +- Function calls +- Property access + +Output: CompiledFunction { bytecode, constants, local_count } +""" + context: js_bytecode_design + +session: hammer + prompt: """ +Implement the JavaScript VM. + +File: src/js/vm.rs + +Stack-based virtual machine that executes bytecode. + +Components: +- Value stack +- Call stack (frames) +- Global object +- Heap for objects + +Execute each opcode. Handle errors gracefully. +Test: run console.log("Hello from JS!"); +""" + context: js_bytecode_design + +session: hammer + prompt: """ +Implement JavaScript builtins. + +File: src/js/builtins.rs + +Essential builtins: +- Object: Object.keys(), Object.values() +- Array: push, pop, shift, unshift, map, filter, forEach, length +- String: length, charAt, substring, indexOf, split +- Number: toString, toFixed +- console: log, error, warn +- Math: floor, ceil, round, random, max, min + +Each builtin is a native function. Register them on the global object. +""" + +session: quench + prompt: """ +Test the JavaScript engine: + +Test cases: +1. Variables: let x = 10; console.log(x); +2. Functions: function add(a, b) { return a + b; } console.log(add(2, 3)); +3. Objects: let o = { x: 1 }; console.log(o.x); +4. Arrays: let a = [1, 2, 3]; console.log(a.length); +5. Control flow: if (true) { console.log("yes"); } +6. Loops: for (let i = 0; i < 3; i++) { console.log(i); } +7. Closures: function outer() { let x = 10; return function() { return x; }; } +8. Methods: [1,2,3].map(x => x * 2) + +Run each test. Verify correct output. +""" + +loop until **the JS engine passes all tests** (max: 10): + if **there are test failures**: + resume: crucible + prompt: "Analyze and fix the JS engine bugs." + session: hammer + prompt: "Implement the fixes." + context: crucible + session: quench + prompt: "Re-run JS tests." + +resume: smith + prompt: """ +Phase 7 complete. We have a working JavaScript engine. +The fire burns bright. The blade lives. +""" + +# ============================================================================= +# PHASE 8: DOM BINDINGS - The Handle +# ============================================================================= + +resume: smith + prompt: """ +Phase 8: DOM Bindings + +JavaScript without DOM access is just a calculator. +We need to expose the DOM to our JS engine. + +Essential APIs: +- document.getElementById() +- document.querySelector() +- element.innerHTML +- element.style +- element.addEventListener() +- element.appendChild() + +This connects the fire to the blade. The handle that makes it usable. +""" + +let bindings_design = session: smelter + prompt: """ +Design the DOM bindings. + +Bridge between JS values and DOM nodes: +- Each DOM node gets a corresponding JS object +- JS object has properties/methods that call back into Rust DOM +- Changes to DOM trigger re-style/re-layout/re-paint + +Key bindings: +- window object (global) +- document object +- Element objects +- Event objects + +document methods: +- getElementById(id) → Element | null +- querySelector(selector) → Element | null +- createElement(tag) → Element + +Element properties/methods: +- innerHTML (get/set) +- style (get/set) +- children, parentElement +- getAttribute, setAttribute +- appendChild, removeChild +- addEventListener(event, handler) + +Event system: +- Event object: type, target, preventDefault, stopPropagation +- Event dispatch: capture → target → bubble +""" + +session: hammer + prompt: """ +Implement DOM bindings. + +File: src/bindings/mod.rs +File: src/bindings/document.rs +File: src/bindings/element.rs +File: src/bindings/console.rs + +Create JS wrappers for DOM nodes. +Wire them up to the actual DOM. +Handle the bidirectional sync. + +Test: document.getElementById('test').innerHTML = 'Modified'; +""" + context: bindings_design + +session: hammer + prompt: """ +Implement the event system. + +File: src/bindings/events.rs +File: src/shell/events.rs (update for DOM events) + +Handle: +- addEventListener/removeEventListener +- Event dispatch (click, etc.) +- Event object creation +- Handler invocation through JS VM + +Wire window events (from winit) to DOM events. +""" + +session: quench + prompt: """ +Test DOM bindings: + +Test cases: +1. document.getElementById() returns correct element +2. element.innerHTML read/write works +3. element.style.color = 'red' changes computed style +4. addEventListener + click event handler runs +5. appendChild adds child to DOM +6. createElement + appendChild creates new elements + +Verify DOM mutations trigger re-render. +""" + +loop until **DOM bindings work** (max: 5): + if **there are issues**: + session: hammer + prompt: "Fix the DOM binding issues." + session: quench + prompt: "Re-test DOM bindings." + +resume: smith + prompt: "Phase 8 complete. JavaScript can manipulate the DOM. The handle is attached." + +# ============================================================================= +# PHASE 9: INTEGRATION - The Tempering +# ============================================================================= + +resume: smith + prompt: """ +Phase 9: Integration + +All the pieces exist. Now we temper them into one unified blade. + +The full pipeline: +1. User enters URL +2. Fetch HTML over HTTPS +3. Parse HTML into DOM +4. Find and parse CSS (inline styles,