Skip to content

Studio Code: Show a core block's declared settings in tool results that show the block - #5307

Merged
chubes4 merged 1 commit into
trunkfrom
studio-code/block-settings-in-results
Oct 23, 2026
Merged

chubes4 merged 1 commit into
trunkfrom
studio-code/block-settings-in-results

Conversation

@chubes4

@chubes4 chubes4 commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Related issues

How AI was used in this PR

Claude (via the Pi coding agent in a Roadie session) read the failing eval transcripts, wrote the change and its tests, and ran the evals below. I reviewed the code and the transcripts.

Proposed Changes

When a tool result shows block markup, Studio Code adds one line for each core block type in it, listing the settings that block type declares in the site's own wp-includes/blocks/<block>/block.json. For example:

core/navigation settings, declared in …/wp-includes/blocks/navigation/block.json: ref (number), …, showSubmenuIcon (boolean, default true), submenuVisibility ("hover"|"click"|"always", default "hover"), overlayMenu (string, default "mobile"), …

  • Each block type is described once per turn. Attributes read from the block's HTML (source) are content, so they are left out, along with internal __unstable/__experimental ones.
  • It applies to every Studio tool result, so wp_cli post get, Read and Bash cat all get it.
  • It reads files on disk only. Plugin blocks, remote sites and blocks without a block.json are skipped.

Why. In the template-part eval ("Make the header navigation open its submenus on click instead of on hover"), the failing runs reason "there's no built-in 'open on click' toggle … this requires custom JavaScript", then write a script and CSS into the theme, at 1–1.7M tokens per run. The navigation block declares submenuVisibility: "click". The model doesn't remember it and has no reason to open block.json. Stating the declared settings where the block appears means the model reads them while it is looking at the block.

Testing Instructions

  • npx vitest run apps/cli/ai/tests/block-settings.test.ts: describes the core blocks in a header from their block.json, describes each one once, and leaves out content attributes, closing comments and blocks without a block.json.
  • Eval: template-part-db-override, 6 runs per arm, run against this branch and current trunk (09253bcef) at the same time:
Pass JS workaround Mean tokens Mean tool calls Mean time
This branch 6/6 0 223k 17 53s
Trunk 4/5 1 675k 32 94s

One trunk run stalled at the 420s timeout after 91k tokens without reaching an answer. It is left out above as an infrastructure stall. Counted as a failure, trunk is 4/6.

  • Every branch run's session shows the core/navigation settings line in the post get 5 or Read parts/header.html result, and every branch run set submenuVisibility in the saved header. No branch run wrote JavaScript or read core's navigation/view.js. On trunk, one run wrote a script and another read view.js three times before finding the setting.
  • Regression check: the three other cases that start on a local site, 6 runs per arm:
Case This branch Trunk
global-styles-db-override 6/6, 189k tokens 5/6, 187k tokens
design-system-annotation 6/6, 260k tokens 5/6, 289k tokens
active-site-reused 6/6, 68k tokens 6/6, 66k tokens

Both trunk failures are unrelated to this change: one is a port collision during inspection, the other discarded the saved styles. The settings line appeared in only 1 of these 18 runs (it passed), because these tasks rarely read block markup, so this check shows no harm rather than a gain.

  • Size: replaying 263 earlier sessions that read block markup, the added lines come to a median of ~240 tokens per session (p90 ~460, max ~1.8k).
  • Six runs per arm can't establish a pass-rate gain, so the claim is parity or better on accuracy. The fall in tokens and tool calls is large and consistent across runs.

Pre-merge Checklist

  • Have you checked for TypeScript, React or other console errors?

@chubes4
chubes4 marked this pull request as ready for review October 23, 2026 01:54
@wpmobilebot

Copy link
Copy Markdown
Collaborator

📊 Performance Test Results

Comparing daa71b2 vs trunk

app-size

Metric trunk daa71b2 Diff Change
App Size (Mac) 940.68 MB 940.68 MB +0.00 MB ⚪ 0.0%

site-editor

Metric trunk daa71b2 Diff Change
load 1217 ms 1209 ms 8 ms ⚪ 0.0%

site-startup

Metric trunk daa71b2 Diff Change
siteCreation 7536 ms 7512 ms 24 ms ⚪ 0.0%
siteStartup 4377 ms 4378 ms +1 ms ⚪ 0.0%

Results are median values from multiple test runs.

Legend: 🟢 Improvement (faster) | 🔴 Regression (slower) | ⚪ No change (<50ms diff)

@chubes4
chubes4 merged commit aabc42a into trunk Oct 23, 2026
14 checks passed
@chubes4
chubes4 deleted the studio-code/block-settings-in-results branch October 23, 2026 02:15
chubes4 added a commit that referenced this pull request Oct 23, 2026
…y changes (#5308)

## Related issues

- Of the 120 PRs merged since Oct 1, 20 changed only Studio Code agent
files (`apps/cli/ai/**`, `apps/cli/commands/ai/**`, `scripts/eval/**`).
Each one still waited on desktop E2E and Performance Metrics, the two
slowest jobs (about 17.5 min each on build 23481), even though neither
suite runs agent code.

## How AI was used in this PR

Claude (via the Pi coding agent in a Roadie session) measured job times
from Buildkite logs, classified merged PRs by changed paths, checked
which suites can reach agent code, and wrote the change. I reviewed the
diff and the evidence.

## Proposed Changes

`should-skip-job.sh` gets an `AGENT_PATTERNS` list and an `e2e` job
type:

- **Desktop E2E** (`run-e2e-tests.sh`) now uses `--job-type e2e`: the
`validation` rules, plus a skip when every changed file is an agent
file.
- **Performance Metrics** adds the same agent patterns to its existing
skip list.
- **Lint, Unit Tests and CLI E2E** keep `--job-type validation` and
still run on agent-only PRs.

A skipped job exits 0 the same way the existing docs-only skips do, so
the required statuses still report as passed.

Why these two suites never exercise agent code:

- The desktop E2E sessions launch with `agenticFeaturesEnabled: false`
(`apps/studio/e2e/e2e-helpers.ts`), and no desktop test drives the chat
or Studio Code.
- The metrics suites
(`tools/metrics/tests/{app-size,site-editor,site-startup}`) measure app
size, site editor load and site startup.
- The agent is loaded lazily from `apps/cli/index.ts`
(`cli/commands/ai`) and from `studio mcp`. The one module under
`apps/cli/ai/` used outside the agent, `browser-utils.ts`, is reached
only through URL imports (`data-liberation-client`, `capture-preview`).
The desktop E2E suite doesn't test those, and Unit and CLI E2E still run
on any change to it.

A PR that also touches anything else (`apps/ui`, `packages/common`,
other `apps/cli` code, `package.json`) runs every job as before. One
thing an agent-only PR no longer gets: the app-size line of the
performance comment. `compare-perf` never fails a PR, and dependency
changes still run metrics.

Expected effect on agent-only PRs: the gate drops from about 19 min (p50
of the 39 PR builds since build 23377) to about 10 min, set by CLI E2E
on Windows.

## Testing Instructions

This PR only touches `.buildkite/**`, which the existing rules already
skip, so its own CI doesn't run the new path. To check it locally:

- Real diff: from a checkout of #5307 (`daa71b227`, agent-only), run
`BUILDKITE_PULL_REQUEST=5307 BUILDKITE_PULL_REQUEST_BASE_BRANCH=trunk
.buildkite/commands/should-skip-job.sh --job-type <type>`. Result:
`validation` runs (exit 1), and `e2e` and `metrics` skip (exit 0).
- Stubbed `pr_changed_files` with fixed file lists:

| Changed files | validation | e2e | metrics | build |
|---|---|---|---|---|
| agent only (`apps/cli/ai/**` + tests) | run | skip | skip | run |
| `apps/cli/commands/ai/**` + `scripts/eval/**` | run | skip | skip |
run |
| agent + `apps/cli/commands/site/create.ts` | run | run | run | run |
| agent + `apps/ui/**` | run | run | run | run |
| agent + `packages/common/ai/**` | run | run | run | run |
| `apps/ui/**` only | run | run | run | run |
| docs only | skip | skip | skip | skip |
| `apps/studio/e2e/**` only | run | run | skip | run |

- `bash -n` passes. `shellcheck` reports nothing on the changed lines;
its two findings are on existing lines.

## Pre-merge Checklist

- [x] Lint, Unit Tests and CLI E2E still run on agent-only PRs.
- [x] Mixed PRs run every job as before.
@youknowriad

Copy link
Copy Markdown
Contributor
  • studio mcp doesn't get this. The hook is in the pi runtime's toToolDefinition, so Claude Code and Codex agents never see these lines. Can we move it somewhere studio mcp tool results also pass through? It's important that all fixes we do for Studio Code support all of our surfaces (including CLI, app, the AI plugins and MCP)
  • It's once per session, not once per turn. The tracker is created in createStudioAgentSession, so after a compaction the model may have lost the line and never gets it again. That's probably fine, but the description should say so.

It would also help to know how often the "rebuild a built-in block setting in JS/CSS" pattern shows up in real sessions beyond this eval. That would tell us how much this is worth beyond the one case.

chubes4 added a commit that referenced this pull request Oct 23, 2026
…5333)

## Related issues

- Follows #5307, addressing the review there: the block settings notes
only reached Studio Code, not agents using `studio mcp`.

## How AI was used in this PR

Claude (via the Pi coding agent in a Roadie session) wrote the change
and the test and ran the end-to-end check below. I reviewed the diff and
the results.

## Proposed Changes

#5307 adds the declared settings of each core block a tool result shows
(read from the site's own `wp-includes/blocks/<block>/block.json`). The
notes are wired up in the Pi runtime's `toToolDefinition`, which the MCP
server bypasses: it calls `tool.rawHandler` directly. So Claude Code,
Codex, and the AI plugins never got them.

- **One module for result notes, `cli/ai/result-notes.ts`.**
`createResultNotes()` returns `( sitePath, text ) => notes`: the facts
read from that site about what the result shows, each stated once per
tracker. Block settings are the only kind today; a new kind is added
there and reaches every surface.
- **Both surfaces use it the same way.** Each creates one tracker per
conversation it can see and passes the site it works on:
- Studio Code: one per turn, with the turn's active site (as #5307 did).
- `studio mcp`: one per MCP session, with the site the call names
(`nameOrPath`). A call that names no site, or one that isn't found, gets
no notes.
- The MCP call path moves into `runtimes/mcp/served-tool.ts`
(`runServedTool`); pending work reports and error handling are
unchanged.

Limits:

- MCP clients read theme files with their own Read tool, which never
passes through Studio. Notes only fire for Studio tools (`wp_cli` and
the like), not for files the client reads itself.
- Once per tracker means a note stated early can be lost if the context
is compacted later: within a Studio Code turn (the tracker is created in
`createStudioAgentSession`, which `runAgentSessionTurn` calls, so it is
per turn, not per session), and within an MCP session, whose compaction
Studio can't see.

## Testing Instructions

- `npx vitest run apps/cli/ai/runtimes/mcp`: `served-tool.test.ts`
resolves a real site from a `cli.json` (no mocks): no notes for a call
without a site or with an unknown one, the settings for the named site,
then none on a repeat call in the same session.
- End-to-end, on a throwaway site with an isolated config: built the
CLI, ran `studio mcp` over stdio, and called `wp_cli` with `post get 2
--field=post_content` twice, then `option get blogname`. The first
result had the page content plus:
  ```
core/paragraph settings, declared in
<site>/wp-includes/blocks/paragraph/block.json: dropCap (boolean,
default false), placeholder (string), direction ("ltr"|"rtl").
core/quote settings, declared in
<site>/wp-includes/blocks/quote/block.json: textAlign (string).
  ```
  The repeat call and `option get blogname` had no notes.

## Pre-merge Checklist

- [x] Have you checked for TypeScript, React or other console errors?
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.

3 participants