Skip to content

feat: update agents, tools, permissions and web UI - #36

Merged
alpibrupa merged 2 commits into
mainfrom
claude/sync-workspace
Jun 9, 2026
Merged

feat: update agents, tools, permissions and web UI#36
alpibrupa merged 2 commits into
mainfrom
claude/sync-workspace

Conversation

@alpibrupa

Copy link
Copy Markdown
Contributor

Summary

  • lex.toml: path → git deps
  • All agent implementations updated (build, explore, plan, refactor, review, spec, test)
  • New: permissions manifests, os_check tool, web server
  • Updated web UI

Test plan

  • lex check src/**/*.lex
  • lex test tests/

🤖 Generated with Claude Code

- lex.toml: switch to git deps
- src/agents/*: build, explore, plan, refactor, review, spec, test agents updated
- src/permissions/rules.lex, manifests.lex: permission rules and manifests
- src/tools/index.lex, os_check.lex: tool index and OS check tool
- src/server/web.lex: web server
- src/web/index.html: updated UI

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Security review found two medium-confidence issues introduced by this PR. I found no prior automation review threads to reconcile on this PR.

Open in Web View Automation 

Sent by Cursor Automation: PR Lex

Comment thread src/tools/os_check.lex
Comment on lines +71 to +81
let mode := util.field_str_or(args, "mode", "build")
match proc.spawn("lex", ["--output", "json", "check", path]) {
Err(msg) => Err(e.single("", "proc_error", msg)),
Ok(out) => if out.exit_code != 0 {
Err(e.single("", "lex_check_failed", str.concat(out.stdout, out.stderr)))
} else {
match jv.parse(out.stdout) {
Err(_) => Err(e.single("", "parse_error", "could not parse lex check output")),
Ok(parsed) => {
let required := extract_effects(parsed)
let forbidden := forbidden_for_mode(mode)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Medium: mode is supplied by the tool caller and defaults to build, so forbidden_for_mode returns no forbidden effects for build or any typo/unknown value. A prompt-injected refactor agent can call os_check with mode: "build" and receive grant check passed for code that uses net, bypassing the trust-grant check this tool is meant to enforce. Bind the mode from the active session or validate an enum and fail closed.

Comment thread lex.toml
Comment on lines +7 to +13
lex-llm = { git = "https://github.com/alpibrusl/lex-llm" }
lex-agent = { git = "https://github.com/alpibrusl/lex-agent" }
lex-trail = { git = "https://github.com/alpibrusl/lex-trail" }
lex-spec = { git = "https://github.com/alpibrusl/lex-spec" }
lex-schema = { git = "https://github.com/alpibrusl/lex-schema" }
lex-os-manifest = { git = "https://github.com/alpibrusl/lex-os-manifest" }
lex-web = { git = "https://github.com/alpibrusl/lex-web" }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Medium: these new Git dependencies are unpinned and there is no lockfile in this repo. Future installs/builds will resolve mutable default branches from these remote repos, so a compromised repo or force-pushed branch can inject code into lex-code builds. Pin each dependency to an immutable commit/tag, and commit a lockfile if Lex supports one.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Found and fixed two high-severity regressions from this PR in follow-up PR #37: #37

Bug and impact:

  • os_check was bypassable in refactor mode. A refactor agent could call os_check without mode or with mode: "build", causing files with forbidden net effects to be reported as passing the grant check.
  • The web UI defaulted to Ollama while every Ollama agent variant in this PR has tools: [] and max_steps: Some(3), making the default browser experience unable to read/write/grep/check code.

Root cause:

  • os_check trusted a model-supplied mode argument and defaulted to the full build grant.
  • index.html selected Ollama by default despite the Ollama agents being intentionally chat-only in this PR.

Fix and validation:

  • PR #37 removes the caller-controlled mode parameter from os_check and fixes it to the currently permitted refactor grant.
  • PR #37 restores Anthropic as the web UI default provider.
  • Validation performed: source regression checks, local static web serving check, and browser walkthrough confirming the provider dropdown defaults to Anthropic. lex check . could not run because the lex CLI is not installed in this environment.
Open in Web View Automation 

Sent by Cursor Automation: Quality of PR Lex

Comment thread src/tools/os_check.lex

fn execute(args :: jv.Json) -> [net, io, proc] Result[jv.Json, e.Errors] {
let path := util.field_str_or(args, "path", ".")
let mode := util.field_str_or(args, "mode", "build")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This defaults omitted mode to build, and the model can also explicitly pass mode: "build". In refactor mode that bypasses the new trust-grant check: a Lex file requiring net effects is checked against the full build grant, so forbidden_for_mode returns no violations and the tool reports a pass instead of the expected refactor grant violation. I fixed this in PR #37 by removing the caller-controlled mode from the schema and binding this tool to the refactor grant.

Comment thread src/web/index.html
</label>
<label>Provider
<select id="provider-select">
<option value="ollama" selected>Ollama</option>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This makes the default browser path select Ollama, but this same PR changed every ollama_agent() to tools: [] and max_steps: Some(3). A user opening the web UI and sending a normal build/explore/refactor task gets a chat-only agent that cannot read, write, grep, or run checks. PR #37 restores Anthropic as the default so the initial web experience uses a fully-tooled provider.

- build.lex: add vertex_agent() using vtx.gemini_35_flash() + providers.vertex();
  fix ollama_agent() to use all_tools() and max_steps=20 (was empty tools + 3 steps)
- session.lex: route "vertex" provider tag to vertex_agent() for Build mode
- main.lex: add --vertex flag, run_headless() function for headless/CI use,
  and collect_final_text() that prefers StepDone over TextChunk accumulation

run_headless emits [AGENTCMP_RESULT]\t{"ok":…,"final":…} sentinel so the
agentcmp lex_code adapter can parse results without screen-scraping.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@alpibrupa
alpibrupa merged commit a43b249 into main Jun 9, 2026
1 check failed
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.

1 participant