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.4.0",
"version": "1.5.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 @@ -21,7 +21,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/) | 20 slash commands, 5 subagents, 10 hooks, a 5-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, read from `main`), a local read-only platform MCP server and the public docs MCP |
| [`lua-agent-builder`](./plugins/lua-agent-builder/) | 21 slash commands, 5 subagents, 10 hooks, a 6-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`), a local read-only platform MCP server and the public docs MCP |

## Quick walkthrough

Expand Down
20 changes: 12 additions & 8 deletions docs/USER_GUIDE.md

Large diffs are not rendered by default.

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.4.0",
"version": "1.5.0",
"description": "Build, test, and deploy Lua AI agents from inside Claude Code",
"author": {
"name": "Lua AI",
Expand Down
38 changes: 38 additions & 0 deletions plugins/lua-agent-builder/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,44 @@

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.5.0 — 2026-09-22

**Log drains, and a `lua logs` that reads a window instead of a page.** Two shipped CLI surfaces reach the plugin: the whole `lua drains` command — the rules that copy an organization's agent log records to a destination the customer owns — and the `lua logs` read window `--since` / `--until` / `--environment` / `--follow`, with all **18** log sources finally reachable through `--type`. Everything below was read from lua-core-services `main`: `packages/lua-cli/src/cli/command-definitions.ts` (the `drains` and `logs` declarations), `src/commands/drains.ts`, `src/commands/drains.mutations.ts`, `src/commands/logs.ts`, `src/api/drains.api.service.ts`, `src/utils/aliases.ts` (`drains.action`, `logs.type`), `@lua/shared-types` `log-drain.types.ts` / `vm-execution-log.types.ts` and `@lua/shared-observability` `drain-scrubber.ts` — never from the public docs, which agree with all of it and are cited only as a destination for the user. [PRO-1896]

**Version.** lua-cli **3.38.0** carries all of it and nothing below it does: `lua drains` exits 1 as an unknown command, and the four new `lua logs` options exit 1 as unknown options. `PINNED_MIN_LUA_CLI` moves 3.37.0 → 3.38.0, and unlike the last two bumps this one adds real **command surface**, so every addition is marked "⏳ lua-cli 3.38.0 or later" in the text that emits it.

### `/lua-drains` (new)

- `commands/lua-drains.md` covers all eleven verbs — `list`, `status`, `deliveries`, `create`, `update`, `delete`, `test`, `verify`, `pause`, `resume`, `rotate-secret` — with the plugin's single-permission pattern: one `AskUserQuestion`, then the Bash prompt (the `ask` tier) as the single confirmation for a mutation, and no `AskUserQuestion` on top of it.
- **Secret handling is the point of the file.** The HMAC signing secret is never an input: the platform mints it and the CLI prints it once (at `create`, and at a `rotate-secret` without `--finalize`), so the slash never copies it into a file, an env var, a commit or its own reply. A header VALUE never reaches a command line — `--header <NAME>` prompts hidden and therefore cannot work under `--ci`; the CI form is `--header-from-env <NAME>=<ENV_VAR>`, and an unset variable is exit 2 naming the *variable*. For a vendor preset (`--header DD-API-KEY`, `--header Authorization` as `Bearer <token>`) the slash stops at the secret and hands the user the exact line to run in their own terminal.
- **The JSON contract**: `--json` on **stdout** (`lua drains create --json | jq -r '.secret'` has to work), the verification instructions and the content acknowledgement on **stderr** (`emitAside`), a typed envelope rather than the `✖` line for a refusal that escapes a verb. The per-verb payloads are tabulated.
- `--include-content` is run **without** `--yes` first: the CLI prints `CONTENT_WARNING_TEXT` and `CONTENT_ACKNOWLEDGEMENT_TEXT` and exits non-zero having created nothing, the slash quotes both verbatim, and the user's approval of the re-run *is* the acknowledgement.
- ⚠ `lua drains status` exits **2** both for a usage error and for "some drain is `failing`" — decide from `drains[].state` in `--json`, never from the exit code. `test` (30 s) and `verify` (60 s) are 202-then-poll: `pending: true` with exit 1 means *not yet*, not *failed*.

### `lib/knowledge/log-drains.md` (new, the sixth knowledge file)

What a drain is (an **organization** resource — `--org`, else `lua.skill.yaml`, else a credential that reaches exactly one org) · the eleven verbs and their aliases · the six states (`pending_verification healthy degraded failing paused disabled`) and the transitions that surprise people (a resume lands in `degraded`, an endpoint change returns to `pending_verification`, 24 h failing auto-pauses) · the selectors, including the 19 selectable sources (the 18 `AGENT_LOG_SOURCES` plus `execution`) and the two content ones · the **verification handshake** (only `http` echoes `X-Lua-Verify`, with the `/.well-known/lua-drain-verify` fallback; `otlp`/`datadog`/`betterstack` accept any 2xx test post; `token_not_echoed` is the common failure and the phrase to search for; 5 attempts per drain per hour) · the four presets and what each does with `--endpoint` / `--site` / `--format` · delivery guarantees, the retry/terminal status split (OTLP is the one place a `500` is terminal), the 6-hour horizon and the **`Retry-After`** contract — honoured exactly, clamped at an hour, and the drain *routes* answer `429 DRAIN_RATE_LIMITED` with a bare `Retry-After` and no `X-RateLimit-*` headers · the quota ladder (80% notify → 100% drop `debug` → 125% drop `info` → 150% pause with reason `quota`; `warn` and `error` never go first) · the **scrubber**, its built-in rule classes and the `[redacted:builtin]` / `[redacted:lua-token]` / `[redacted:vendor-key]` / `[redacted:org:<rule-id>]` markers — with the warning that scrubbing only catches shapes it recognises · **`logs:read` vs `logs:manage`**, the second being *sensitive* (a `logs:*` wildcard does not satisfy it) and the deprecation window on the old read scopes.

### `--since` / `--follow` everywhere a window was being reconstructed

- `commands/lua-logs.md`: the full 18-source `--type` list (on 3.37.0 and older the alias table was hand-listed and `trigger`, `model-resolver`, `workflow-step`, `workflow-script`, `workflow` were exit 2, reachable only through the `tail_logs` MCP tool — 3.38.0 derives `logs.type` from `AGENT_LOG_SOURCES`), the read window, and `--follow`'s real semantics: it POLLS (no SSE route), refuses `--page`, advances on the newest timestamp it printed with id de-duplication, and under `--json` emits one `{ logs, nextCursor, pagination }` envelope per poll that produced rows.
- `agents/lua-debug.md` gains step **2b** and the **"watch a promote"** recipe — `lua logs --ci --type all --since <the instant the promote returned> --follow --json`, selecting `subType` `error`/`warn` client-side — plus a drain-triage entry (`status` → `deliveries` → `test` → `verify`) routing the fix to `/lua-drains`.
- `hooks/post-deploy-smoke.mjs` — the other half of the ticket's Context sentence. It pulled a 20-row page and filtered it against **this machine's** clock; it now asks the route for the window with `--since 1m`, which the SERVER resolves, and trusts it. A lua-cli older than 3.38.0 exits 1 on the unknown option, so one fallback to the pre-3.38.0 shape (page + local clock) keeps the check working instead of silently reporting nothing — the pin only warns, so those sessions are still in the field. `--environment production` is deliberately **not** passed: the step-1 ping goes through `lua chat`, whose rows the A1 call sites may stamp `sandbox`, and a smoke check that hid its own ping's errors would be worse than a slightly wider scan. Four new tests cover both paths.
- `agents/lua-qa.md` records `T0` before the first turn and scans with `--since <T0> --environment <target>` instead of pulling 100 rows and filtering by timestamp; `--follow` is called out as wrong for an unattended suite.
- ⚠ **`lua logs` has no severity flag.** `--min-severity` is a log-*drain* selector; severity on a log read is filtered client-side on `subType`. `scripts/lint-cli-flags.mjs` now denies `lua logs --min-severity` so the confusion cannot ship.
- ⚠ **A log entry now HAS an environment field.** The plugin said "there is no `environment` field" in `lua-logs.md`, `lua-qa.md` and `cli-reference.md`; `AgentLogMetadata` gained `orgId`, `environment`, `agentVersion`, `executionId`, `executionSeq`, `traceparent`, `truncated` / `droppedLines`. It is optional and additive, and a row without it reads as **`production`** — on the drain matcher and under `--environment` alike — so its absence never means sandbox. `metadata.channel === 'dev'` is still CLI traffic in *either* environment and is still not an environment marker.

### Plugin machinery

- `lib/permissions-template.json`: allow `lua drains list|status|deliveries|test`; ask `lua drains create|update|delete|verify|pause|resume|rotate-secret`. They are **not** added to `lib/tokenizer.mjs`: nothing a drain verb does changes what runs in production, and `LUA_DEPLOY_CONFIRMED=1` (“the user confirmed a deploy”) would be the wrong sentence — `confirm-deploy` would send the user to `/lua-deploy` for a log-shipping change. The per-verb spelling is deliberate: a blanket `Bash(lua drains *)` would either prompt for a read or admit `rotate-secret`. `test/lib/permissions-mirror.test.mjs` pins every one of the eleven.
- `scripts/lint-knowledge-commands.mjs`: the eleven `drains.action` verbs join the action table. `scripts/lint-cli-flags.mjs`: `lua logs --follow` is **removed** from the denylist — it was denied because it did not exist, and PRO-1838 shipped it; the entry is deleted rather than inverted, which is the mistake that made the plugin emit `lua sync --accept` for months. Two new entries take its place (`lua logs --min-severity`, `lua drains update --type`).
- Bump 1.4.0 → 1.5.0 everywhere; `mcp/lua-platform/dist/server.js` rebuilt; `PINNED_MIN_LUA_CLI` 3.37.0 → 3.38.0 (`hooks/check-lua-version.mjs`, both READMEs, the user guide). `scripts/lint-pinned-version.mjs` compares the pin with npm's `latest` and is therefore **red by design until lua-cli 3.38.0 is published** — the same window 1.4.0 sat in before 3.37.0 shipped; it was not weakened.

### Unchanged on purpose

- No gate behaviour changes: `hooks/hooks.json`, `confirm-deploy` and `lib/tokenizer.mjs` are untouched, because a log drain is organization configuration and not a production verb. `post-deploy-smoke` changed only in HOW it reads the window — same trigger set (`SMOKE_LABELS`), same warning, same non-blocking behaviour.
- The `tail_logs` MCP tool is unchanged and has no window parameter; it stays documented as the fallback when the installed CLI is older than 3.38.0.

## 1.4.0 — 2026-09-20

**What a workflow run costs, and why.** The plugin described a Job-tier attempt as a flat 4 credits and every run budget in "credits". Both are wrong for a priced run: a Job step is billed per model **REPLY** — one credit per reply on a legacy plan, **actions** (the call's price band × the resolved model's multiplier, cached prompt tokens at the fraction the provider charges) on a seat plan — and a coding turn makes dozens of replies in ONE attempt. Read from lua-core-services `main` at `ebcf6689c` (the lua-cli 3.37.0 release, `#3095`; the billing train `#3094`) — the CLI renderers in `src/commands/workflows.ts`, the wire shapes in `src/interfaces/workflows.ts`, the deploy advisory in lua-api's developer workflow service, the Job model legs and their labels in shared-types, the cache weighting in lua-core's Job rate module — never from the public docs.
Expand Down
10 changes: 6 additions & 4 deletions plugins/lua-agent-builder/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Verified against **lua-cli 3.33.0** (September 2026): every command shape, SDK t
/plugin marketplace add lua-ai-global/claude-code-lua-plugin
/plugin install lua-agent-builder@claude-code-lua-plugin
/reload-plugins
/lua-doctor # Node, npm, lua-cli ≥ 3.37.0, auth, permission rules
/lua-doctor # Node, npm, lua-cli ≥ 3.38.0, auth, permission rules
```

New login runs in your own terminal (`lua auth configure`) — the plugin never handles your email, one-time code or credential. `/lua-auth` guides it.
Expand All @@ -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/ # 20 slash commands
├── commands/ # 21 slash commands
├── agents/ # 5 subagents (architect, skill-builder, debug, deploy-pilot, qa)
├── hooks/ # 10 Node ESM hooks + hooks.json
├── lib/
│ ├── knowledge/ # primitives, workflows, cli-reference, integrations, decision-trees
│ ├── knowledge/ # primitives, workflows, cli-reference, integrations, decision-trees, log-drains
│ ├── permissions-template.json# allow/ask/deny rules /lua-doctor merges into .claude/settings.json
│ ├── tokenizer.mjs # production-verb classifier for the deploy gate
│ └── credentials.mjs, hook-runtime.mjs, lua-cli.mjs, platform.mjs
Expand All @@ -49,7 +49,8 @@ plugins/lua-agent-builder/
| `/lua-test [type]` | `lua test --ci skill\|webhook\|job\|preprocessor\|postprocessor\|workflow`; failures go to the debug subagent |
| `/lua-workflow <verb>` | Offline workflow runs with scripted approvals/signals; list/status/watch; start/approve/signal/resume/cancel with one confirmation |
| `/lua-chat` | One-shot `lua chat --ci -e <env> -m … -t` on an isolated thread |
| `/lua-logs` | `lua logs --ci --json` with the real `--type` list |
| `/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-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 |
| `/lua-sync` | Drift report from `lua status --json` + `lua sync --check`; `--pull` / `--push` |
Expand All @@ -63,6 +64,7 @@ plugins/lua-agent-builder/

- **Production gate** — every verb that changes what runs in production is blocked by the `confirm-deploy` hook (on every Bash call) unless it carries the `LUA_DEPLOY_CONFIRMED=1` prefix, which only the deploy flow emits after your single confirmation: `lua deploy`, `lua skills|webhooks|jobs|preprocessors|postprocessors deploy`, `lua persona production deploy`, `lua workflows deploy|activate`, `lua version promote`, `lua mcp activate`, `lua marketplace template publish|apply` — in every spelling lua-cli accepts (its `publish`/`on`/`enable`/`submit`/`rollout`/`prod` aliases and the `heylua`/`lua-ai` binaries). A hook block wins over any allow rule. The permission template allows the literal prefixed forms and carries no deny/ask rule for the bare verbs, because Claude Code evaluates deny/ask past a leading env assignment and such a rule would block the confirmed form too. `lib/tokenizer.mjs` is the one classifier; `test/lib/permissions-mirror.test.mjs` fails if the layers drift.
- **`--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.
- **Credential isolation** — `lua auth configure|key|logout` are denied for the model; login happens in your terminal.
- **Single permission per slash** — each slash asks at most one question (`x-lua-multi-step: true` marks the diagnostic exceptions).

Expand Down
3 changes: 2 additions & 1 deletion plugins/lua-agent-builder/agents/lua-architect.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@ lua-cli is a TypeScript SDK/CLI. It has nothing to do with the Lua programming l

## Always start by reading these (cached; no need to re-read every turn)

The plugin ships a knowledge base verified against lua-cli 3.33.0 source. Read all five with the `Read` tool:
The plugin ships a knowledge base verified against lua-cli source (3.33.0 base; the drain material against 3.38.0). Read all six with the `Read` tool:

- `${CLAUDE_PLUGIN_ROOT}/lib/knowledge/primitives.md` — every SDK primitive and runtime API, exact shapes, gotchas, the decision matrix
- `${CLAUDE_PLUGIN_ROOT}/lib/knowledge/workflows.md` — the workflow builder, steps, approvals/signals, Job tier, script form, CLI verbs, test recipe
- `${CLAUDE_PLUGIN_ROOT}/lib/knowledge/integrations.md` — Unified.to connectors, auto-provisioned MCPs, event subscriptions, channels, `Integrations.passthrough`
- `${CLAUDE_PLUGIN_ROOT}/lib/knowledge/cli-reference.md` — commands, exit codes, push/deploy matrix, agent versions, marketplace templates, docs URL map
- `${CLAUDE_PLUGIN_ROOT}/lib/knowledge/decision-trees.md` — task → primitive routing
- `${CLAUDE_PLUGIN_ROOT}/lib/knowledge/log-drains.md` — ⏳ 3.38.0: shipping the org's logs to the customer's own stack (`lua drains`), the states, the verification handshake, the http/otlp/datadog/betterstack presets, quotas, the scrubber, `logs:read` vs `logs:manage`. Read it when the plan involves observability, SIEM, alerting or an on-call rotation — a drain is the answer to “we want these logs in Datadog”, and it is org configuration, never agent code

When a question goes beyond the knowledge files, use the docs MCP: `mcp__plugin_lua-agent-builder_lua-docs__search_lua_cli` for a question, `mcp__plugin_lua-agent-builder_lua-docs__query_docs_filesystem_lua_cli` to read a page (`head -200 /workflows/authoring.mdx`, `rg -n "approval" /`). `WebFetch https://docs.heylua.ai/<path>` is the fallback (paths are listed in cli-reference.md §6). The knowledge files win over the docs where they disagree — they were checked against the CLI source.

Expand Down
Loading
Loading