Skip to content

feat(lua-agent-builder): live build session mode + lua-cli 3.62.0 test/push/compile; 1.17.0 - #29

Merged
lua-stefan-kruger merged 14 commits into
mainfrom
feat/lbs/session-mode-1.17
Oct 28, 2026
Merged

lua-stefan-kruger merged 14 commits into
mainfrom
feat/lbs/session-mode-1.17

Conversation

@lua-stefan-kruger

Copy link
Copy Markdown
Contributor

What

Ships live build session mode on main as 1.17.0, and brings the builder's prompts up to lua-cli 3.62.0 lua test / lua push / lua compile behaviour. Part of LUA-1855: Lua session pods pin the unmerged feat/lbs/plugin-session-mode head (6444a92, plugin.json 1.14.0) because main has no hooks/session-guard.mjs, and the Job tier pins 1.12.0. Once this is released as v1.17.0, a lua-core-services PR moves both pins to that tag's commit.

Commits

  1. Merge feat/lbs/plugin-session-mode into main (1.16.0). I used a merge rather than a rebase, so the commit the pods pin today stays in the history. There were four conflicts:
    • inject-context.mjs: keeps both the 1.16.0 /lua-audit offer and the session line.
    • The two READMEs: counts now read 25 commands, 11 subagents and 16 hooks, and the knowledge list includes browser and build-session.
    • CHANGELOG: the "Unreleased (planned 1.15.0)" session entry becomes 1.17.0.
  2. Session mode as 1.17.0.
    • Every session-mode "1.15.0" now reads 1.17.0, because 1.15.0 and 1.16.0 shipped as the browser and /lua-audit releases.
    • /lua-audit and /lua-browser are new on main since the branch was cut, so they get their ## Build session sections. session-docs.test.mjs failed without them.
      • /lua-audit: the lua-auditor playbook runs inline and stays read-only.
      • /lua-browser: browsers list runs directly. browser read|run and browsers delete go through request_action, because the shared B23 table classes them as approval.
    • I checked the vendored lib/session-commands.mjs against shared-types on lua-core-services main. Since the vendored commit, the table only gained --operations and the build-session rows, and both are already here.
  3. lua-cli 3.62.0 in the prompts (lua-skill-builder, lua-debug, /lua-test, cli-reference.md §4, primitives.md §14/§23/§24, build-session.md, the session brief, USER_GUIDE):
    • lua test --ci never prompts. A missing kind, --name, or tool --input exits 2 and lists what exists. --name <skill> exits 2 and lists that skill's tools. The builder always passes --name <tool> and --input ('{}' for a tool with no fields). The old "picker exits 0 having tested nothing" text stays as the below-3.62.0 note.
    • Offline doubles. These run with --offline or LUA_TEST_DOUBLES, and are always on in a session. The docs list which families they cover. The builder adds --offline for a tool that writes or sends. The /lua-test live-data gate for web-app write routes is unchanged.
    • lua compile type-checks. By default a type error is a warning. --strict-types / --no-type-check / LUA_TYPE_CHECK change that, and in a session a type error always fails the compile. Strict skill tools also apply: a string in tools is an error. The builder fixes reported type errors in its compile loop.
    • lua push <kind> <name> is documented. The plugin keeps emitting --name.
    • Session brief and build-session.md. They now say there is no lua new command and no lua-docs program; sessions tried both. They also name lua integrations info, because lua-cli has no inspect.
    • Version markers. lua-cli 3.62.0 is not on npm yet (newest is 3.61.1), so every new behaviour is marked ⏳ 3.62.0.
  4. Release 1.17.0. Bumps package.json, plugin.json, marketplace.json, the MCP package and lock, and the client/server metadata, and rebuilds dist/server.js.

Tests

Run in plugins/lua-agent-builder:

  • npm ci && npm run lint: all 18 checks ✓.
  • npm test -- --coverage: 72 suites, 2545 tests passed.
  • node scripts/check-coverage.mjs ✓
  • lint-knowledge-commands, run against lua-cli 3.62.0 source (LUA_CLI_SRC=<lua-core-services main>/packages/lua-cli): 1312 references check out. CI skips this check because it has no monorepo.

Run in mcp/lua-platform:

  • npm ci && npm test: 149 passed.
  • npm run build, with the committed dist/ matching the build.
  • check-bundle-size ✓

Merge

main needs one approving review, and auto-merge is off in this repo. I'll merge (squash, like #28) once it is approved. release-prod then cuts v1.17.0.

🤖 Generated with Claude Code

lua-stefan-kruger and others added 14 commits October 23, 2026 14:59
…ILD_SESSION)

Spec v3 B22/B23. When the session pod sets LUA_BUILD_SESSION=1 the hooks
adapt; with it unset every hook answers exactly as before.

- lib/session-commands.mjs: the B23 command classes (direct_read,
  session_write, approval, secret, unavailable), vendored from
  lua-core-services shared-types build-sessions/commands.ts at 162935cf
  with the shared spec tables as a parity fixture.
- lib/session-mode.mjs: the session switch, the lua-session tool ids,
  the routing texts and the per-command decision.
- tokenizer: findLuaInvocations, an advisory listing of every lua argv in
  a Bash command (same lexer and command positions as the gate).
- New session-guard (PreToolUse, Bash(*lua*)): blocks unavailable
  commands and secret values on a command line (-> request_secret);
  approval-class commands are not blocked, they get context on the
  Desktop approval and the pending answer (no retry).
- New session-context (SessionStart): the session brief.
- confirm-deploy: in a session the prefix is void and every gated verb
  stays blocked (checked before headless, which the pod also sets);
  deploy/promote route to request_release, other verbs to request_action.
- block-auto-deploy, block-auth-configure, block-device-secret: session
  wording, never fewer blocks.
- check-lua-auth, check-lua-version: skipped in a session (no probe).
- post-deploy-smoke: never pings production from a session.
- detect-project, inject-context: no slash pointer / a session line.

Tests prove flags-off behaviour is unchanged on a shared corpus and that
session mode never removes a block.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every slash command gets a short "Build session" section (spec v3 B23
supersedes the B22 table): reads run directly, session writes stay in
the session, production changes go to the user in Lua Desktop, secrets
are named, never asked for.

- /lua-deploy: stage_for_test, test_chat / preview_webapp, then
  request_release; no pilot, no deploy verb; rollback via request_action.
- /lua-version: create -> stage_for_test; promote -> release/rollback.
- /lua-chat and /lua-qa quick mode (and the lua-qa playbook): always the
  session test version via test_chat or sandbox chat, never production.
- /lua-env: secret-shaped keys -> request_secret; production config and
  deletes -> request_action; sandbox .env edits stay direct (the session
  guard no longer flags them).
- /lua-integrations, /lua-drains, /lua-devices, /lua-decisions,
  /lua-template, /lua-workflow, /lua-init: mutations -> request_action;
  OAuth links and signing secrets stay with the user in Desktop.
- /lua-auth, /lua-update: not available; /lua-doctor: read-only probes.
- The rest work as written with no auth preflight, questions asked in
  the reply, and subagent playbooks inline.
- lib/knowledge/build-session.md: the full session table, the tools,
  how to wait on a decision, releases and rollback, hook behaviour.
- lint-mcp-refs: knows the host-provided lua-session server (bare names).
- lua-deploy-pilot: not used in a session.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…hangelog)

- docs/BUILD_SESSION.md: how a session pod turns session mode on
  (LUA_BUILD_SESSION=1), what each hook and slash command does there,
  the lua-session MCP server and session deny rows to pass, the proxy as
  the boundary, and how to keep the vendored B23 table in sync.
- JOB_TIER.md points at it: session mode wins over headless.
- README, plugin README, SECURITY (session-mode contract row), CHANGELOG
  (Unreleased; the version bump re-stamps the MCP bundle and belongs to
  the release PR).
- test/lib/session-docs.test.mjs: every slash command but /lua-docs has
  a Build session section before its first step, without the question
  tool, a sign-in or the confirmation prefix; every lua-session tool
  reference is real and the knowledge file documents all eight.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… knowledge path

- `lua --version`, `lua --help`, `lua help …` and `<cmd> --help|-h` fall
  to the B23 table's fail-closed default (approval); the guard no longer
  calls them production changes. Blocks are unaffected (`lua update
  --help` stays blocked).
- The SessionStart brief and the per-prompt line name the knowledge file
  by absolute path: hook output is not expanded and a relative path
  would be read against the agent project.
- The approval note also says not to nohup or poll a pending request.
- Knowledge: rollback via request_action is decided by the platform
  (promote maps to its release flow), confirmed with `lua version list`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… in any case

Port lua-core-services b4be3b9b (shared-types commands.ts): positional
tokens and the command path compare lowercased, as lua-cli normalizeArg
does, and devices.credential lists the `credentials` and `key` aliases.
Before, `lua devices key thermo --out .dev.env` or the uppercase
CREDENTIAL spelling classified as a generic approval and session-guard
only warned. Parity fixture carries the new shared spec rows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…a session

The session check ran after the `--out <file>` exemption, so in a build
session any credential spelling with a real out file returned null and
relied on session-guard, which missed the `credentials` / `key` aliases.
The session check now runs first (after --help), so the alias-aware,
case-insensitive CREDENTIAL_RE blocks every form. Flags off, the --out
form is still allowed exactly as before (new test).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…name and entry file

npx lua-cli, npx lua-cli@<version> and node .../lua-cli/dist/index.js
followed by the devices credential verbs were not matched, so the printing
form (and in a session every form) passed this hook (F011).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… unavailable in a session

Mirror the shared B23 table at lua-core-services 7c53151b: '--operations'
joins VALUE_TAKING_FLAGS, so the devices credential verb after an
--operations list classifies as secret (the list was read as the verb and
the call only warned), and the build-session rows (status is a read, every
other verb unavailable). Parity rows copied from the shared spec, plus the
triage's key row. The case-insensitive and alias handling of b4be3b9b is
kept (stricter than the integration branch).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tput in a session

B15/B23 want log and run output that reaches Claude fenced as untrusted data
(F065). New PostToolUse hook (Bash(*lua*)): in a session, after a lua read
whose output carries runtime text (logs, workflows runs/job-logs,
integrations inspect, devices logs, drains deliveries, sandbox chat, test,
evals run, decisions run) it adds an UNTRUSTED DATA note. A PostToolUse hook
cannot rewrite a Bash result, so this is a banner after the output, not a
fence; the fence proper belongs in the :8092 proxy and lua-cli. Silent
outside a session (tested on the whole flags-off corpus).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ecret change

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings live build session mode (LUA_BUILD_SESSION=1, hooks/session-guard.mjs,
session-context, session-untrusted-output, build-session knowledge) onto
current main. Conflicts resolved:

- hooks/inject-context.mjs: keep both the 1.16.0 /lua-audit offer
  (headless-gated) and the session line
- README.md, plugins/lua-agent-builder/README.md: 25 commands,
  11 subagents, 16 hooks, browser + build-session knowledge
- CHANGELOG.md: the session-mode entry becomes 1.17.0 above 1.16.0

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… /lua-browser session paths

- Every "1.15.0" that named session mode now says 1.17.0 (1.15.0 and
  1.16.0 went out on main as the browser and /lua-audit releases); the
  browser 1.15.0 references are unchanged
- /lua-audit runs the lua-auditor playbook inline, read-only, in a session
- /lua-browser in a session: list direct; browser read|run and
  browsers delete go to request_action (shared B23 table: approval rows)
- docs/BUILD_SESSION.md: unset-flag behaviour is as in 1.16.0, three new hooks
- inject-context test pins the merged hook: a session pod gets the session
  line and no /lua-audit offer

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…the builder prompts (LUA-1855)

- lua-skill-builder: always --name <tool> and --input ('{}' for none);
  3.62.0 exits 2 listing kinds/names/the skill's tools instead of the
  old picker that exited 0 having tested nothing (kept for older CLIs);
  --offline for a tool that writes or sends; the compile loop fixes
  3.62.0 type errors and never passes --no-type-check; strict skill tools
- lua-debug, /lua-test, cli-reference §4, primitives §14/§23/§24: the same,
  plus offline doubles (families, LUA_TEST_DOUBLES, always on in a
  session), lua compile --strict-types / --no-type-check /
  LUA_TYPE_CHECK, and lua push <kind> <name>
- build-session.md + session brief: there is no `lua new` command and no
  `lua-docs` program (sessions ran both); lua test runs on offline doubles
  and lua compile fails on type errors in a session; lua integrations info
  (lua-cli has no inspect)
- USER_GUIDE: New in 1.17.0

Everything new is marked ⏳ 3.62.0: npm's newest lua-cli is still 3.61.1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
package.json, plugin.json, marketplace.json, the MCP package and lock,
X-Lua-Client / server metadata, and the rebuilt dist/server.js.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@lua-stefan-kruger

Copy link
Copy Markdown
Contributor Author

@selcuk-lua @rares04 could one of you review this? It brings the plugin's session-mode branch onto main, and updates the lua-cli guidance for 3.62.0 (lua test skill --ci --name <tool> --input, lua push <kind> <name>, the type check in lua compile, and offline doubles in sessions). It unblocks LUA-1855: the pod images can then move off plugin 1.14.0 and 1.12.0. All CI checks pass.

@selcuk-lua selcuk-lua left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code review — MEDIUM risk

This PR introduces live build session mode (LUA_BUILD_SESSION=1) — a vendored command classifier, a session-mode decision library, new SessionStart/PreToolUse/PostToolUse hooks, extensive knowledge docs, and a 1.17.0 release bump with lua-cli 3.62.0 prompt updates. The reviewed security-sensitive files are well-structured and exceptionally well-tested (2545 tests; explicit invariants that session mode never removes a block and that flags-off behavior is byte-identical). The code correctly positions itself as defense-in-depth — its own comments name the :8092 Lua-API proxy as the real boundary. No exploitable flaw was found in the reviewed code; the findings are advisory. Note only 7 of 69 changed files were available for review, which bounds confidence.

Minor

  • plugins/lua-agent-builder/lib/session-commands.mjs:1 — The classification table is a hand-maintained mirror of a private shared-types source pinned to commit 7c53151b…, synced via a manual "port the change here" process and a parity fixture that only checks copied rows. New upstream verbs/aliases fail closed to approval/high (safe), but a verb upstream reclassifies to a stricter class stays misclassified until a human syncs. Add a CI check that flags when the vendored commit lags upstream, or generate the table at build time.
  • plugins/lua-agent-builder/lib/session-commands.mjs:214 — The marketplace.read gate guesses the verb slot via pos[1] ?? pos[0], which is fragile for lua marketplace skill/template <id> bare forms. The destructive/mutating post-checks and existing tests mitigate the dangerous cases, but make the (noun, verb) grammar explicit and add fixtures for the bare-id forms.
  • plugins/lua-agent-builder/lib/session-mode.mjs:260 — untrustedOutputNote appends an UNTRUSTED DATA banner after the tool result rather than fencing it (a documented PostToolUse limitation). Prompt-injection defense for third-party-writable runtime text therefore relies on model compliance plus the proxy. Acceptable as belt-and-suspenders; ensure the proxy-side fence is the tracked authoritative control and never relied on solely via this banner.

PR Risk Reviewer — automated senior review of cbb35c1 · risk: medium · confidence: 0.62

@lua-stefan-kruger
lua-stefan-kruger merged commit e45fdbb into main Oct 28, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants