Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"name": "lua-agent-builder",
"source": "./plugins/lua-agent-builder",
"description": "Build, test, and deploy Lua AI agents from inside Claude Code",
"version": "1.9.1",
"version": "1.10.0",
"homepage": "https://github.com/lua-ai-global/claude-code-lua-plugin#readme",
"repository": "https://github.com/lua-ai-global/claude-code-lua-plugin.git",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Then `/lua-auth`: an existing credential is kept; a new login runs `lua auth con

| Plugin | Description |
|---|---|
| [`lua-agent-builder`](./plugins/lua-agent-builder/) | 22 slash commands, 10 subagents, 13 hooks, a 7-file knowledge base verified against lua-cli source (3.33.0 base; 1.3.0 added per-step model classes and the workflow autonomy envelope from lua-cli 3.36.0, 1.4.0 the Job-tier billing rules and the lua-cli 3.37.0 cost read-outs, 1.5.0 log drains and the `lua logs` read window from lua-cli 3.38.0, read from `main`; 1.6.0 headless mode and a hardened production-gate parser; 1.7.0 `/lua-devices`, device credentials that never reach the conversation, and a re-check against lua-cli 3.44.0 / 3.45.0; 1.8.0 web apps (Lua Apps); 1.9.0 the full QA suite, `/lua-qa full`), a local read-only platform MCP server and the public docs MCP |
| [`lua-agent-builder`](./plugins/lua-agent-builder/) | 23 slash commands, 10 subagents, 13 hooks, a 9-file knowledge base verified against lua-cli source (3.33.0 base; 1.3.0 added per-step model classes and the workflow autonomy envelope from lua-cli 3.36.0, 1.4.0 the Job-tier billing rules and the lua-cli 3.37.0 cost read-outs, 1.5.0 log drains and the `lua logs` read window from lua-cli 3.38.0, read from `main`; 1.6.0 headless mode and a hardened production-gate parser; 1.7.0 `/lua-devices`, device credentials that never reach the conversation, and a re-check against lua-cli 3.44.0 / 3.45.0; 1.8.0 web apps (Lua Apps); 1.9.0 the full QA suite, `/lua-qa full`; 1.10.0 decisions, `/lua-decisions` and `/lua-new decision` from lua-cli 3.48.0 / 3.49.2), a local read-only platform MCP server and the public docs MCP |

## Quick walkthrough

Expand Down
3 changes: 3 additions & 0 deletions docs/USER_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ If you just want to start: [Installation](#installation) → [Your first agent](

`/lua-doctor` checks all of these and offers consent-gated fixes. Platforms: macOS 14+, Ubuntu 22.04+, Windows 11; CI runs the suite on all three with Node 18 and 20.

New in 1.10.0: **decisions.** A decision is one call that takes some state and typed questions and returns typed answers with probabilities: the odds that something is true, a choice with its confidence, or a score on a scale. `/lua-new decision <name>` writes a `LuaDecision` with literal questions and registers it; `/lua-push decision` stages a version; `/lua-decisions` lists the agent's decisions, shows their versions, runs one on a message or JSON state (on the version's model, or `--model <id>` for any of the thirteen decision models, Jev and OpenAI included), publishes a version (the rollback) or deletes one. Reads and runs go at once; publish and delete confirm once through the Bash prompt. Needs lua-cli 3.48.0; `--model` and the OpenRouter ids need 3.49.2.

New in 1.9.0: **the full QA suite.** `/lua-qa full` runs at a tier: `smoke` (a 30-minute cap from the moment you approve the plan), `medium` (the default, 1 to 2 hours) or `production-ready` (3 to 5 hours, ending in a release gate). It maps the agent into diagrams you confirm and infers the qualifying answers and metrics from the code, citing a `file:line` for each (`--interview` asks you instead). Then it plays customer personas several times each plus a red team, runs offline workflow flow tests, direct tool tests and (outside smoke) a stress test in parallel, grades every run with two independent graders (one in smoke), clusters the failures by root cause and writes a PDF, HTML and JSON report. Bare `/lua-qa` (or `/lua-qa quick`) is the pass from earlier releases, unchanged and with no new question.

New in 1.7.0: **devices.** `/lua-devices` connects a Raspberry Pi, a laptop or a Pico W to the agent. It helps you choose between a self-describing client and a `defineDevice` declaration. With lua-cli 3.45.0 it issues a **device credential** straight into a git-ignored, mode-600 `.env.device` that the conversation never sees (a scoped personal API key is refused by the device gateway). It writes a Node, Python or MicroPython client, pushes, and tests with `lua devices status`, `test --command` and `test-trigger --trigger`. Every 3.45-only step names its lua-cli 3.44 fallback. The same release re-checks the plugin against lua-cli 3.44.0, where `lua push agent` stages the persona and `lua push all` no longer activates workflows, and gates the new non-interactive `lua skills production deploy`.
Expand Down Expand Up @@ -172,6 +174,7 @@ Chat-composed workflows can't be deployed from the CLI (`WORKFLOW_DYNAMIC`); `/l
| `/lua-chat` | `lua chat --ci -e … -m … -t` | always an explicit thread |
| `/lua-logs` | `lua logs --ci --type … --json` | the real 18-source `--type` list (`mastra` is not valid); ⏳ 3.38.0 `--since` / `--until` (ISO instant or `15m`/`2h`/`7d`, resolved by the server's clock), `--environment production\|sandbox`, `--follow` (polls ~2 s, refuses `--page`) |
| `/lua-drains` | `lua drains list\|status\|deliveries\|create\|update\|delete\|test\|verify\|pause\|resume\|rotate-secret` | ⏳ 3.38.0. Reads run at once; the seven configuration verbs confirm once through the Bash prompt. Needs `logs:manage` (a sensitive scope). The signing secret is printed once by the platform and never stored by the plugin; header values are prompted or read from an environment variable with `--header-from-env NAME=ENV_VAR`, never typed on a command line |
| `/lua-decisions` | `lua decisions list\|versions\|run\|publish\|delete`, `lua logs --type decisions` | ⏳ 3.48.0. `run` takes `--message` or `--state` and, ⏳ 3.49.2, `--provider` / `--model <id>` (any decision model, including the eleven served through OpenRouter) / `--min-confidence`; list/versions/run go at once, publish and delete confirm once through the Bash prompt; a new decision is `/lua-new decision`, a push is `/lua-push decision` |
| `/lua-devices` | `lua devices list\|status\|credential\|test\|test-trigger\|enable\|disable\|remove`, `lua push device\|device-trigger`, `lua logs --type device\|device-trigger` | guided `setup` (credential → client → push → test); the credential always goes to a git-ignored file via `--out`; reads run at once, everything else confirms once through the Bash prompt; ⏳ 3.45.0 verbs have 3.44 fallbacks |
| `/lua-env` | `lua env <sandbox\|production> --list \| -k KEY -v VALUE \| -k KEY --delete` | environment + key + value collected once; the Bash prompt is the confirmation; the value is never echoed, listings show masked values |
| `/lua-integrations` | `lua integrations available\|list\|info\|webhooks …\|mcp …` | read-only verbs run at once; disconnect/convert/webhooks/mcp mutations confirm once via the Bash prompt; `connect`/`update` (browser OAuth) are printed for your terminal |
Expand Down
2 changes: 1 addition & 1 deletion plugins/lua-agent-builder/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "lua-agent-builder",
"version": "1.9.1",
"version": "1.10.0",
"description": "Build, test, and deploy Lua AI agents from inside Claude Code",
"author": {
"name": "Lua AI",
Expand Down
23 changes: 23 additions & 0 deletions plugins/lua-agent-builder/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,29 @@

All notable changes to the `lua-agent-builder` plugin. Versions follow the tag `release-prod.yml` cuts from `package.json` (`v<version>`). lua-cli is a TypeScript SDK/CLI; it is unrelated to the Lua programming language.

## 1.10.0 — 2026-10-11

**Decisions: `/lua-decisions`, `/lua-new decision`, and a knowledge file for the Decisions primitive** (lua-cli 3.48.0; `--model` and the OpenRouter ids from lua-cli 3.49.2).

A decision is one call that takes some state and typed questions (`Decisions.odds`, `Decisions.choice`, `Decisions.score`) and returns typed answers with probabilities, from any agent code. A `LuaDecision` is the named, versioned form: `lua push` stages a version, the dashboard edits and publishes, `lua decisions publish` rolls back, and `Decisions.run('<name>', state)` keeps asking the current version. Thirteen models answer behind one shape: Jev (Lua's default), OpenAI, and eleven decision models served through OpenRouter by `vendor/model` id.

### New

- **`/lua-decisions [list | versions <name> | run <name> | publish <name> <version> | delete <name>]`** (`commands/lua-decisions.md`). `run` takes `--message '<text>'` or `--state '<json>'` and the per-call overrides `--provider`, `--model <id>` and `--min-confidence`, and reports every answer by its type (odds, choice with confidence and `uncertain`, score with its level, or refused) with the provider, the dated model id, the routing rule, duration, tokens, cache status and the cost in actions. `publish` and `delete` go through the Bash prompt once (`--force`, since the CLI's own y/N cannot be answered from a slash); the slash never adds an AskUserQuestion on top.
- **`/lua-new decision <name>`** writes `src/decisions/<name>.ts` with literal questions (the one shape the compiler can read), registers it in `decisions: [...]`, compiles, reads the manifest entry back, and names the push and publish steps; the builder shows the typed caller the user will write and why `answer.type` is checked before `.odds` / `.choice` / `.score`.
- **`lib/knowledge/decisions.md`**: the builders and their limits, the result shape, providers and routing (what `auto` picks, when a fallback runs and what it costs, why a pinned provider never switches), the OpenRouter rules (a `vendor/model` id pins openrouter; `provider: 'openrouter'` needs a model; `typesafe/…` and `openai/…` ids are refused with the provider to use; unknown or data-retaining ids fail `decision_rejected` with no fallback; images reach every model), the `LuaDecision` lifecycle (staged by push, current by promote or publish, 1.0.1 on the first push, dashboard drafts never pinned), the five verbs with aliases and exit codes, the error codes, sharing and caching, the `decisions` log source, and billing (0.005 actions on Jev, 0.01 on OpenAI or OpenRouter, free when cached, failed or cancelled).

### Changed

- **Permissions** (`lib/permissions-template.json`, mirrored in `test/lib/permissions-mirror.test.mjs`): `lua decisions list|versions|run` are allowed (`run` is one billed call that changes no configuration); `lua decisions publish|delete` sit in `ask`, the single confirmation `/lua-decisions` relies on. `lua push decision` rides the generic push allow — a pushed decision is staged only. Not in the tokenizer: making a decision version current is agent configuration, not a deploy.
- **`/lua-logs`** documents `--type decisions` (one row per call: model, provider, rule, answers with probabilities, tokens, cost, cache status, error code).
- **The debug subagent** (`agents/lua-debug.md`) reads a `DecisionError` by code: `decision_invalid` names the field, `decision_not_found` is a version that was never made current (fix with publish or promote, not code), `decision_rejected` is the model refusing the request and never falls back, the 503 family is the provider side and the SDK never retries. `lua decisions list|versions` join its allowlist.
- **`/lua-new`** accepts `decision` (aliased from `decisions`) with one extra question, "what should it decide, and what are the possible answers?"; the builder (`agents/lua-skill-builder.md`) reads `decisions.md`, writes the file by convention, registers it in `decisions`, and compile-verifies it (there is no `lua test` type).
- **`primitives.md` §16 and `decision-trees.md`** route "a judgment the code branches on" to `Decisions.ask` or a `LuaDecision`, next to `AI.generate` for prose.
- **`cli-reference.md`** gains the `lua decisions` row in §4 and the two SDK pages in the docs map.

Versioning: 1.9.1 is on `main` and tagged, so this is 1.10.0. Nothing else is open that declares a version.

## 1.9.1 — 2026-10-08

**`/lua-qa full`: report correctness fixes from the first three-tier trial.** The suite ran smoke, medium and production-ready on a test agent (Pageturner Books: 7 tools, 4 workflows, one of them a `foreach`). Four defects changed what the report said.
Expand Down
6 changes: 4 additions & 2 deletions plugins/lua-agent-builder/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ New login runs in your own terminal (`lua auth configure`) — the plugin never
plugins/lua-agent-builder/
├── .claude-plugin/plugin.json # plugin manifest
├── .mcp.json # lua-platform (local stdio) + lua-docs (https://docs.heylua.ai/mcp)
├── commands/ # 22 slash commands
├── commands/ # 23 slash commands
├── agents/ # 10 subagents (architect, skill-builder, debug, deploy-pilot, qa, qa-cartographer, qa-player, qa-grader, qa-analyst, qa-reporter)
├── hooks/ # 12 Node ESM hooks + hooks.json
├── lib/
│ ├── knowledge/ # primitives, workflows, cli-reference, integrations, decision-trees, log-drains, devices
│ ├── knowledge/ # primitives, workflows, cli-reference, integrations, decision-trees, log-drains, devices, web-apps, decisions
│ │ └── qa/ # /lua-qa full prompts: rubric, ICP cards, player, red team, graders, analyst, fix-locus, mechanics, qualifying questions
│ ├── qa/ # /lua-qa full helpers behind one entry, lib/qa/cli.mjs (recorder, checks, discovery + SVG, report, Workflow script)
│ ├── permissions-template.json# allow/ask/deny rules /lua-doctor merges into .claude/settings.json
Expand Down Expand Up @@ -53,6 +53,7 @@ plugins/lua-agent-builder/
| `/lua-chat` | One-shot `lua chat --ci -e <env> -m … -t` on an isolated thread |
| `/lua-logs` | `lua logs --ci --json` with the real 18-source `--type` list and ⏳ the 3.38.0 read window (`--since` / `--until` / `--environment` / `--follow`) |
| `/lua-drains` | ⏳ 3.38.0 log drains: `lua drains list\|status\|deliveries\|create\|update\|delete\|test\|verify\|pause\|resume\|rotate-secret`; reads run at once, the seven config verbs confirm once, the signing secret is never stored |
| `/lua-decisions` | ⏳ 3.48.0 named decisions (`LuaDecision`): `lua decisions list\|versions\|run\|publish\|delete`; `run` takes a message or JSON state and, ⏳ 3.49.2, `--model <id>` for any of the thirteen decision models (Jev, OpenAI, eleven through OpenRouter); list/versions/run go at once, publish (rollback) and delete confirm once |
| `/lua-devices` | Hardware and local machines: self-describing vs `defineDevice`, ⏳ 3.45.0 `lua devices credential --out` (the secret goes to a git-ignored mode-600 file, never the conversation), Node / Python / Pico W client scaffolds, `push device` / `device-trigger`, `status`, ⏳ 3.45.0 `test --command` / `test-trigger --trigger`, `lua logs --type device\|device-trigger`, troubleshooting — every 3.45-only verb has a 3.44 fallback |
| `/lua-env` | `lua env <sandbox\|production> --list \| -k KEY -v VALUE \| -k KEY --delete`; the Bash prompt is the confirmation, values never echoed |
| `/lua-integrations` | `lua integrations available\|list\|info\|webhooks …\|mcp …`; read-only verbs run at once, mutations confirm once, OAuth connects go to your terminal |
Expand All @@ -69,6 +70,7 @@ plugins/lua-agent-builder/
- **Headless mode** — `LUA_PLUGIN_HEADLESS=1` (for `claude -p` in the Lua Job tier or CI): no hook message points at a slash command, the `LUA_DEPLOY_CONFIRMED=1` prefix is void (every production verb is blocked) and the post-deploy smoke ping is skipped. See [Running in the Lua Job tier](../../docs/JOB_TIER.md).
- **`--auto-deploy`** is denied and blocked unconditionally.
- **Log drains** (⏳ lua-cli 3.38.0) are ORGANIZATION configuration, not a deploy: `lua drains list|status|deliveries|test` are allowed, and `create|update|delete|verify|pause|resume|rotate-secret` sit in the `ask` tier — that prompt is `/lua-drains`'s single confirmation. They are deliberately **not** in `lib/tokenizer.mjs`: none of them changes what runs in production, and `LUA_DEPLOY_CONFIRMED=1` would be the wrong sentence for a log-shipping change. No secret ever reaches a command line — a header value is prompted or read from an environment variable (`--header-from-env NAME=ENV_VAR`), and the HMAC signing secret is minted server-side and printed exactly once.
- **Decisions** (⏳ lua-cli 3.48.0) are AGENT configuration, not a deploy: `lua decisions list|versions|run` are allowed (`run` is one billed call that changes nothing), and `publish` (makes a version current for every caller) and `delete` sit in the `ask` tier — that prompt is `/lua-decisions`'s single confirmation. `lua push decision` stages only and rides the generic push allow; a staged version goes live through `lua version promote` (gated) or `lua decisions publish` (ask).
- **Devices** are not part of agent versions and are not deploy verbs: a pushed `defineDevice` is live on the next turn, so `lua push device` / `device-trigger` sit in the `ask` tier (above the generic push allow rule), as do `lua devices enable|disable|remove|test|test-trigger|credential` and their aliases; `list` / `status` are allowed. A device-trigger is published only by `--auto-deploy`, which stays denied — `/lua-devices` prints that line for your own terminal.
- **Web apps** (lua-cli 3.42.0+) run their routes as you against the agent's live `Data`, locally too — there is no test database. The plugin runs `GET` routes freely and asks once before any route that writes; it never starts `lua apps dev` (it prints that for your own terminal). Only `lua apps new <name>` and four npm commands run without a prompt — `npm --prefix src/apps/<name>/web install --ignore-scripts [@lua-ai-global/app-client]`, `run typecheck`, `run build` — and only in that exact form: the `approve-web-app` hook matches them with anchored regexes rather than permission globs (a glob's `*` would also match an extra package, a second `--prefix`, or anything after the app name). A web-app push is staged only; `/lua-deploy webapp` promotes a new agent version and stops before promoting if that version would also make other staged primitives live.
- **Credential isolation** — `lua auth configure|key|logout` are denied for the model; login happens in your terminal. A device credential is only ever issued with `--out <file>` (the `block-device-secret` hook blocks the printing form), into a git-ignored mode-600 file the plugin never reads back.
Expand Down
Loading
Loading